forked from aylei/leetcode-rust
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathn0018_4sum.rs
86 lines (81 loc) · 2.61 KB
/
n0018_4sum.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/**
* [18] 4Sum
*
* Given an array nums of n integers and an integer target, are there elements a, b, c, and d in nums such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
*
* Note:
*
* The solution set must not contain duplicate quadruplets.
*
* Example:
*
*
* Given array nums = [1, 0, -1, 0, -2, 2], and target = 0.
*
* A solution set is:
* [
* [-1, 0, 0, 1],
* [-2, -1, 1, 2],
* [-2, 0, 0, 2]
* ]
*
*
*/
pub struct Solution {}
// submission codes start here
// TODO: change to faster N^3 solution... maybe
// this is a N^2 * logN solution, but slower than N^3 solution
// iterate all combinations and the sum of 2 elements, then use one-round hash
use std::collections::BTreeMap;
use std::collections::HashSet;
impl Solution {
pub fn four_sum(nums: Vec<i32>, target: i32) -> Vec<Vec<i32>> {
if nums.len() < 4 { return vec![] }
let mut set: HashSet<Vec<i32>> = HashSet::new();
let mut map: BTreeMap<i32, Vec<(usize, usize)>> = BTreeMap::new();
// collect two-sums in asc order, store the index to avoid single number reusing
for i in 0..(nums.len() - 1) {
for j in (i + 1)..nums.len() {
map.entry(nums[i] + nums[j]).or_insert(Vec::new()).push((i, j));
}
}
// find results
for (&sum, pairs) in map.iter() {
// avoid duplicates
if sum > target / 2 { break; }
match map.get(&(target - sum)) {
None => continue,
// 2-sum + 2-sum == target, then all the possible combination
// (without index conflicts) is our answer
Some(subs) => {
for pair in pairs.iter() {
for sub in subs.iter() {
if sub.0 == pair.0 || sub.0 == pair.1 || sub.1 == pair.0 || sub.1 == pair.1 {
continue
}
let mut vec = vec![nums[pair.0], nums[pair.1], nums[sub.0], nums[sub.1]];
vec.sort();
set.insert(vec);
}
}
}
}
}
set.into_iter().collect()
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
// TODO: build a macro for arbitrary match
#[test]
#[ignore]
fn test_18() {
assert_eq!(Solution::four_sum(vec![1, 0, -1, 0, -2, 2], 0), vec![
vec![-1, 0, 0, 1],
vec![-2, 0, 0, 2],
vec![-2, -1, 1, 2]
]);
}
}