详细见:leetcode.com/problems/4sum/
Java Solution: github
package leetcode;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class P018_4SumEqualsTarget {
public static void main(String[] args) {
// System.out.println(new Solution3().threeSum(new int[] {-4, -1, -1, 0, 1, 2}, -1, 0));
// System.out.println(new Solution3().threeSum(new int[] {-2, 0, 0, 2, 2}, -1, 0));
System.out.println(new Solution3().fourSum(new int[] {1, 0, -1, 0, -2, 2}, 0));
System.out.println(new Solution3().fourSum(new int[] {-2, 2, 2, 2, 2, 2}, 4));
System.out.println(new Solution3().fourSum(new int[] {2, 2, 2, 2, 2, 2, 4, 0}, 8));
// Node node = new Node(4, 3, 2, 1);
// Set<Node> set = new HashSet<Node>();
// set.add(node);
// node = new Node(4, 3, 1, 2);
// set.add(node);
// System.out.println(set.size());
}
/*
* 106 ms
* 6.18%
* O(N^3)
*/
static class Solution1 {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> ans = new LinkedList<List<Integer>>();
if (nums == null || nums.length < 4)
return ans;
Arrays.sort(nums);
for (int i = 0; i != nums.length; i ++) {
if (i != 0 && nums[i] == nums[i - 1])
continue;
List<List<Integer>> temp = threeSum(nums, i, target - nums[i]);
Iterator<List<Integer>> it = temp.iterator();
while (it.hasNext()) {
List<Integer> list = it.next();
list.add(nums[i]);
ans.add(list);
}
}
return ans;
}
List<List<Integer>> threeSum(int[] nums, int bomb, int target) {
List<List<Integer>> ans = new LinkedList<List<Integer>>();
int i = 0, j = 0, k = 0;
for (i = bomb + 1; i != nums.length; i ++) {
if (i != 0 && nums[i] == nums[i - 1] && (i != bomb + 1)) continue;
j = i + 1; k = nums.length - 1;
while (j < k) {
int sum = nums[i] + nums[j] + nums[k];
if (sum == target) {
List<Integer> list = new LinkedList<Integer>();
list.add(nums[i]); list.add(nums[j]); list.add(nums[k]);
ans.add(list);
do {
j ++;
} while (j != nums.length && nums[j] == nums[j - 1]);
do {
k --;
} while (k != -1 && nums[k] == nums[k + 1]);
} else if (sum > target) {
do {
k --;
} while (k != -1 && nums[k] == nums[k + 1]);
} else {
do {
j ++;
} while (j != nums.length && nums[j] == nums[j - 1]);
}
}
}
return ans;
}
}
/*
* 87 ms
* 11.81%
* O(N^3)
*/
static class Solution2 {
List<List<Integer>> ans = new LinkedList<List<Integer>>();
public List<List<Integer>> fourSum(int[] nums, int target) {
if (nums == null || nums.length < 4)
return ans;
Arrays.sort(nums);
for (int i = 0; i != nums.length; i ++) {
if (i != 0 && nums[i] == nums[i - 1])
continue;
threeSum(nums, i, target - nums[i]);
}
return ans;
}
void threeSum(int[] nums, int bomb, int target) {
int i = 0, j = 0, k = 0;
for (i = bomb + 1; i != nums.length; i ++) {
if (i != 0 && nums[i] == nums[i - 1] && (i != bomb + 1)) continue;
j = i + 1; k = nums.length - 1;
while (j < k) {
int sum = nums[i] + nums[j] + nums[k];
if (sum == target) {
List<Integer> list = new LinkedList<Integer>();
list.add(nums[i]); list.add(nums[j]);
list.add(nums[k]); list.add(nums[bomb]);
ans.add(list);
do {
j ++;
} while (j != nums.length && nums[j] == nums[j - 1]);
do {
k --;
} while (k != -1 && nums[k] == nums[k + 1]);
} else if (sum > target) {
do {
k --;
} while (k != -1 && nums[k] == nums[k + 1]);
} else {
do {
j ++;
} while (j != nums.length && nums[j] == nums[j - 1]);
}
}
}
}
}
/*
* 采用HashMap的方法来进行计算
* 光荣TLE
*/
static class Solution3 {
public List<List<Integer>> fourSum(int[] nums, int target) {
List<List<Integer>> ans = new LinkedList<List<Integer>>();
if (nums == null || nums.length < 4)
return ans;
HashMap<Integer, HashSet<Node>> map = new HashMap<Integer, HashSet<Node>>();
HashSet<Node> ansset = new HashSet<Node>();
HashMap<Integer, Integer> nums_map = new HashMap<Integer, Integer>();
for (int i = 0; i != nums.length; i ++) {
if (nums_map.containsKey(nums[i]))
nums_map.put(nums[i], nums_map.get(nums[i]) + 1);
else
nums_map.put(nums[i], 1);
for (int j = i + 1; j != nums.length; j ++) {
int sum = nums[i] + nums[j];
if (map.containsKey(sum)) {
map.get(sum).add(new Node(nums[i], nums[j]));
} else {
HashSet<Node> set = new HashSet<Node>();
set.add(new Node(nums[i], nums[j]));
map.put(sum, set);
}
}
}
for (int k : map.keySet()) {
if (map.containsKey(target - k)) {
HashSet<Node> set1 = map.get(k);
HashSet<Node> set2 = map.get(target - k);
for (Node node1 : set1) {
for (Node node2 : set2) {
nums_map.put(node1.a, nums_map.get(node1.a) - 1);
nums_map.put(node1.b, nums_map.get(node1.b) - 1);
nums_map.put(node2.a, nums_map.get(node2.a) - 1);
nums_map.put(node2.b, nums_map.get(node2.b) - 1);
if (nums_map.get(node1.a) > -1 && nums_map.get(node1.b) > -1 &&
nums_map.get(node2.a) > -1 && nums_map.get(node2.b) > -1) {
ansset.add(new Node(node1.a, node1.b, node2.a, node2.b));
}
nums_map.put(node1.a, nums_map.get(node1.a) + 1);
nums_map.put(node1.b, nums_map.get(node1.b) + 1);
nums_map.put(node2.a, nums_map.get(node2.a) + 1);
nums_map.put(node2.b, nums_map.get(node2.b) + 1);
}
}
}
}
for (Node node : ansset) {
List<Integer> list = new LinkedList<Integer>();
list.add(node.a);
list.add(node.b);
list.add(node.c);
list.add(node.d);
ans.add(list);
}
return ans;
}
}
static class Node {
int a, b, c, d;
public Node (int a, int b) {
this.a = a;
this.b = b;
this.c = Integer.MAX_VALUE;
this.d = Integer.MAX_VALUE;
}
public Node (int a, int b, int c, int d) {
int temp = 0;
if (a > b) {
temp = a;
a = b;
b = temp;
}
if (c > d) {
temp = c;
c = d;
d = temp;
}
this.a = Math.min(a, c);
this.d = Math.max(b, d);
c = this.a == a ? c : a;
b = this.d == d ? b : d;
if (b < c) {
this.b = b;
this.c = c;
} else {
this.b = c;
this.c = b;
}
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Node) {
Node o = (Node) obj;
return this.a == o.a && this.b == o.b && this.c == o.c && this.d == o.d;
} else {
return false;
}
}
@Override
public int hashCode() {
return a * 11 + b * 22 + c * 33 + d * 44;
}
}
}
C Solution: github
/*
url: leetcode.com/problems/4sum/
36ms 45.28%
*/
#include <stdio.h>
#include <stdlib.h>
//[l, r]
int partition(int* a, int l, int r) {
int t = *(a + l);
while (l < r) {
while (l < r && *(a + r) >= t) r --;
*(a + l) = *(a + r);
while (l < r && *(a + l) <= t) l ++;
*(a + r) = *(a + l);
}
*(a + l) = t;
return l;
}
//[l, r)
void quick_sort(int* a, int l, int r) {
int p = 0;
if (l < r) {
p = partition(a, l, r - 1);
quick_sort(a, l, p);
quick_sort(a, p + 1, r);
}
}
struct list {
int a[4];
struct list *next;
};
void free_list(struct list * head) {
struct list * next = head;
while (next != NULL) {
head = next->next;
free(next);
next = head;
}
}
int** fourSum(int* nums, int numsSize, int target, int* returnSize) {
int ** answer = NULL;
struct list * head = NULL, * next = NULL, * temp = NULL;
int i = 0, j = 0, l = 0, r = 0, sum = 0, count = 0;
int * answer_temp = NULL;
quick_sort(nums, 0, numsSize);
for (i = 0; i < numsSize; i ++) {
if (i != 0 && *(nums + i - 1) == *(nums + i))
continue;
for (j = i + 1; j < numsSize; j ++) {
if (j != i + 1 && *(nums + j - 1) == *(nums + j))
continue;
l = j + 1;
r = numsSize - 1;
while (l < r) {
sum = *(nums + i) + *(nums + j) + *(nums + l) + *(nums + r);
if (sum == target) {
temp = (struct list *) malloc(sizeof(struct list));
temp->next = NULL;
temp->a[0] = *(nums + i);
temp->a[1] = *(nums + j);
temp->a[2] = *(nums + l);
temp->a[3] = *(nums + r);
if (NULL == head) {
head = temp;
next = temp;
} else {
next->next = temp;
next = temp;
}
count ++;
do {
l ++;
} while (l < r && nums[l - 1] == nums[l]);
do {
r --;
} while (l < r && nums[r + 1] == nums[r]);
} else if (sum > target) {
do {
r --;
} while (l < r && nums[r + 1] == nums[r]);
} else {
do {
l ++;
} while (l < r && nums[l - 1] == nums[l]);
}
}
}
}
answer = (int **) malloc(sizeof(int *) * count);
next = head;
for (i = 0; i < count; i ++) {
answer_temp = (int *) malloc(sizeof(int) * 4);
answer_temp[0] = next->a[0];
answer_temp[1] = next->a[1];
answer_temp[2] = next->a[2];
answer_temp[3] = next->a[3];
*(answer + i) = answer_temp;
next = next->next;
}
free_list(head);
*(returnSize) = count;
return answer;
}
int main() {
int nums[] = {-1,0,1,2,-1,-4};
//int nums[] = {1, 1, 1, 1, 1, 1};
int numsSize = 6;
int target = -1;
int returnSize[] = {0};
int ** a = fourSum(nums, numsSize, target, returnSize);
int i = 0;
printf("answer length is %d\r\n", *(returnSize));
for (i = 0; i < *(returnSize); i ++)
free(*(a + i));
free(a);
return 0;
}
Python Solution: github
#coding=utf-8
'''
url: leetcode.com/problems/4sum/
@author: zxwtry
@email: zxwtry@qq.com
@date: 2017年3月28日
@details: Solution1: TLE
@details: Solution2: 745ms 53.60%
'''
class Solution1(object):
def search(self, a, n, s, t, i, I, p, pi):
if pi == 4:
#Python2 LeetCode Judge is Python2
#if s == t: a.append(p[:])
#Python3
if s == t: a.append(p.copy())
return
for j in range(i, I):
if j != i and n[j - 1] == n[j]: continue
p[pi] = n[j]
self.search(a, n, s + n[j], t, j + 1, I, p, pi + 1)
def fourSum(self, n, t):
"""
:type n: List[int]
:type t: int
:rtype: List[List[int]]
"""
a = []
nn = 0 if n == None else len(n)
if nn == 0: return a
n.sort(key=None, reverse=False)
self.search(a, n, 0, t, 0, nn, [0] * 4, 0)
return a
class Solution2(object):
def fourSum(self, n, target):
a = []
nn = 0 if n == None else len(n)
if nn == 0: return a
n.sort(key=None, reverse=False)
for i in range(nn):
if i != 0 and n[i - 1] == n[i]: continue
for j in range(i + 1, nn):
if j != i + 1 and n[j - 1] == n[j]: continue
l, r, t = j + 1, nn - 1, target-n[i]-n[j]
while l < r:
s = n[l] + n[r]
if s == t:
a.append([n[i], n[j], n[l], n[r]])
while True:
l += 1
if l >= r or n[l-1] != n[l]: break
while True:
r -= 1
if l >= r or n[r+1] != n[r]: break
elif s < t:
l += 1
else:
r -= 1
return a
if __name__ == "__main__":
n = [1,0,-1,0,-2,2]
t = 0
print(Solution2().fourSum(n, t))