【问题标题】:3-Sum algorithm analysis3-Sum算法分析
【发布时间】:2016-11-02 12:36:14
【问题描述】:

我知道解决 3-Sum 问题的两种方法。

问题陈述:

给定一个包含 n 个整数的数组 S,S 中是否存在元素 a、b、c 使得 a + b + c = 0?查找数组中所有唯一的三元组,其总和为零。

解决方案1:使用2指针方法

public List<List<Integer>> threeSum(int[] nums) {
    List<List<Integer>> result = new ArrayList<List<Integer>>();

    if (nums == null || nums.length < 3)
        return result;

    Arrays.sort(nums);

    for (int i = 0; i < nums.length - 2; i++) {
        if (i == 0 || nums[i] > nums[i - 1]) {
            int j = i + 1;
            int k = nums.length - 1;

            while (j < k) {
                if (nums[i] + nums[j] + nums[k] == 0) {
                    List<Integer> l = new ArrayList<Integer>();
                    l.add(nums[i]);
                    l.add(nums[j]);
                    l.add(nums[k]);
                    result.add(l);

                    j++;
                    k--;

                    //handle duplicate here
                    while (j < k && nums[j] == nums[j - 1])
                        j++;
                    while (j < k && nums[k] == nums[k + 1])
                        k--;

                } else if (nums[i] + nums[j] + nums[k] < 0) {
                    j++;
                } else {
                    k--;
                }
            }
        }

    }

    return result;
}

解决方案2:使用地图

public List<List<Integer>> threeSum(int[] nums) {
    HashMap<Integer, Integer> map = new HashMap<>();
    HashMap<String, Integer> map2 = new HashMap<>();
    List<List<Integer>> list = new LinkedList<>();
    for (int i : nums) {
        map.put(i, map.get(i) != null ? map.get(i) + 1 : 1);
    }
    for (int i = 0; i < nums.length - 2; i++) {
        for (int j = i + 1; j < nums.length - 1; j++) {
            int findMe = -(nums[i] + nums[j]);
            Integer count = map.get(findMe);
            if (count != null) {
                if ((count == 1 && nums[i] != findMe && nums[j] != findMe) || (count == 2 && (nums[i]!=nums[j] || nums[j]!=findMe)) || count > 2) {
                    int min = Math.min(findMe, Math.min(nums[i], nums[j]));
                    int max = Math.max(findMe, Math.max(nums[i], nums[j]));
                    if (map2.get(min + "" + max) == null) {
                        map2.put(min + "" + max, max);
                        LinkedList<Integer> li = new LinkedList<>();
                        li.add(min);
                        li.add(-(min + max));
                        li.add(max);
                        list.add(li);
                    }
                }
            }

        }
    }
    return list;
}

上下文:

1)Solution1 -- 解的时间复杂度为 -> O(nlogn) + O(n^2) ~ O(n^2)

2)Solution2 -- 解的时间复杂度为 -> O(n) + O(n^2) + O(k) ~ O(n^2)

我的问题: 两者都是 O(n^2) 算法。然而,对于较大的输入,Solution1 的性能优于 2,但根据时间复杂度分析,Solution2 的性能应该更好。有人可以帮我理解为什么会这样吗?

我正在使用的输入:

[13,14,1,2,-11,-11,-1,5,-1,-11,-9,-12,5,-3,-7,-4,-12,-9,8,-13,-8,2,-6,8,11,7,7,-6,8,-9,0,6,13,-14,-15,9,12,-9,-9,-4,-4,-3,-9,-14,9,-8,-11,13,-10,13,-15,-11,0,-14,5,-4,0,-3,-3,-7,-4,12,14,-14,5,7,10,-5,13,-14,-2,-6,-9,5,-12,7,4,-8,5,1,-10,-3,5,6,-9,-5,9,6,0,14,-15,11,11,6,4,-6,-10,-1,4,-11,-8,-13,-10,-2,-1,-7,-9,10,-7,3,-4,-2,8,-13]

【问题讨论】:

  • “根据时间复杂度分析,Solution2 应该表现得更好”……您为什么认为会这样?我认为您对 O 表示法和时间复杂度有一些基本的误解,但我希望看到您的回答以帮助我了解您的误解所在。
  • 但是对于较大的输入,Solution1 的性能优于 2,但根据时间复杂度分析,Solution2 的性能应该更好 ?能详细点吗?
  • @ajb:我错过了解决方案的性能取决于基于输入的 O(n)+O(k) 和 O(nlog(n)) 的值。谢谢..我相信我迷路了。

标签: java algorithm


【解决方案1】:

您应该明白,渐近分析不会给出准确的时间或空间复杂度。

但是,您是在精确的持续时间内测量这两种解决方案。

提出你的问题,当输入很大时,在解决方案 2 中 O(k) 变得越来越大,这就是为什么用于计算解决方案 2 的时间比解决方案 1 多的原因。

【讨论】:

  • @RMittal:为什么“k”会变大?大 n 的平均值是 ~n^2 还是更高?仅适用于随机数据吗?你的估计是什么?如果 n 增长的数据中没有三元组怎么办?
猜你喜欢
  • 2011-10-29
  • 1970-01-01
  • 2014-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多