第六周_A-数组-四数之和

90 阅读1分钟

题目:

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

0 <= a, b, c, d < n

a、b、c 和 d 互不相同

nums[a] + nums[b] + nums[c] + nums[d] == target

你可以按 任意顺序 返回答案 。

public class 四数之和 {

    public static void main(String[] args) {
        int[] nums = {-2,-1,-1,1,1,2,2};
        System.out.println( fourSum(nums, 0));
    }

    public static List<List<Integer>> fourSum(int[] nums, int target) {

        List result = new ArrayList(); 

        if (nums == null || nums.length < 4) {  //nums 为空或者长度小于4直接返回
            return new ArrayList();
        }

        //先排序;这样使用双指针就很方便
        Arrays.sort(nums);
        int b = 0, c = 0, d = 0;
        int nn = nums.length;

        for (int i = 0; i < nn - 3; i++) { //因为总共是四个数字,最后面最少保留三位
            if (i > 0 && nums[i] == nums[i - 1]) {   //排除重复的元素
                continue;
            }
//因为排序得,前面四个都大于目标值了,后面只会更多
            if ((long) nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) {
                break;
            }
//因为排序得,后面四个都小于目标值了,前面只会更小
            if ((long) nums[i] + nums[nn - 3] + nums[nn - 2] + nums[nn - 1] < target) {
                continue;
            }

            for (b = i + 1; b < nn - 2; b++) { //第二层循环(此刻和三数之和一样的)
                if (b > i + 1 && nums[b] == nums[b - 1]) { //防止遍历的元素重复
                    continue;
                }

                c = b + 1;  //左指针
                d = nn - 1; //右指针
                while (c < d) { 
//和小于target,那么左指针需要右移
                    if (nums[i] + nums[b] - target < -(nums[c] + nums[d])) {
                        c++;
                    }
//和大于target,那么右指针需要左移
										else if (nums[i] + nums[b] - target > -(nums[c] + nums[d]))//同上
                    {
                        d--;
                    } else {//值相等了
                        List list = new ArrayList();
                        list.add(nums[i]);
                        list.add(nums[b]);
                        list.add(nums[c]);
                        list.add(nums[d]);
                        result.add(list);
                        while (c < d && nums[c] == nums[c+1]) { //避免重复
                            c++;
                        }
                        c++;
                        while (c < d && nums[d] == nums[d-1]) { //确保nums[d] 改变了
                            d--;
                        }
                        d--;
                    }
                }
            }
        }
        return result;
    }

}

比起三数之和就是外面多了一个循环。

三数之和的关键是去重。如何避免重复结果。使用排序数组加双指针。当前数字和前一个数字比较

四数之和就是在三数之和的基础上,外面再套了一个 for 循环。

一看啥都会,自己写啥也不会。。。