leetcode 贪心_Leetcode-贪心

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

解:

dfs,找到所有可能买入卖出情况,O(2n),搜索的限制条件太少,递归层数太多,肯定超时。

class Solution:

def maxProfit(self, prices: List[int]) -> int:

def dfs(prices, s):

if s > len(prices):

return 0

res = 0

for start in range(s, len(prices)):

max_profit = 0

for end in range(start+1, len(prices)):

if prices[start] < prices[end]: # 如果当前的卖出高于买入,就卖出,从当前end卖出的整体收益等于这次卖出的收益+从下一天开始继续操作的收益

profit = prices[end] - prices[start] + dfs(prices, end+1)

if profit > max_profit:

max_profit = profit # 记录从start买入,不同点卖出的最大收益

if max_profit > res:

res = max_profit # 记录从不同点买入的最大收益

return res

return dfs(prices, 0)

贪心,因为可以多次买入卖出,找出那些共同使得利润最大化的买入及卖出价格即可。只要第二天股价涨了,就在当天买入第二天卖掉。O(N)

class Solution:

def maxProfit(self, prices: List[int]) -> int:

if not prices:

return 0

p = 0

for i in range(1, len(prices)):

cur = prices[i] - prices[i-1]

if cur > 0:

p += cur

return p if p else 0

动态规划,只要第二天涨了,卖了就赚了,否则就持有。记录每一天的状态记录最大利润,状态转移方程为:dp[i] = dp[i-1]  if prices[i] <= prices[i-1] else dp[i-1] + prices[i] -prices[i-1],遍历一次即可,O(n)

def maxProfit(self, prices: List[int]) -> int:

if not prices:

return 0

n = len(prices)

dp = [0]*n

for i in range(1, n):

if prices[i] > prices[i-1]:

dp[i] = dp[i-1] + prices[i] -prices[i-1]

else:

dp[i] = dp[i-1]

return max(dp)

但其实不需要单独开一个数组,因为只要所有状态中最大的即可。写出来发现跟贪心就一样了。

class Solution:

def maxProfit(self, prices: List[int]) -> int:

if not prices:

return 0

n = len(prices)

res = 0

for i in range(1, n):

if prices[i] > prices[i-1]:

res = res + prices[i] - prices[i-1]

else:

continue

return res

在柠檬水摊上,每一杯柠檬水的售价为 5 美元。

顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。

每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。

注意,一开始你手头没有任何零钱。

如果你能给每位顾客正确找零,返回 true ,否则返回 false 。

提示:

0 <= bills.length <= 10000

bills[i] 不是 5 就是 10 或是 20

解:

模拟过程,贪心策略在于要尽可能多留5元在手里

class Solution:

def lemonadeChange(self, bills: List[int]) -> bool:

if not bills:

return True

five, ten = 0, 0

for bill in bills:

if bill == 5: # 如果付5元,不用管

five += 1

elif bill == 10: # 如果付10元,手里必须要有5元可以找

if not five:

return False

ten += 1

five -= 1

elif bill == 20: # 如果付20元,手里必须要有3张5元或1张5元1张10元可以找,贪心策略在于要尽可能的多留5元在手上

if ten and five: # 先走5+10的方案

ten -= 1

five -= 1

elif five >= 3:

five -= 3

else:

return False

return True

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

注意:

你可以假设胃口值为正。

一个小朋友最多只能拥有一块饼干。

解:

贪心,先把g和s都sort一下。对g和s分别维护一个索引。如果当前sj可以满足gi,res、i、j都加1;否则的话饼干的索引+1(换个更大的饼干)。如果最大的sj都比gi小,说明后面的gi已经不可能被满足,直接返回结果。

class Solution:

def findContentChildren(self, g: List[int], s: List[int]) -> int:

if not g or not s:

return 0

g.sort()

s.sort()

i, j, res = 0, 0, 0

while i < len(g) and j < len(s):

if s[-1] < g[i]:

return res

if s[j] >= g[i]:

res += 1

i += 1

j += 1

else:

j += 1

return res

机器人在一个无限大小的网格上行走,从点 (0, 0) 处开始出发,面向北方。该机器人可以接收以下三种类型的命令:

-2:向左转 90 度

-1:向右转 90 度

1 <= x <= 9:向前移动 x 个单位长度

在网格上有一些格子被视为障碍物。

第 i 个障碍物位于网格点  (obstacles[i][0], obstacles[i][1])

如果机器人试图走到障碍物上方,那么它将停留在障碍物的前一个网格方块上,但仍然可以继续该路线的其余部分。

返回从原点到机器人的最大欧式距离的平方。

提示:

0 <= commands.length <= 10000

0 <= obstacles.length <= 10000

-30000 <= obstacle[i][0] <= 30000

-30000 <= obstacle[i][1] <= 30000

答案保证小于 2 ^ 31

解:

按照题目要求模拟,把方向表示和step的索引结合起来用,注意障碍的位置用hashset存一下,每次查询就O(1)。

class Solution:

def robotSim(self, commands: List[int], obstacles: List[List[int]]) -> int:

if not commands:

return 0

direct = 0 # 初始面向北方 1: 东;2:南;3:西

res = 0

loc = (0, 0) # 初始位于原点,direct = 0, y+step; 1,x+step; 2, y-step; 3, x-step

step_x = (0, 1, 0, -1)

step_y = (1, 0, -1, 0)

obstacles = set(map(tuple, obstacles))

for v in commands:

if v == -1: # 向右转90度

direct += 1

direct %= 4

elif v == -2: # 向左转90度

direct += 3 # -1+4

direct %= 4

else: # 前进

while v:

if (loc[0]+step_x[direct], loc[1]+step_y[direct]) in obstacles:

break

loc = (loc[0]+step_x[direct], loc[1]+step_y[direct])

res = max(res, loc[0]**2 + loc[1]**2)

v -= 1

return res

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值