List Intersection

ぐ巨炮叔叔 提交于 2019-12-11 07:27:28

问题


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 solve this problem better than O(m*n)?


回答1:


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;



回答2:


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.




回答3:


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).



来源:https://stackoverflow.com/questions/6099899/list-intersection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!