008_三数之和
知识点:双指针
LeetCode第十五题:https://leetcode-cn.com/problems/3sum/submissions/
讲道理,代码中哈希版本的解法和双指针解法都是O n平方,为何运行结果时长却差这么远,可能理论上的时间复杂度和实际测试用例的运行时长不一定成比例吧,毕竟一些细节优化优化,剪剪枝,往往也能得到不少的提升。不过,只要运行结果时间不要相差太远就行。
语言:GoLang
// 双指针:O(n^2),仅30~40ms
func threeSum(nums []int) [][]int {
length := len(nums)
if length < 3 {
return [][]int{}
}
sort.Ints(nums)
result := [][]int{}
for i := 0; i < length; i++ {
l, r := i + 1, length - 1
if 0 < i && nums[i] == nums[i - 1] {
continue
}
if nums[i] > 0 {
break
}
for l < r {
sum := nums[i] + nums[l] + nums[r]
if sum == 0 {
result = append(result, []int{nums[i], nums[l], nums[r]})
for l < length - 1 && nums[l] == nums[l + 1] {
l++
}
for 0 < r && nums[r] == nums[r - 1] {
r--
}
l++
r--
} else if sum > 0 {
r--
} else if sum < 0 {
l++
}
}
}
return result
}
// 哈希表:O(n^2),900ms ???
func threeSum_(nums []int) [][]int {
length := len(nums)
if length < 3 {
return [][]int{}
}
helpMap := map[int]int{}
for i := 0; i < length; i++ {
helpMap[0 - nums[i]] = i
}
visit := map[[3]int]bool{}
result := [][]int{}
for i := 0; i < length; i++ {
for j := i + 1; j < length; j++ {
if index, ok := helpMap[nums[i] + nums[j]]; ok {
target := []int{nums[i], nums[j], nums[index]}
if index != i && index != j && !hasVisited(visit, target) {
result = append(result, target)
}
}
}
}
return result
}
func hasVisited(visit map[[3]int]bool, target []int) bool {
sort.Ints(target)
key := [3]int{target[0], target[1], target[2]}
if _, ok := visit[key]; ok {
return true
}else {
visit[key] = true
return false
}
}
// 朴素解法:o(n^3)