我是靠谱客的博主 感动日记本,最近开发中收集的这篇文章主要介绍【算法】剑指 Offer 专项突击版 Day3数组部分【算法】剑指 Offer 专项突击版 Day3数组部分I 【中等】007. 数组中和为 0 的三个数II 【中等】 008. 和大于等于 target 的最短子数组III 【中等】009. 乘积小于 K 的子数组,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
【算法】剑指 Offer 专项突击版 Day3数组部分
题目地址:https://leetcode-cn.com/study-plan/lcof/?progress=wgzvtig
目标:要点总结,分享思路
通俗代码,满足要求快速实现
文章目录
- 【算法】剑指 Offer 专项突击版 Day3数组部分
- I 【中等】007. 数组中和为 0 的三个数
- II 【中等】 008. 和大于等于 target 的最短子数组
- III 【中等】009. 乘积小于 K 的子数组
I 【中等】007. 数组中和为 0 的三个数
难度:普通,双指针题
要点:
- 思路:数组排序后,在不重复要求下,设置起始第一个数base,在剩下数字中通过双指针寻找和为target-base的两个数
- 重点:为什么一定先对数组排序,因为只有排序后才能使用双指针。且先不排序的话,循环中每次寻找也是要排序的,故排序是必需的。(可以先通过暴力遍历思考理解)
这道题想到双指针就可以做出来了,但是加入一些剪枝可以大大降低时间复杂度
剪枝1:如果第一个数字已经成功使用过,就不需要双指针重复找剩下两个数
剪枝2:在有序数组条件下,如果两数最值都不满足target直接更换base进入下一轮寻找
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
if len(nums)<3:return []
ans,ans_set,first_num_set = [],set(),set()
nums.sort()
for i in range(len(nums)-2):
base = nums[i] # 第一个数字
target = 0-base
if base not in first_num_set: # 剪枝1
left,right = i+1,len(nums)-1
if nums[left]+nums[left+1]>target or nums[right] + nums[right-1]<target:
continue # 剪枝2
while left<right:
if nums[left]+nums[right] < target:
left+=1
elif nums[left]+nums[right]>target:
right-=1
else:
if (base,nums[left],nums[right]) not in ans_set:
ans.append([base,nums[left],nums[right]])
ans_set.add((base,nums[left],nums[right]))
first_num_set.add(base)
left+=1
return ans
总结:两数之和、三数之和等问题可以考虑双指针+剪枝解决
II 【中等】 008. 和大于等于 target 的最短子数组
难度:普通,滑动窗口题
要点:两种方法
- 思路:(1)设置双指针,右指针不断向右移,当窗口和>目标值时记录窗口长度并不断移动左指针,时间复杂度 O ( n ) O(n) O(n)
- (2)前缀和+二分查找,因题目中明确数组中均为正数,这样就满足了前缀和递增有序,时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn),题目有这个思考要求,理解就好
- 小技巧:这种最小值长度问题可以先将结果ans设置成数组长度+1,这样后面判断一下就知道ans是否有改变,因为满足条件的最大值长度就是数组长度
滑动窗口版
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
# 滑动窗口——推荐
if not nums:return 0
left,right=0,0
total = 0
ans = len(nums)+1 # 设置成最大长度+1
while right<len(nums):
total+=nums[right]
while total>=target:
ans = min(ans,right-left+1)
total -= nums[left]
left += 1
right+=1
return ans if ans!=len(nums)+1 else 0
前缀和+滑动窗口
图例全部详细请见
【花落&月缺】反正我也没弄白前缀和方法哪里比较好……(T_T)(前缀和、滑动窗口)
这里截一张他的图便于理解
class Solution:
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
# 前缀和 + 二分查找
sums = [0]
ans = len(nums)+1
for i in range(len(nums)):
sums.append(sums[-1]+nums[i])
for i in range(1,len(sums)):
find = target+sums[i-1]
middle = bisect.bisect_left(sums,find)
if middle!=len(sums):
ans = min(middle-i+1,ans)
return ans if ans!=len(nums)+1 else 0
III 【中等】009. 乘积小于 K 的子数组
难度:简单的滑动窗口题
要点:
- 思路:双指针解决滑动窗口问题,窗口不断向右移动,即右指针不断增加,当窗口内乘积大于等于目标k时,缩小窗口,即左指针不断减小
class Solution:
def numSubarrayProductLessThanK(self, nums: List[int], k: int) -> int:
if k<=1: return 0
left,right,ans,multi = 0,0,0,1
while right<len(nums):
multi *= nums[right]
while multi >= k:
multi /= nums[left]
left+=1
ans += right - left+1
right += 1
return ans
最后
以上就是感动日记本为你收集整理的【算法】剑指 Offer 专项突击版 Day3数组部分【算法】剑指 Offer 专项突击版 Day3数组部分I 【中等】007. 数组中和为 0 的三个数II 【中等】 008. 和大于等于 target 的最短子数组III 【中等】009. 乘积小于 K 的子数组的全部内容,希望文章能够帮你解决【算法】剑指 Offer 专项突击版 Day3数组部分【算法】剑指 Offer 专项突击版 Day3数组部分I 【中等】007. 数组中和为 0 的三个数II 【中等】 008. 和大于等于 target 的最短子数组III 【中等】009. 乘积小于 K 的子数组所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复