- Published on
Three Sum Review
- Authors
- Name
- DP Piggy
- @xiaozhudxiaozhu
思路分析: 整体思路为:算出两数之和, 然后利用两数之和算出三数之和
java
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
// 将数组排序
Arrays.sort(nums);
int n = nums.length;
List<List<Integer>> res = new LinkedList<>();
for (int i = 0; i < n; i++) {
List<List<Integer>> twoSumList = twoSum(nums, i + 1, 0 - nums[i]);
if (!twoSumList.isEmpty()) {
for (List<Integer> list : twoSumList) {
list.add(nums[i]);
res.add(list);
}
}
// 排除重复
// i++ 之后 由于外层循环 i++, 所以下一次i是在 i + 2
// 即为重复项的下一项
while (i < n - 1 && nums[i] == nums[i + 1]) {
i++;
}
}
return res;
}
public List<List<Integer>> twoSum(int[] nums, int start, int target) {
int low = start;
int high = nums.length - 1;
List<List<Integer>> res = new LinkedList<>();
while (low < high) {
int left = nums[low];
int right = nums[high];
int sum = left + right;
if (sum < target) {
while (low < high && nums[low] == left) {
// 排除重复项
low++;
}
} else if (sum > target) {
while (low < high && nums[high] == right) {
// 排除重复项
high--;
}
} else {
List<Integer> list = new LinkedList<>();
list.add(left);
list.add(right);
res.add(list);
// 排除重复项
while (low < high && nums[low] == left) {
low++;
}
while (low < high && nums[high] == right) {
high--;
}
}
}
return res;
}
}
go
func threeSum(nums []int) [][]int {
n := len(nums)
sort.Ints(nums)
var res [][]int
for i := 0; i < n; i++ {
twoSumList := twoSum(nums, i+1, 0-nums[i])
for _, el := range twoSumList {
el = append(el, nums[i])
res = append(res, el)
}
for i < n-1 && nums[i] == nums[i+1] {
i++
}
}
return res
}
func twoSum(nums []int, start int, target int) [][]int {
low := start
high := len(nums) - 1
var res [][]int
for low < high {
left := nums[low]
right := nums[high]
sum := left + right
if sum < target {
// 1 1 2 3 4 5
// 1 + 5 = 6
for low < high && nums[low] == left {
low++
}
} else if sum > target {
for low < high && nums[high] == right {
high--
}
} else {
list := []int{left, right}
res = append(res, list)
for low < high && nums[low] == left {
low++
}
for low < high && nums[high] == right {
high--
}
}
}
return res
}
rust
use std::cmp::Ordering;
impl Solution {
pub fn three_sum(mut nums: Vec<i32>) -> Vec<Vec<i32>> {
let n = nums.len();
nums.sort();
let mut res = vec![];
let mut i = 0;
while i < n {
let two_sum_list = Self::two_sum(&nums, i + 1, 0 - nums[i]);
for mut el in two_sum_list {
el.push(nums[i]);
res.push(el);
}
let mut j = i;
while j < n - 1 && nums[j] == nums[j + 1] {
j += 1;
}
i = j + 1;
}
res
}
pub fn two_sum(nums: &[i32], start: usize, target: i32) -> Vec<Vec<i32>> {
let mut low = start;
let mut high = nums.len() - 1;
let mut res = vec![];
while low < high {
let left = nums[low];
let right = nums[high];
let sum = left + right;
match sum.cmp(&target) {
Ordering::Less => while low < high && nums[low] == left { low += 1; },
Ordering::Greater => while low < high && nums[high] == right { high -= 1; },
Ordering::Equal => {
res.push(vec![left, right]);
while low < high && nums[low] == left { low += 1; };
while low < high && nums[high] == right { high -= 1; };
}
}
}
res
}
}