LeetCode:贪心算法问题解决方案集合(教程+Python代码)


目录

例1:LeetCode455. 分发饼干(easy)

例2:LeetCode376. 摆动序列(medium)

例3:LeetCode402. 移掉K位数字(medium)

例4:LeetCode55. 跳跃游戏(medium)

例5:LeetCode55. 跳跃游戏2(hard)

例6:LeetCode452. 用最少数量的箭引爆气球(medium)


 

例1:LeetCode455. 分发饼干(easy)

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

注意:你可以假设胃口值为正。一个小朋友最多只能拥有一块饼干。

 

示例 1:

输入: [1,2,3], [1,1]

输出: 1

解释: 
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。

示例 2:

输入: [1,2], [1,2,3]

输出: 2

解释: 
你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
你拥有的饼干数量和尺寸都足以让所有孩子满足。
所以你应该输出2.

贪心想法:

LeetCode:贪心算法问题解决方案集合(教程+Python代码)_第1张图片

算法设计:

LeetCode:贪心算法问题解决方案集合(教程+Python代码)_第2张图片

LeetCode:贪心算法问题解决方案集合(教程+Python代码)_第3张图片

代码:

class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        g.sort()
        s.sort()
        child = 0
        cookie = 0
        while child < len(g) and cookie < len(s):
            if g[child] <= s[cookie]:
                child += 1
            cookie += 1
        return child

 

 

例2:LeetCode376. 摆动序列(medium)

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。

