【问题标题】:3sum(3 sum) if duplicates are allowed3sum(3 sum) 如果允许重复
【发布时间】:2019-06-11 18:27:32
【问题描述】:

与传统的 3sum 问题相比,如果任何三个元素的总和等于 0,则查找所有三元组,我们可以使用任何重复项。 例如,对于输入数组 [-2, -1, 3, 4],(-2, -2, 4) 也是一种解决方案。 (-2 是重复的并且是允许的)。 我的解决方案是将每个元素复制为 3 个副本,然后将修改后的元素视为传统的 3sum 问题。但是这种方法在最坏的情况下会花费 O(2n) 空间。有没有可用的常数空间解决方案?

【问题讨论】:

    标签: algorithm


    【解决方案1】:

    问题有点不清楚,因为您还没有发布您的实际实现。但是,假设 standard O(n^2) implementation 没有散列:

     sort(S);
     for i=0 to n-3 do
        a = S[i];
        start = i+1;
        end = n-1;
        while (start < end) do
           b = S[start];
           c = S[end];
           if (a+b+c == 0) then
              output a, b, c;
               start = start + 1
               end = end - 1
           else if (a+b+c > 0) then
              end = end - 1;
           else
              start = start + 1;
           end
        end
     end
    

    您可以通过将变量start 初始化为i 而不是i+1 来获得解决方案中的重复项。此外,如果您允许最终三元组中的所有元素来自同一个数组元素,则另外将 while 循环条件从 while (start &lt; end) 更改为 while (start &lt;= end)

    【讨论】:

    • 感谢您的解决方案。我想你是对的。我们可以将start 修改为 i 并添加start &lt;= end 以允许重复。顺便说一句,为什么我的问题不清楚?我尽力解释了这一点......
    • @EmersonXu 欢迎您!如果您认为它有用,请随时投票/接受答案。如果您发布了您使用的实际实现,您的问题会更容易回答,因为 3SUM 问题可以通过几种不同的策略来解决。例如,如果您使用散列(这是解决此问题的一种很常见的方法),答案会有所不同。
    【解决方案2】:

    我的解决方案:

    public static List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> resultList = new ArrayList();
        int start1 = 0;
        while (start1 <= nums.length - 1 - 2) {
            int start2 = start1 + 1;
            int end = nums.length - 1;
            while (true) {
                if (start2 >= end) {
                    break;
                }
                int result = nums[start1] + nums[start2] + nums[end];
                if (result == 0) {
                    addToResponse(resultList, nums[start1], nums[start2], nums[end]);
                    do {
                        start2++;
                    } while (start2 < end && nums[start2] == nums[start2 - 1]);
                    do {
                        end--;
                    } while (end > start2 && nums[end] == nums[end + 1]);
                } else if (result > 0) {
                    do {
                        end--;
                    } while (end > start2 && nums[end] == nums[end + 1]);
                } else if (result < 0) {
                    do {
                        start2++;
                    } while (start2 < end && nums[start2] == nums[start2 - 1]);
                }
    
    
            }
            do {
                start1++;
            }
            while (nums[start1] == nums[start1 - 1] && start1 < nums.length-1);
    
        }
        return resultList;
    }
    
    private static void addToResponse(List<List<Integer>> result, int a, int b, int c) {
        result.add(Arrays.asList(a, b, c));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-08
      相关资源
      最近更新 更多