算法刷题之十一贪心算法
贪心算法
- 发饼干
- 合唱团
#发饼干
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
示例 1:
输入: g = [1,2,3], s = [1,1]
输出: 1
解释:
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。
示例 2:
输入: g = [1,2], s = [1,2,3]
输出: 2
解释:
你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
你拥有的饼干数量和尺寸都足以让所有孩子满足。
所以你应该输出2.
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/assign-cookies
方法:
贪心算法:大尺寸的饼干能够满足胃口小的孩子,也能够满足胃口大的孩子,所以对于大尺寸的饼干要优先满足胃口大的孩子,而胃口小的孩子用小尺寸的饼干来喂,尽量减少浪费。
局部最优:充分利用饼干尺寸满足一个;全局最优:就是满足尽可能多的孩子。
首先将饼干数组和孩子数组进行排序,然后从后往前依次进行比较。
若 g[i] <= s[index]g[i]<=s[index]
并且 index >= 0index>=0
,则说明此时还有饼干并且当前遍历的这个饼干能够满足当前遍历的这个孩子的胃口(因为是从后往前进行遍历的,所以每次遍历的孩子和饼干都是当前两个数组中最大的)。
若 g[i] > s[index]g[i]>s[index]
并且 index >= 0index>=0
,则说明当前饼干的尺寸 s[index]
s[index](此时,饼干数组中饼干的最大尺寸)无法满足当前遍历的这个孩子的胃口 g[i]g[i](此时,当前孩子数组中胃口最大的孩子),需要将这个孩子舍弃(因为当前最大的饼干尺寸都不能够喂饱,再往前遍历时的饼干尺寸一定不可能满足这个孩子)。
若 index < 0index<0,说明此时饼干已经全部分完了,没有多余的饼干来喂剩余的孩子了,此时应该直接结束。
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
#首先要对g 和 s排序:题中没有说明输入是有序序列
g.sort()
s.sort()
#两个指针分别指向两个列表的末尾
r_g = len(g) - 1
r_s = len(s) - 1
count = 0
#循环条件
while r_g >= 0 and r_s >= 0:
#两个指针分别指向两个列表的末尾如果满足`s[r_s] >= g[r_g]`,则都向前移动
if s[r_s] >= g[r_g]:
count += 1
r_g -= 1
r_s -= 1
#否则只需要移动g的指针
else:
r_g -= 1
return count
合唱团
计算最少出列多少位同学,使得剩下的同学排成合唱队形
说明:
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足存在i(1<=i<=K)使得T1<T2<......<Ti-1
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形。
示例1:5,4,7,9,3,2
方法:先从左到有求出最长上升数组:1,1,2,3,1,1,然后从右到左求出最长上升数组:1,2,3,3,2,2。最后将两个相加,算出最大的即可。
import bisect
def max_list(alist):
n = len(alist)
temp = [99999] * n
temp[0] = alist[0]
ret = [1]
for i in range(1, n):
pos = bisect.bisect_left(temp, alist[i])
ret.append(pos+1)
temp[pos] = alist[i]
# print(ret)
return ret
while True:
try:
n = int(input())
nums = list(map(int, input().split()))
dt1 = max_list(nums)
dt2 = max_list(nums[::-1])[::-1]
a = max(dt1[i] + dt2[i] for i in range(n))
res = n - a + 1
print(res)
except:
break
递归算法
M个苹果放入N个盘子
题目:
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。
输入
每个用例包含二个整数M和N。0<=m<=10,1<=n<=10。
样例输入
7 3
样例输出
8
思路:
将m个苹果分到n个盘子中,可以有两种大的状态:
- 盘子有空的,可以空1个,2个,3个,一直到m-1个
- 盘子不为空,所有盘子都装满,那么全部都减去1并不影响摆放
def func(m, n):
if m == 0 or n == 1:
return 1
if m < n:
return func(m, m)
else:
return func(m, n-1) + func(m-n, n)
m = 7
n = 3
res = func(m, n)
print(res)