oj-和为定值的子数组-java

Description

Given an array A of size N, find all combination of four elements in the array whose sum is equal to a given value K. For example, if the given array is {10, 2, 3, 4, 5, 9, 7, 8} and K = 23, one of the quadruple is “3 5 7 8” (3 + 5 + 7 + 8 = 23).

Input

The first line of input contains an integer T denoting the no of test cases. Then T test cases follow. Each test case contains two lines. The first line of input contains two integers N and K. Then in the next line are N space separated values of the array.(1<=T<=100;1<=N<=100;-1000<=K<=1000;-100<=A[]<=100)

Output

For each test case in a new line print all the quadruples present in the array separated by space which sums up to value of K. Each quadruple is unique which are separated by a delimeter “$” and are in increasing order.

Sample Input 1

2
5 3
0 0 2 1 1
7 23
10 2 3 4 5 7 8

Sample Output 1

0 0 1 2 $
2 3 8 10 $2 4 7 10 $3 5 7 8 $

原代码来源

njuselw/AdvancedAlgorithm

package org.alphacat.first;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

public class SubarraySumEqualsK {

    private static int NUM_AMOUT = 4;

    //四数之和,求出所有和为target的包含四个元素的子数组
    public static List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> res = new ArrayList<>();

        //如果数组长度不足4,则返回空结果
        if (nums == null || nums.length < NUM_AMOUT) {
            return res;
        }
        Arrays.sort(nums);
        int len = nums.length;
        for (int i = 0; i < len - NUM_AMOUT + 1; i++) {
            //对于重复值,不需要再次计算,最终结果不重复
            if (i > 0 && nums[i] == nums[i - 1]){
                continue;
            }

            //数组升序排序后,当连续四个元素和超过target时,后续不再可能出现和为target的子数组,跳出循环
            if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target){
                break;
            }

            //如果当前元素与最大的三个元素相加结果小于target,也不可能出现包含该元素的最终结果,跳过此次计算
            if (nums[i] + nums[len - 3] + nums[len - 2] + nums[len - 1] < target){
                continue;
            }

            //将四数之和问题转化为三数之和
            for (int j = i + 1; j < len - NUM_AMOUT + 2; j++) {

                //与四数之和问题相同的处理方式
                if (j > i + 1 && nums[j] == nums[j - 1]){
                    continue;
                }

                if (nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target){
                    break;
                }

                if (nums[i] + nums[j] + nums[len - 2] + nums[len - 1] < target){
                    continue;
                }

                //将三数之和问题转化为两数之和,用二分法解决
                int l = j + 1, r = len - 1;
                while (l < r) {
                    int sum = nums[i] + nums[j] + nums[l] + nums[r];

                    //和为target,则将四数加入结果集中
                    if (sum == target) {
                        res.add(Arrays.asList(nums[i], nums[j], nums[l], nums[r]));
                        //跳过重复值,继续寻找下一个解
                        while (l < r && nums[l] == nums[l + 1]){
                            l++;
                        }
                        l++;
                        while (l < r && nums[r] == nums[r - 1]){
                            r--;
                        }
                        r--;
                    } else if (sum > target) {
                        //和大于target,则将right指针左移
                        r--;
                    } else {
                        //和小于target,则将left指针右移
                        l++;
                    }
                }
            }
        }
        return res;
    }


    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            int t = scanner.nextInt();
            for (int i = 0; i < t; i++) {
                int n = scanner.nextInt();
                int target = scanner.nextInt();
                int[] nums = new int[n];
                for (int j = 0; j < n; j++) {
                    nums[j] = scanner.nextInt();
                }
                List<List<Integer>> res = fourSum(nums, target);
                print(res);
            }
        }
    }

    private static void print(List<List<Integer>> res) {
        for (List<Integer> subArr : res) {
            for (Integer element : subArr) {
                System.out.print(element + " ");
            }
            System.out.print("$");
        }
        System.out.println();
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值