functwoSum(numbers []int, target int) []int { var left, right int = 0, len(numbers) - 1// 初始化左右指针 var res []int// 初始化结果数组 for left < right{ sum := numbers[left] + numbers[right] if sum == target{ res = append(res, []int{left+1,right+1}...) left++ right-- }elseif sum < target{ left++ }else{ right-- } } return res }
functhreeSum(nums []int) [][]int { // 先排序 sort.Ints(nums) var ans [][]int for i := 0; i < len(nums) - 2; i++{ var now = nums[i] if i > 0 && nums[i] == nums[i-1]{ continue }
// 开始双指针 j := i + 1 k := len(nums) - 1 for j < k{ sum := now + nums[j] + nums[k] if sum == 0{ ans = append(ans, []int{now, nums[j], nums[k]}) j++ // 遇到相同的就跳过 for j < k && nums[j] == nums[j-1]{ j++ } k-- // 遇到相同的就跳过 for j < k && nums[k] == nums[k+1]{ k-- } }elseif sum < 0{ j++ }else{ k-- } } } return ans }
functhreeSumClosest(nums []int, target int)int { // 先排序 sort.Ints(nums) var ans int = 100001 for i := 0; i < len(nums) - 2; i++{ var now = nums[i] if i > 0 && nums[i] == nums[i-1]{ continue }
// 开始双指针 j := i + 1 k := len(nums) - 1 for j < k{ poor := now + nums[j] + nums[k] - target if poor == 0{ return target }elseif poor < 0{ // 搞到正数会不会好一点 j++ }else{ // 小一点会不会更好 k-- }
if abs(poor) < abs(ans - target){ ans = poor + target } } } return ans }
funcabs(i int)int{ if i < 0{ return -i } return i }
funcfourSum(nums []int, target int) (ans [][]int) { sort.Ints(nums) n := len(nums) for i := 0; i < n - 3; i++{ x := nums[i] // 重复数字跳过 if i > 0 && x == nums[i-1]{ continue }
for j := i + 1; j < n - 2; j++{ y := nums[j] // 重复数字跳过 if j > i + 1 && y == nums[j-1]{ continue } // 双指针 z := j + 1 k := n - 1 for z < k{ sum := x + y + nums[z] + nums[k] if sum == target{ ans = append(ans, []int{x, y, nums[z], nums[k]}) // 跳过重复数字 z++ for z < k && nums[z] == nums[z-1]{z++} k-- for z < k && nums[k] == nums[k+1]{k--} }elseif sum < target{ z++ }else{ k-- } } } } return ans }
LeetCode 611
思路
三角形边要满足的条件是:
两边之和大于第三边
两边之差小于第三边
即:
a + b > c
a + c > b
b + c > a
当 a b c 满足 1 < a < b < c 时,只需要 a + b > c,那么这三条边就可以构成一个三角形。
数组是按照递增顺序排序的,如果上述条件成立,那么 j++ 直到 j = k - 1 式子nums[j] + nums[k] > nums[i] 都是成立的。所以使 ans += k - j,然后 k–。
否则 j++ 继续寻找合适的边
j < k 时停止查找
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
functriangleNumber(nums []int)int { sort.Ints(nums) var ans int for i := 2; i < len(nums); i++{ j := 0 k := i - 1 for j < k{ if nums[j] + nums[k] > nums[i]{ // k - j 都是符合条件的 ans += k - j k-- }else{ j++ } } } return ans }
LeetCode 2824
思路
唯一要注意的就是找到符合条件的 left right 时,ans 要加上 right - left 的值。
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
funccountPairs(nums []int, target int)int { sort.Ints(nums) var ans int var left, right = 0, len(nums) - 1 for left < right{ sum := nums[left] + nums[right] if sum >= target{ // 太大了 right-- }else{ ans += right - left left++ } } return ans }
LeetCode 11
思路
这题有个很关键的点在于:最低的边决定面积的大小(木桶效应)。
面积等于: min(h1,h2) * (right - left)
通过上述式子,我们移动 right 和 left 时,(right - left) 都会减小 1,仅考虑这个因素,那么它们谁往中间移动都是无关紧要的。影响面积大小的因素就是 min(h1, h2)。如果:
funcmaxArea(height []int)int { var left, right = 0, len(height) - 1 var ans int for left < right{ w := right - left h := min(height[left], height[right]) temp := w * h ans = max(ans, temp) if h == height[left]{ left++ }else{ right-- } } return ans }
funcmax(x, y int)int{ if x < y{ return y } return x }
funcmin(x, y int)int{ if x < y{ return x } return y }
funcminSubArrayLen(target int, nums []int)int { var low int var sum, ans int = 0, 100001 for fast := 0; fast < len(nums); fast++{ sum += nums[fast] // 舍弃前边的直到不符合条件(滑动窗口) for low < len(nums) && sum >= target{ ans = min(ans, fast - low + 1) sum -= nums[low] low++ } } // 如果是初始值表示没有满足条件的长度 if ans == 100001{ ans = 0 } return ans }
funcmin(x, y int)int{ if x < y{ return x } return y }
LeetCode 713
思路
本题最重要的一行代码就是:
ans += fast - low + 1
这里引用官解评论区中的一个评论来说,当我们遍历到 fast 时,我们需要计算包含最右边数字的子串数量,因为左侧数字子串的数量我们已经统计过了。举例来说就是 [10, 5],当我们遍历到 5 时,如果 5 是满足加入条件,只需要加入 [10, 5] 和 [5]。而这部分的数量正好是 r - l + 1。
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13
funcnumSubarrayProductLessThanK(nums []int, k int)int { var low int var mul, ans int = 1, 0 for fast := 0; fast < len(nums); fast++{ mul *= nums[fast] for low <= fast && mul >= k{ mul /= nums[low] low++ } ans += fast - low + 1 } return ans }
funclongestOnes(nums []int, k int)int { var low, ans, cnt int for fast := range nums{ if nums[fast] == 0{ cnt++ } for cnt > k { if nums[low] == 0{ cnt-- } low++ } ans = max(ans, fast - low + 1) } return ans }
funcmax(x, y int)int{ if x < y{ return y } return x }
funcbalancedString(s string)int { m := len(s) / 4 var cnt = make(map[byte]int) for i := range s{ cnt[s[i]]++ }
if cnt['Q'] == m && cnt['W'] == m && cnt['E'] == m && cnt['R'] == m{ // 如果四个字母的出现次数都等于 m,直接返回 return0 }
var low,ans = 0, len(s) for fast := range s{ cnt[s[fast]]-- for cnt['Q'] <= m && cnt['W'] <= m && cnt['E'] <= m && cnt['R'] <= m{ // 如果四个字母的出现次数都小于等于 m ans = min(ans, fast - low + 1) cnt[s[low]]++ low++ } } return ans }
funcmin(x, y int)int{ if x < y{ return x } return y }
funcminOperations(nums []int, x int)int { // 转换成找一个满足和 target 的最长子数组 var target = -x for i := range nums{ target += nums[i] } if target < 0{ return-1 } var ans,low,sum int = -1, 0, 0 for fast := range nums{ sum += nums[fast] for sum > target{ sum -= nums[low] low++ } if sum == target{ ans = max(ans, fast - low + 1) } }
if ans == -1{ return ans } returnlen(nums) - ans }
funcmax(x,y int)int{ if x < y{ return y } return x }