zoukankan      html  css  js  c++  java
  • Leetcode-贪心

    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
    

      

  • 相关阅读:
    持有你自己的权力
    《活在恩典中》:我们所寻求的是什么?
    修学文钞 | 道证法师怎么学印光大师《文钞》
    致初学者:印祖文钞修学次第建议
    印光大师指定的文钞入门篇目
    sql注入在线检测(sqlmapapi)
    【转】Kali Linux 新手折腾笔记
    JAVA开发-我的第一个webScan扫描器
    JAVA开发--游戏24点
    JAVA开发--U盘EXE恢复工具
  • 原文地址:https://www.cnblogs.com/chaojunwang-ml/p/11359345.html
Copyright © 2011-2022 走看看