嵌套循环复杂性

时间:2014-12-04 11:29:01

标签: algorithm list loops time-complexity

我有几个不同大小的列表,列表的每个索引都包含一个键和一个对象:list1.add(' Key',obj)。

列表全部排序。

我的目标是遍历列表并使用密钥将列表2,3,4或n中的一个或多个项目匹配到mainList中的项目。

目前我做的事情是:

for i to list1 size
   for j to list2 size
   if list1[i] = list2[j]
      do stuff 

当我循环浏览I时,使用布尔值使用if current!= previous check快速退出,并且我从列表中删除对象,我从中取出。

它工作正常,但我现在有另一个我需要匹配的列表,之后可能还有另外n个列表。这些清单的大小不同。

我可以看到的两个选项是在内部列表发生变化的情况下多次重复上面的代码段 - 我不喜欢这种方法。

另一个选择是扩展上面的内容,一旦内部循环完成,移动到下一个:

  for i to list1 size
       for j to list2 size
       if list1[i] = list2[j]
          do stuff 
       for k to list2 size
       if list1[i] = list2[k]
          do stuff 

我想我认为第二个更有效但我不确定是正确的。还有,有更好的方法吗?

感谢您的任何建议/帮助。

1 个答案:

答案 0 :(得分:1)

如果列表都已排序,那么您只需要迭代每个列表一次;在主列表的每次迭代中,遍历辅助列表(从先前保存的索引开始,初始化为0),直到找到其值大于主列表的当前值的索引,保存此索引,然后继续下一个次要名单。

Array<Integer> indices = new Array(n-1); // indices for every list except list1
for(int i = 0; i < indices.size; i++) {
  indices[i] = 0;
}

for(int i = 0; i < list1.size; i++) {
  Value curVal = list1[i];
  while(indices[0] < list2.size && list2[indices[0]] <= curVal) {
    if(list2[indices[0]] == curVal) {
      // do stuff on list2[indices[0]]
    }
    indices[0]++;
  }
  while(indices[1] < list3.size && list3[indices[1]] < curVal) {
    if(list3[indices[1]] == curVal) {
      // do stuff on list3[indices[1]]
    }
    indices[1]++;
  }
  // etc
}

您可以使用包含列表及其当前索引的ListIterator之类的内容来避免复制粘贴;然后在主循环的每次迭代中,您将遍历ListIterators列表而不是复制粘贴的代码块

public class ListIterator {
  int index = 0;
  List<Value> list;
  Value curVal() {
    return list[index];
  }
  boolean hasNext() {
    return (index < list.size);
  }
}

List<ListIterator> iterators;
for(int i = 0; i < list1.size; i++) {
  Value curVal = list1[i];
  for(int j = 0; j < iterators.size; j++) {
    ListIterator iterator = iterators[j];
    while(iterator.hasNext() && iterator.curVal() <= curVal) {
      if(iterator.curVal() == curVal) {
        // do something with iterator.curVal()
      }
      iterator.index++;
    }
  }
}

这是时间复杂度O(n),其中n是所有列表的长度之和


编辑:如果通过<=比较密钥很困难,那么您可以使用Set实施。将List1密钥添加到Set,然后迭代检查集合成员资格的剩余列表。

Set<String> set = new Set(List1);
Array<List> lists = new Array();
// add lists to Array<List>

for(int i = 0; i < lists.size; i++) {
  List currentList = lists[i];
  for(int j = 0; j < currentList.size; j++) {
    if(set.contains(currentList[j]) {
      // do something
    }
  }
}