雜湊與雙指標兩種思路實現,關鍵在去重
題面
n
個整數的陣列 nums
,判斷 nums
中是否存在三個元素 a,b,c
,使得 a + b + c = 0
?請你找出所有和為 0
且不重複的三元組。
雜湊
- 充分複用排序,雜湊計數資訊
- 三數之和,三數要麼不同,要麼有相同
- 計數區分可否相同,雜湊裁定第三數是否存在,排序縮小其範圍
func threeSum(nums []int) [][]int {
sort.Ints(nums)
length := len(nums)
if length < 3 || nums[length-1] < 0 || nums[0] > 0 {
return nil
}
ans := [][]int{}
hash := make(map[int]int)
for _, v := range nums {
hash[v]++
}
for i:=0;i<length;i += hash[nums[i]] {
for l:= i+hash[nums[i]];l<length && nums[l] < -nums[i]-nums[l];l +=hash[nums[l]]{ // 三數不同
if _, ok := hash[-nums[i]-nums[l]];ok{
ans = append(ans, []int{nums[i],nums[l],-nums[i]-nums[l]})
}
}
if hash[nums[i]] > 1 { // 三數存在相同
if _,ok := hash[-nums[i]*2];ok {
if nums[i] == 0 && hash[0] < 3 { continue }
ans = append(ans, []int{nums[i],nums[i], -nums[i]*2})
}
}
}
return ans
}
雙指標
- 排序+迴圈遍歷去重
func threeSum(nums []int) [][]int { sort.Ints(nums) length := len(nums) if length < 3 || nums[length-1] < 0 || nums[0] > 0 { return nil } ans := [][]int{} for i:=0;i<length;i++ { if i==0 || nums[i] != nums[i-1] { // 非重複項為首 for l,r:= i+1,length-1;l<r;{ if nums[l]+nums[r] == -nums[i] { // 左右邊界同時收縮 ans = append(ans,[]int{nums[i],nums[l],nums[r]}) for l<r && nums[l] == nums[l+1]{l++} // 去重 for l<r && nums[r] == nums[r-1]{r--} // 去重 l++ r-- }else if nums[l]+nums[r] < -nums[i] { // 左邊界收縮 l++ }else{ // 右邊界收縮 r-- } } } } return ans }
二合一
- 化為兩數之和,雜湊計數跳躍
- 維護解空間的有序性,化繁為簡,相同或不同
func threeSum(nums []int) [][]int { sort.Ints(nums) length := len(nums) if length < 3 || nums[length-1] < 0 || nums[0] > 0 { return nil } ans := [][]int{} hash := make(map[int]int) for _, v := range nums { hash[v]++ } for i:=0;i<length;i+=hash[nums[i]] { for l,r:= i+hash[nums[i]],length-1;l<r;{ if nums[l]+nums[r] == -nums[i] { // 左右邊界同時收縮 ans = append(ans,[]int{nums[i],nums[l],nums[r]}) l +=hash[nums[l]] r -=hash[nums[r]] }else if nums[l]+nums[r] < -nums[i] { // 左邊界收縮 l +=hash[nums[l]] }else{ // 右邊界收縮 r -=hash[nums[r]] } } if hash[nums[i]] > 1 { // 存在相同元素 if _, ok := hash[-nums[i]*2];ok && nums[i] <= -nums[i]*2{ // 保證有序去重 if nums[i] == 0 && hash[0] < 3 {continue} // 排除特例 ans = append(ans, []int{nums[i],nums[i],-nums[i]*2}) } } } return ans }
本作品採用《CC 協議》,轉載必須註明作者和本文連結