1.贪心算法
贪心算法是每一小步都选最优,从而导致结果最优
贪心算法基本都是常识问题,并且和其他混合在一起。
就想刚刚我做了一道题,做完之后,我满脸问号,我这是用了贪心?没感觉
所以不用太多想贪心的问题,正常做就好。
2.简单中等题目(455、376、53、122、55、1005、134、860、406、452)
455. 分发饼干 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
g.sort()
s.sort()
res=0
#将饼干从小到大依次发给同学,如果小于同学的胃口不给,再在下面找到一个大的给。
#哎哎有贪心的感觉了
for i in s:
if res< len(g) and i>=g[res]:res+=1
return res
376. 摆动序列 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def wiggleMaxLength(self, nums: List[int]) -> int:
cursub, res = 0, 1
for i in range(len(nums)-1):
suber = nums[i+1]-nums[i] #cursub代表选定的数,如果与他的乘积大于1 不选
if cursub*suber<=0 and suber!=0:
res+=1
cursub=suber #前一个差数
return res
53. 最大子数组和 - 力扣(LeetCode) (leetcode-cn.com)
我发现贪心的每道题都不一样,每道题都有他的独到之处,很考验观察能力。
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
#连续的子数组 ,如果连续数组相加为负的,那么再相加,只会连累后面的数组,所以要从新开始
count=0
res=-float(inf)
for i in range(len(nums)):
count+=nums[i]
if count> res: res=count
if count<=0 :count=0 #如果前面数相加为负的,从新开始,conut清零
return res
122. 买卖股票的最佳时机 II - 力扣(LeetCode) (leetcode-cn.com)
贪心啊贪心,难的还是数学想法,难喽
class Solution:
def maxProfit(self, prices: List[int]) -> int:
#两天相差小于0的不要 只要大于0的
res= 0
for i in range(1,len(prices)):
res+= max(prices[i]-prices[i-1],0)
return res
55. 跳跃游戏 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def canJump(self, nums: List[int]) -> bool:
'''
#用curval表示 某个位置值和 curval-1 最大一个
#如果curval 在某一位小于0 说明跳不过去
curval=1
for i in nums:
if curval-1 <0: return False
curval = max(curval-1,i)
return True
'''
#反过来想 可以用curval 表示某个位置 i+num[i] 和curval 最大值
#如果他大于nums长度减-1 说明能够到达最后
curval = i=0
while i<= curval:
curval = max(i+nums[i],curval)
if curval >=len(nums)-1:return True
i+=1
return False
55. 跳跃游戏 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def jump(self, nums: List[int]) -> int:
#
jumpval=0
start, ender, res =0, 1, 0
while ender<len(nums):
for i in range(start,ender):
if i+nums[i]>= jumpval: jumpval = i+nums[i] # 能跳到最远的距离
start=ender #下一次起跳点范围开始的格子
ender=jumpval+1 #下一次起跳点范围结束的格子
res+=1 #跳跃次数
return res
1005. K 次取反后最大化的数组和 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
'''
nums.sort()
res=0
for i in range(len(nums)):
if k>0:
if nums[i]<0:
k-=1
res-=nums[i]
elif k%2:
if i>0 and -nums[i-1]<nums[i]:
res+=2*nums[i-1]
res+=nums[i]
else:
res-=nums[i]
k=0
else:res+=nums[i]
else:res+=nums[i]
if k and k%2:res+=2*nums[-1]
return res
'''
#自己想法还是太复杂了
#直接用绝对值的排序
nums.sort(key=abs,reverse=True) #按照绝对值 将nums排序 这个对最后k在负值没有取完有好处
res=0
for i in range(len(nums)):
if k>0 and nums[i]<0:
nums[i]*=-1
k-=1
if k>0 and k%2:nums[-1]*=-1
return sum(nums)
134. 加油站 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
#result = gas- cost
#如果所有的result和为大于0 说明可以走的回去
#从哪里开始,可以用i=0 试探找到最小值点 如果这个点小于0 就从i+1 开始
minres =float(inf)
res= resindex =0
for i in range(len(gas)):
res += gas[i] - cost[i]
if res< minres:
minres=res
resindex=i #保存最小情况索引
if res<0 : return -1
else:
if minres>=0: return 0
else:return resindex+1
860. 柠檬水找零 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def lemonadeChange(self, bills: List[int]) -> bool:
#5 不需要 10 需要前一个5 20需要前面右1个10和一个5
num5=0
num10=0
for i in bills:
if not i-5: num5+=1
elif not i-10:
num10+=1
num5-=1
else:
if num10-1<0:num5-=2 #这里用了贪心,优先给10元的
else:num10-=1
num5-=1
if num5<0 or num10<0:return False
return True
406. 根据身高重建队列 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
#首先按照身高从高到低排序
people.sort(key = lambda x:(-x[0],x[1])) #首先按照身高排序 先按照身高从大到小,如果身高相同,在按照k从到大排列
res=[]
#然后从这个序列依次取出,按照k的值插入 因为身高低的不会影响后面的k的值
for i in people: res.insert(i[1],i)
return res
452. 用最少数量的箭引爆气球 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def findMinArrowShots(self, points: List[List[int]]) -> int:
points.sort()
#选中一个点xend 看下一个是否在这个范围内,直至不能满足要求
fxend=points[0][1]
res=1
for i in points[1:]:
if i[0]>fxend:
fxend=i[1]
res+=1
else:
if i[1]<fxend: fxend=i[1]
return res
3.困难题目(135)
135. 分发糖果 - 力扣(LeetCode) (leetcode-cn.com)
两次贪心策略
一次是从左到右遍历,只比较右边孩子评分比左边大的情况。
一次是从右到左遍历,只比较左边孩子评分比右边大的情况。
每次用py做完都想说,python yyds。
class Solution:
def candy(self, ratings: List[int]) -> int:
#分两次 一次从左向右遍历, 保证右边大于的左边 只要右边大于左边 res[i]=res[i-1]+1
#另外一次从右向左遍历,保证左边大于右边 只要左边大于右边 res[i]=res[i+1]+1
#但是要和第一次遍历情况中和,也就是两个都要包含 所以取最大值
res =[1 for _ in ratings]
for i in range(1,len(ratings)): #从左向右遍历
if ratings[i]>ratings[i-1]:
res[i]=res[i-1]+1
for i in range(len(ratings)-2,-1,-1): #从右向左遍历
if ratings[i]>ratings[i+1]:
res[i]=max(res[i+1]+1,res[i])
return sum(res)
4.总结
感觉我再做贪心算法之类的题,我就要疯掉了,虽然做出来感觉不难,但是去想的过程太煎熬了,就是因为没有固定的格式。。。
好吧,还有10道左右,明天再给自己一天时间把。