pub fn three_sum(nums: Vec<i32>) -> Vec<Vec<i32>> {
algorithm_2(nums)
}
fn algorithm_2(nums: Vec<i32>) -> Vec<Vec<i32>> {
let mut res: Vec<Vec<i32>> = vec![];
if nums.len() >= 3 {
let mut sorted_nums = nums.clone();
sorted_nums.sort();
let mut i = 0;
while i < sorted_nums.len() - 1 {
let a = sorted_nums[i];
if i > 0 && sorted_nums[i - 1] == sorted_nums[i] {
i += 1;
continue;
}
let mut j = i + 1;
while j < sorted_nums.len() - 1 {
let b = sorted_nums[j];
if a + b > 0 {
break;
}
if i + 1 < j && b == sorted_nums[j - 1] {
j += 1;
continue;
}
let mut start = 0;
let mut end = sorted_nums[(j + 1)..].len() - 1;
while start < end {
let middle = (end + start) / 2;
if sorted_nums[(j + 1)..][middle] < -a - b {
start = middle + 1;
} else {
end = middle;
}
}
let k = j + 1 + start;
let c = sorted_nums[k];
if a + b + c == 0 {
res.push(vec![a, b, c]);
}
j += 1;
}
i += 1;
}
}
res
}
#[allow(dead_code)]
pub fn algorithm_1(mut nums: Vec<i32>) -> Vec<Vec<i32>> {
let mut res = vec![];
let len = nums.len();
nums.sort_unstable();
for i in 0..len {
let left = nums[i];
if i > 0 && nums[i - 1] == left {
continue;
}
let mut middle = i + 1;
let mut right = len - 1;
while middle < right {
let curr_sum = left + nums[middle] + nums[right];
if curr_sum == 0 {
res.push(vec![left, nums[middle], nums[right]]);
middle += 1;
while middle < right && nums[middle - 1] == nums[middle] {
middle += 1;
}
right -= 1;
} else if curr_sum < 0 {
middle += 1;
} else {
right -= 1;
}
}
}
res
}
#[cfg(test)]
mod tests {
use super::three_sum;
#[test]
fn test_three_sum() {
assert_eq!(
vec![vec![-1, -1, 2], vec![-1, 0, 1]],
three_sum(vec![-1, 0, 1, 2, -1, -4])
);
assert_eq!(Vec::<Vec<i32>>::from(vec![]), three_sum(vec![0, 1, 1]));
assert_eq!(vec![vec![0, 0, 0]], three_sum(vec![0, 0, 0]));
assert_eq!(vec![vec![0, 0, 0]], three_sum(vec![0, 0, 0, 0]));
}
}