以下代码的复杂性

时间:2016-07-24 08:15:38

标签: java algorithm performance

我接到了以下任务:

鉴于 - 2名单。第一个列表的大小是N1,第二个列表的大小是N2。每个列表都没有相同的元素。 编写一个代码,使用第一个和第二个列表中的元素创建一个新列表。该列表也不应具有相同的元素。 还要估算代码的复杂程度。

我写了以下代码:

public class Lists {    
    static ArrayList<Integer> getNewList(ArrayList<Integer> list1, 
                                         ArrayList<Integer> list2) {
        ArrayList<Integer> tmp = new ArrayList<>();
        for (Integer i : list1) {
            tmp.add(i);
        }
        for (Integer i : list2) {
            if (!list1.contains(i)) 
                tmp.add(i);
        }
        return tmp;
    }

    public static void main(String[] args) { 
        Integer[] arr1 = {1, 2, 3, 14, 15, 16};        
        Integer[] arr2 = {3, 6, 7, 8, 14};
        ArrayList<Integer> list1 = new ArrayList<>(Arrays.asList(arr1));
        ArrayList<Integer> list2 = new ArrayList<>(Arrays.asList(arr2));
        for (Integer i : getNewList(list1, list2)) {
            System.out.print(i + " ");
        }
    }
}

并说getNewList方法的执行时间与N1 * N2成正比。作为回复,我收到以下内容,没有任何解释 - &#34;你错了,这段代码的复杂性不是N1 * N2&#34;。

那么有人能说出正确的答案吗?并解释如何确定复杂性?

4 个答案:

答案 0 :(得分:9)

代码的复杂性为user/add.html,但您可以使用O(N1*N2)确定哪些数字出现在两个列表中,从而做得更好:

HashSet

这会为您提供static ArrayList<Integer> getNewList(ArrayList<Integer> list1, ArrayList<Integer> list2) { ArrayList<Integer> tmp = new ArrayList<>(); HashSet<Integer> dups = new HashSet<>(); tmp.addAll(list1); dups.addAll(list1); for (Integer i : list2) { if (!dups.contains(i)) tmp.add(i); } return tmp; } 的运行时间,因为在O(N1+N2)中插入和查找需要预计O(1)次。

答案 1 :(得分:3)

我在这里也肯定会看到O(N1 * N2)的复杂性。我猜你的教授忽略了以下contains电话的费用:

for (Integer i : list2) {
    if (!list1.contains(i)) 
        tmp.add(i);
}
ArrayList上的

contains复杂度为O(N)。由于您的循环列表2也是O(N),因此最终会得到O(N1 * N2)

答案 2 :(得分:3)

嗯,你问题的简短答案是:复杂度是N1 +(N2 * N1)/ 2 + N3(新列表的大小),应该是O(N1 * N2)

故障:

        Line line = new Line() { Stroke = Brushes.Blue};
        Binding binding = new Binding("ActualWidth");
        binding.RelativeSource = new RelativeSource() { Mode=RelativeSourceMode.FindAncestor, AncestorType=typeof(TextBlock) };
        BindingOperations.SetBinding(line, Line.X2Property, binding);

        LogTB.Inlines.Add(line);
for (Integer i : list1) {
  tmp.add(i);
} 
-> clearly, this is N1

在main中你有一个循环,从0迭代到N3(这是新List的长度)

所以,总的来说你得到的是N1 +(N2 * N1)/ 2 + N3,它应该是O(N1 * N2)

答案 3 :(得分:2)

感谢@ Slanec的解释,我在JDK中重新检查了contains(Object obj)的实现,发现它如下所示

public boolean contains(Object obj) {
    return indexOf(obj) >= 0;
}

public int indexOf(Object obj) {
    if (obj == null) {
        for (int i = 0; i < size; i++)
            if (elementData[i] == null)
                return i;

    } else {
        for (int j = 0; j < size; j++)
            if (obj.equals(elementData[j]))
                return j;

    }
    return -1;
}

显然,contains(Object obj)的时间复杂度是O(n)。(我认为它最初是O(1))

因此代码的时间复杂度应该是 O(N1 * N2 ),而不是 O(n )。