例如, [1,7,4,9,2,5] 是一个摆动序列,因为差值 (6,-3,5,-7,3) 是正负交替出现的。相反, [1,4,7,2,5] 和 [1,7,4,5,5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。

示例 1:

输入: [1,7,4,9,2,5]
输出: 6 
解释: 整个序列均为摆动序列。
示例 2:

输入: [1,17,5,10,13,15,10,5,16,8]
输出: 7
解释: 这个序列包含几个长度为 7 摆动序列,其中一个可为[1,17,10,13,10,16,8]。

贪心规律:

LeetCode:贪心算法问题解决方案集合(教程+Python代码)_第4张图片

算法设计:

LeetCode:贪心算法问题解决方案集合(教程+Python代码)_第5张图片

代码:

class Solution:
    def wiggleMaxLength(self, nums: List[int]) -> int:
        if len(nums) < 2:
            return len(nums)
        
        begin = 0
        up = 1
        down = 2
        state = begin
        max_length = 1
        
        for i in range(1, len(nums)):
            if state == begin:
                if nums[i-1] < nums[i]:
                    state = up
                    max_length += 1
                elif nums[i-1] > nums[i]:
                    state = down
                    max_length += 1
            if state == up:
                if nums[i-1] > nums[i]:
                    state = down
                    max_length += 1
            if state == down:
                if nums[i-1] < nums[i]:
                    state = up
                    max_length += 1
        return max_length

 

例3:LeetCode402. 移掉K位数字(medium)

给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。

注意:

num 的长度小于 10002 且 ≥ k。
num 不会包含任何前导零。
示例 1 :

输入: num = "1432219", k = 3
输出: "1219"
解释: 移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219。
示例 2 :

输入: num = "10200", k = 1
输出: "200"
解释: 移掉首位的 1 剩下的数字为 200. 注意输出不能有任何前导零。

贪心规律:

LeetCode:贪心算法问题解决方案集合(教程+Python代码)_第6张图片

算法设计:

LeetCode:贪心算法问题解决方案集合(教程+Python代码)_第7张图片

LeetCode:贪心算法问题解决方案集合(教程+Python代码)_第8张图片

LeetCode:贪心算法问题解决方案集合(教程+Python代码)_第9张图片

代码:

class Solution:
    def removeKdigits(self, num: str, k: int) -> str:
        s = []
        result = ''
        for i in range(len(num)):
            number = int(num[i])
            while len(s) != 0 and s[-1]>number and k>0:
                s.pop()
                k -= 1
            if number != 0 or len(s) != 0:
                s.append(number)
        
        while len(s) != 0 and k>0:
            s.pop()
            k -= 1
        
        result = result.join('%s'%q for q in s)
        if result == '':
            result = '0'
        return result

 

例4:LeetCode55. 跳跃游戏(medium)

给定一个非负整数数组,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个位置。

示例 1:

输入: [2,3,1,1,4]
输出: true
解释: 从位置 0 到 1 跳 1 步, 然后跳 3 步到达最后一个位置。
示例 2:

输入: [3,2,1,0,4]
输出: false
解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。

贪心算法:从前往后跳

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        start = 0
        end = 0
        n = len(nums)
        while start <= end and end < n-1:
            end = max(end, start+nums[start])
            start += 1
        return end >= n-1

 

例5:LeetCode55. 跳跃游戏2(hard)

给定一个非负整数数组,你最初位于数组的第一个位置。

数组中的每个元素代表你在该位置可以跳跃的最大长度。

你的目标是使用最少的跳跃次数到达数组的最后一个位置。

示例:

输入: [2,3,1,1,4]
输出: 2
解释: 跳到最后一个位置的最小跳跃数是 2。
     从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。

贪心规律:

LeetCode:贪心算法问题解决方案集合(教程+Python代码)_第10张图片

算法设计:

LeetCode:贪心算法问题解决方案集合(教程+Python代码)_第11张图片

LeetCode:贪心算法问题解决方案集合(教程+Python代码)_第12张图片

代码:

class Solution:
    def jump(self, nums: List[int]) -> int:

        if len(nums) < 2: return 0
        current_max_index = nums[0]   # 当前可达到的最远位置
        pre_max_max_index = nums[0]   # 遍历当前位置到当前可达到的最远位置之间,可以达到的最远位置
        jump_min = 1
        for i in range(len(nums)):
            if i > current_max_index:    # 无法向前移动了在跳跃
                jump_min += 1
                current_max_index = pre_max_max_index
            if pre_max_max_index < nums[i]+i:
                pre_max_max_index = nums[i]+i
        return jump_min
        

 

例6:LeetCode452. 用最少数量的箭引爆气球(medium)

在二维空间中有许多球形的气球。对于每个气球,提供的输入是水平方向上,气球直径的开始和结束坐标。由于它是水平的,所以y坐标并不重要,因此只要知道开始和结束的x坐标就足够了。开始坐标总是小于结束坐标。平面内最多存在104个气球。

一支弓箭可以沿着x轴从不同点完全垂直地射出。在坐标x处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足  xstart ≤ x ≤ xend,则该气球会被引爆。可以射出的弓箭的数量没有限制。 弓箭一旦被射出之后,可以无限地前进。我们想找到使得所有气球全部被引爆,所需的弓箭的最小数量。

Example:

输入:
[[10,16], [2,8], [1,6], [7,12]]

输出:
2

解释:
对于该样例,我们可以在x = 6(射爆[2,8],[1,6]两个气球)和 x = 11(射爆另外两个气球)。

算法思路:

LeetCode:贪心算法问题解决方案集合(教程+Python代码)_第13张图片

LeetCode:贪心算法问题解决方案集合(教程+Python代码)_第14张图片

LeetCode:贪心算法问题解决方案集合(教程+Python代码)_第15张图片

LeetCode:贪心算法问题解决方案集合(教程+Python代码)_第16张图片

代码:

class Solution:
    def findMinArrowShots(self, points: List[List[int]]) -> int:
        if len(points) == 0: return 0
        
        points = sorted(points, key=lambda x: x[0])
        shoot_num = 1               # 弓箭
        shoot_begin = points[0][0]
        shoot_end = points[0][1]
        
        for i in range(len(points)):
            if points[i][0] <= shoot_end:
                shoot_begin = points[i][0]
                if shoot_end > points[i][1]:
                    shoot_end = points[i][1]
            else:
                shoot_num += 1
                shoot_begin = points[i][0]
                shoot_end = points[i][1]
        return shoot_num

 

 

 

 

你可能感兴趣的:(刷题)