122. 买卖股票的最佳时机ii https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/
给定一个数组,它的第 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
860.柠檬水找零 https://leetcode-cn.com/problems/lemonade-change/
在柠檬水摊上,每一杯柠檬水的售价为 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
455. 分发饼干 https://leetcode-cn.com/problems/assign-cookies/
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 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
874. 模拟行走机器人 https://leetcode-cn.com/problems/walking-robot-simulation/
机器人在一个无限大小的网格上行走,从点 (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