1. 程式人生 > >18. 4Sum

18. 4Sum

continue i+1 數組 color ray 技術 目標 [0 targe

一、描述

  1、題目

    技術分享

2、題意

    給一個數組,和一個目標數,求滿足數組中的4個數的和為目標數的所有組合!

二、解答

    1、思路:

    數組排序後,依次從前向後取一個數 num[i], target - num[i] 即為下標 i 後面 三數之和。再依次遍歷 i 後的數,將目標數記為 target - num[i] - num[j],化為兩數之和。最終采用2變量分別指向 j 後一個數與數組最後一個數,相對遍歷,查出滿足的所有情況!

public List<List<Integer>> fourSum(int[] nums, int target) {
         
         Arrays.sort(nums);
         
         List
<List<Integer>> resultList = new ArrayList<List<Integer>>(); List<Integer> targetList = null; int tempTarget = 0, maxLen = nums.length - 1; for(int i = 0; i <= maxLen; i++) { if(i == 0 || nums[i] != nums[i-1]) for(int
j = i + 1; j <= maxLen; j++) { tempTarget = (target - nums[i] - nums[j]); int low = j+1; int high = maxLen; while(low < high) { if(nums[low] + nums[high] == tempTarget) { targetList
= Arrays.asList(nums[i], nums[j], nums[low], nums[high]); resultList.add(targetList); low++; high--; } else if(nums[low] + nums[high] < tempTarget) low++; else high--; } } } List newList = new ArrayList(new HashSet(resultList)); return newList; }

    2、改進

      查看到大神回答,可以過濾更多的不符合情況,來增加遍歷的速度!測試的速度提高了一半多!

public class Solution {
    public  List<List<Integer>> fourSum(int[] nums, int target) {
        
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        int len = nums.length;
        if(nums == null || len < 4)
            return res;
        
        Arrays.sort(nums);
        
        int max = nums[len-1];
        
        if(4*nums[0] > target || 4*max < target)
            return res;
        
        int z;
        for(int i = 0; i < len; i++) {
            z = nums[i];
            if(i > 0 && z == nums[i-1])
                continue;
            if(z + 3*max < target) 
                continue;
            if(4*z > target)
                break;
            if(4*z == target) {
                if(i + 3 < len && nums[i+3] == z)
                    res.add(Arrays.asList(z, z, z, z));
                break;
            }
            
            threeSumForFourSum(nums, target - z, i+1, len - 1, res, z);
        }
        
        return res;
    }

    private  void threeSumForFourSum(int[] nums, int target, int low, int high,
            List<List<Integer>> fourSumList, int z) {
        
        if(low + 1 >= high) 
            return;
        int max = nums[high];
        if(3 * nums[low] > target || 3 * max < target)
            return;
        
        int z1;
        for(int i = low; i < high - 1; i++) {
            z1 = nums[i];
            if( i > low && z1 == nums[i-1])
                continue;
            if(z1 + 2*max < target)
                continue;
            if(3*z1 > target)
                break;
            
            if(3 * z1 == target) {
                if(i + 1 < high && nums[i+2] == z1)
                    fourSumList.add(Arrays.asList(z1, z1, z1, z));
                break;
            }
            
            twoSumForFourSum(nums, target - z1, i + 1, high, fourSumList, z1, z);
        }
    }

    private  void twoSumForFourSum(int[] nums, int target, int low, int high,
            List<List<Integer>> fourSumList, int z1, int z2) {

        if(low >= high)
            return;
        
        if(2 * nums[low] > target || 2 * nums[high] < target)
            return;
        
        int i = low, j = high, sum, x;
        while(i < j) {
            sum = nums[i] + nums[j];
            if(sum == target) {
                fourSumList.add(Arrays.asList(z1, z2, nums[i], nums[j]));

                x = nums[i];
                while(++i < j && x == nums[i])
                    ;
                x = nums[j];
                while(i < --j && x == nums[j]) 
                    ;
            }
            if(sum < target)
                ++i;
            if(sum > target)
                j--;
        }
    }
}

三、總結

    在遍歷嵌套層次較多的情況下,用 if 判斷過濾不符條件,可以明顯提高運行速度!

18. 4Sum