zoukankan      html  css  js  c++  java
  • [LeetCode] 18. 4Sum 四数之和

    Given an array nums of n integers and an integer target, are there elements abc, and d in nums such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

    Note:

    The solution set must not contain duplicate quadruplets.

    Example:

    Given array nums = [1, 0, -1, 0, -2, 2], and target = 0.
    
    A solution set is:
    [
      [-1,  0, 0, 1],
      [-2, -1, 1, 2],
      [-2,  0, 0, 2]
    ]

    给一个含有n个整数的数组S, 找出所有不重复的4个数和等于target的所有解。

    解法1:Two pointers, 跟3Sum差不多,只是扩展到4个数字的和。还是按照3Sum的解法,先排序,只是在外面套一层循环,相当于求n次3Sum,用set()去重。3Sum的时间复杂度是O(n^2),所以总时间复杂度O(n^3)。但这个时间复杂度高,用时太长。

    解法2:Hash map, 以空间换时间,首先建立一个Hash map,key值为数组中每两个元素的和,对应的value为这两个元素的下标组成的元组num[p]+num[q]] : (p,q) ,pairs元组不一定是唯一的。如对于num=[1,2,3,2]来说,dict={3:[(0,1),(0,3)], 4:[(0,2),(1,3)], 5:[(1,2),(2,3)]}。这样就可以检查target-key这个值在不在dict的key值中,如果target-key在dict中并且下标符合要求,那么就找到了这样的一组解。用set()去重。

    Java: 2 pointers

    public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) {
        Arrays.sort(num);  
        HashSet<ArrayList<Integer>> hashSet = new HashSet<ArrayList<Integer>>();
        ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
      
        for (int i = 0; i < num.length; i++) {
            for (int j = i + 1; j < num.length; j++) {
                int k = j + 1;
                int l = num.length - 1;
      
                while (k < l) {
                    int sum = num[i] + num[j] + num[k] + num[l];
      
                    if (sum > target) {
                        l--;
                    } else if (sum < target) {
                        k++;
                    } else if (sum == target) {
                        ArrayList<Integer> temp = new ArrayList<Integer>();
                        temp.add(num[i]);
                        temp.add(num[j]);
                        temp.add(num[k]);
                        temp.add(num[l]);
      
                        if (!hashSet.contains(temp)) {
                            hashSet.add(temp);
                            result.add(temp);
                        }
      
                        k++;
                        l--;
                    }
                }
            }
        }
      
        return result;
    }
    

    Java:

    public class Solution {
            int len = 0;
            public List<List<Integer>> fourSum(int[] nums, int target) {
                len = nums.length;
                Arrays.sort(nums);
                return kSum(nums, target, 4, 0);
            }
           private ArrayList<List<Integer>> kSum(int[] nums, int target, int k, int index) {
                ArrayList<List<Integer>> res = new ArrayList<List<Integer>>();
                if(index >= len) {
                    return res;
                }
                if(k == 2) {
                	int i = index, j = len - 1;
                	while(i < j) {
                        //find a pair
                	    if(target - nums[i] == nums[j]) {
                	    	List<Integer> temp = new ArrayList<>();
                        	temp.add(nums[i]);
                        	temp.add(target-nums[i]);
                            res.add(temp);
                            //skip duplication
                            while(i<j && nums[i]==nums[i+1]) i++;
                            while(i<j && nums[j-1]==nums[j]) j--;
                            i++;
                            j--;
                        //move left bound
                	    } else if (target - nums[i] > nums[j]) {
                	        i++;
                        //move right bound
                	    } else {
                	        j--;
                	    }
                	}
                } else{
                    for (int i = index; i < len - k + 1; i++) {
                        //use current number to reduce ksum into k-1sum
                        ArrayList<List<Integer>> temp = kSum(nums, target - nums[i], k-1, i+1);
                        if(temp != null){
                            //add previous results
                            for (List<Integer> t : temp) {
                                t.add(0, nums[i]);
                            }
                            res.addAll(temp);
                        }
                        while (i < len-1 && nums[i] == nums[i+1]) {
                            //skip duplicated numbers
                            i++;
                        }
                    }
                }
                return res;
            }
        }  

    Python: Two pointers, Time:  O(n^3), Space: O(1)

    # Two pointer solution. (1356ms)
    class Solution(object):
        def fourSum(self, nums, target):
            """
            :type nums: List[int]
            :type target: int
            :rtype: List[List[int]]
            """
            nums.sort()
            res = []
            for i in xrange(len(nums) - 3):
                if i and nums[i] == nums[i - 1]:
                    continue
                for j in xrange(i + 1, len(nums) - 2):
                    if j != i + 1 and nums[j] == nums[j - 1]:
                        continue
                    sum = target - nums[i] - nums[j]
                    left, right = j + 1, len(nums) - 1
                    while left < right:
                        if nums[left] + nums[right] == sum:
                            res.append([nums[i], nums[j], nums[left], nums[right]])
                            right -= 1
                            left += 1
                            while left < right and nums[left] == nums[left - 1]:
                                left += 1
                            while left < right and nums[right] == nums[right + 1]:
                                right -= 1
                        elif nums[left] + nums[right] > sum:
                            right -= 1
                        else:
                            left += 1
            return res
    

    Python: HashMap, Time:  O(n^2 * p), Space: O(n^2 * p)

    # Hash solution. (224ms)
    class Solution2(object):
        def fourSum(self, nums, target):
            """
            :type nums: List[int]
            :type target: int
            :rtype: List[List[int]]
            """
            nums, result, lookup = sorted(nums), [], collections.defaultdict(list)
            for i in xrange(0, len(nums) - 1):
                for j in xrange(i + 1, len(nums)): 
                    is_duplicated = False
                    for [x, y] in lookup[nums[i] + nums[j]]:
                        if nums[x] == nums[i]:
                            is_duplicated = True
                            break
                    if not is_duplicated:
                        lookup[nums[i] + nums[j]].append([i, j])
            ans = {}
            for c in xrange(2, len(nums)):
                for d in xrange(c+1, len(nums)):
                    if target - nums[c] - nums[d] in lookup:
                        for [a, b] in lookup[target - nums[c] - nums[d]]:
                            if b < c:
                                quad = [nums[a], nums[b], nums[c], nums[d]]
                                quad_hash = " ".join(str(quad))
                                if quad_hash not in ans:
                                    ans[quad_hash] = True
                                    result.append(quad)
            return result
    

    Python:

    def fourSum(self, nums, target):
        def findNsum(nums, target, N, result, results):
            if len(nums) < N or N < 2 or target < nums[0]*N or target > nums[-1]*N:  # early termination
                return
            if N == 2: # two pointers solve sorted 2-sum problem
                l,r = 0,len(nums)-1
                while l < r:
                    s = nums[l] + nums[r]
                    if s == target:
                        results.append(result + [nums[l], nums[r]])
                        l += 1
                        while l < r and nums[l] == nums[l-1]:
                            l += 1
                    elif s < target:
                        l += 1
                    else:
                        r -= 1
            else: # recursively reduce N
                for i in range(len(nums)-N+1):
                    if i == 0 or (i > 0 and nums[i-1] != nums[i]):
                        findNsum(nums[i+1:], target-nums[i], N-1, result+[nums[i]], results)
    
        results = []
        findNsum(sorted(nums), target, 4, [], results)
        return results  

    C++: 2 pointers

    class Solution {
    public:
        vector<vector<int> > fourSum(vector<int> &nums, int target) {
            set<vector<int> > res;
            sort(nums.begin(), nums.end());
            for (int i = 0; i < int(nums.size() - 3); ++i) {
                for (int j = i + 1; j < int(nums.size() - 2); ++j) {
                    int left = j + 1, right = nums.size() - 1;
                    while (left < right) {
                        int sum = nums[i] + nums[j] + nums[left] + nums[right];
                        if (sum == target) {
                            vector<int> out;
                            out.push_back(nums[i]);
                            out.push_back(nums[j]);
                            out.push_back(nums[left]);
                            out.push_back(nums[right]);
                            res.insert(out);
                            ++left; --right;
                        } else if (sum < target) ++left;
                        else --right;
                    }
                }
            }
            return vector<vector<int> > (res.begin(), res.end());
        }
    };
    

    类似题目:

    [LeetCode] 454. 4Sum II 四数之和II

    All LeetCode Questions List 题目汇总

      

  • 相关阅读:
    fedora上部署ASP.NET——(卡带式电脑跑.NET WEB服务器)
    SQL Server 请求失败或服务未及时响应。有关详细信息,请参见事件日志或其它适合的错误日志
    8086CPU的出栈(pop)和入栈(push) 都是以字为单位进行的
    FTP 服务搭建后不能访问问题解决
    指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配
    Linux 安装MongoDB 并设置防火墙,使用远程客户端访问
    svn Please execute the 'Cleanup' command. 问题解决
    .net 操作MongoDB 基础
    oracle 使用绑定变量极大的提升性能
    尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题。
  • 原文地址:https://www.cnblogs.com/lightwindy/p/8496546.html
Copyright © 2011-2022 走看看