[LeetCode] 4Sum 四数之和解法(本算法n数之和都能解)

四数之和 

给一个包含n个数的整数数组S,在S中找到所有使得和为给定整数target的四元组(a, b, c, d)。

 注意事项

四元组(a, b, c, d)中,需要满足a <= b <= c <= d

答案中不可以包含重复的四元组。

例如,对于给定的整数数组S=[1, 0, -1, 0, -2, 2] 和 target=0. 满足要求的四元组集合为:

(-1, 0, 0, 1)

(-2, -1, 1, 2)

(-2, 0, 0, 2)


    这是一道数组求和的问题,看了网上很多解答的算法,比较流行的是一个先排序,然后选两个数字,接着后面用两个指针分别指向剩下数组开始和结束,逐步移向中间求和看和targer是否相等,但是这样的算法感觉实现起来太不优雅了。想到一个深度遍历的算法,可以到达同样的效果,而且以后无论多少个数求和,都能解决。代码如下:

 public ArrayList> fourSum(int[] numbers, int target) {
		Arrays.sort(numbers);
		ArrayList> ret = new ArrayList<>();
		dfs(ret, new ArrayList(), numbers, 0, target);
		return ret;
	}
	
	private void dfs(ArrayList> ret, ArrayList condidate, int[] numbers, int curIndex,
			int target) {
	    // 以后求n数和,只要改这里就能解决,比如4改为3,改为5
		if (condidate.size() == 4) {
			int total = getSum(condidate);
			if (total == target) {
				ret.add(new ArrayList<>(condidate));
			}
			return;
		}
		if (curIndex > numbers.length - 1) {
			return;
		}
		for (int i = curIndex; i < numbers.length; i++) {
		    // 如果是一样的数字,直接忽略,否则会有重复的答案
			if (i != curIndex && numbers[i] == numbers[i - 1]) {
				continue;
			}
			condidate.add(numbers[i]);
			// 如果已经大于target,并且当前数字大于0,再循环加下去已经没有意义了,因为只会更大,直接return
			if (getSum(condidate) > target && numbers[i] > 0) {
				if (!condidate.isEmpty()) {
					condidate.remove(condidate.size() - 1);
				}
				return;
			}
			dfs(ret, condidate, numbers, i + 1, target);
			if (!condidate.isEmpty()) {
				condidate.remove(condidate.size() - 1);
			}
		}
	}

	private int getSum(ArrayList condidate) {
		int total = 0;
		for (Integer num : condidate) {
			total += num;
		}
		return total;
	}




你可能感兴趣的:(算法)