List Intersection
I want to compute a list "intersection". The problem is:
L1 = [1, 0, 2, 3, 1 , 3, 0, 5]
L2 = [3, 5]
Then the result will be
L3 = [0, 0, 0, 1, 0, 1, 0, 1]
Then i will convert this result in a byte. In this case will be 21 in decimal format.
I want to make in delphi and I need this do efficiently. Is there a way to 开发者_StackOverflowsolve this problem better than O(m*n)?
Here's a function that should do what you want. I defined L2
as a set instead of an array since you said all your values will fit in a Byte
. Its complexity is O(n); checking set membership runs in constant time. But since the result needs to fit in a byte, the length of L1
must be bound at 8, so the complexity of this function is actually O(1).
function ArrayMembersInSet(const L1: array of Byte; const L2: set of Byte): Byte;
var
i: Integer;
b: Byte;
begin
Assert(Length(L1) <= 8,
'List is to long to fit in result');
Result := 0;
for i := 0 to High(L1) do begin
b := L1[i];
if b in L2 then
Result := Result or (1 shl (7 - i));
end;
end;
Rob's answer will work for this specific case. For a more general case where two lists have to be compared, you can do it in O(m+n) time if both lists are sorted. (Or O(n log n) time if you have to sort them first, but that's still a lot faster than O(m*n).)
The basic List Comparison algorithm looks like this:
procedure ListCompare(list1, list2: TWhateverList; [Add extra params here]);
var
i, j: integer;
begin
i := 0;
j := 0;
while (i < list1.Count) and (j < list2.Count) do
begin
if list1[i] < list2[j] then
begin
//handle this appropriately
inc(i);
end
else if list1[i] > list2[j] then
begin
//handle this appropriately
inc(j);
end
else //both elements are equal
begin
//handle this appropriately
inc(i);
inc(j);
end;
end;
//optional cleanup, if needed:
while (i < list1.Count) do
begin
//handle this appropriately
inc(i);
end;
while (j < list2.Count) do
begin
//handle this appropriately
inc(j);
end;
end;
This can be customized for a whole bunch of tasks, including list intersection, by changing the "handle this appropriately" places, and it's guaranteed to not run for more steps than are in both lists put together. For list intersection, have the equals case add the value to some output and the other two do nothing but advance the counters, and you can leave off the optional cleanup.
One way to use this algorithm is to make the extra params at the top into function pointers and pass in routines that will handle the appropriate cases, or nil to do nothing. (Just make sure you check for nil before invoking them if you go that route!) That way you only have to write the basic code once.
Well no matter what you will need to visit each element in each list comparing the values. A nested loop would accomplish this in O(n^2) and the conversion should just be local work.
EDIT: I noticed that you want a better runtime than O(n*m).
精彩评论