个人笔记04:方向一笔记-贪心问题 | 豆包MarsCode AI刷题

77 阅读3分钟

方向一笔记-个人笔记04:贪心问题

贪心问题有很多类型,包括从最值开始贪心、区间贪心等。这类问题比较灵活,且很多时候用动态规划方法解决此类问题更合适。

例1:小M负责管理一块的农田(表示为m×n的二维数组cropField),每个元素代表对应位置上的作物产量。小M的灌溉方案是:

① 一条渠道从上到下灌溉整行,另一条渠道从左到右灌溉整列。

② 被灌溉的行或列上的作物产量会加倍(即对应位置的作物产量变为原来的两倍)。

③ 只能给每个作物位置加倍一次,即同一位置不能同时被两条渠道灌溉。

找出需要灌溉的行和列,使得作物的总产量最大化。

(思路)最值贪心问题。求出各行和rowSum与各列和colSum,目标是找到需要灌溉的第i行和第j列使得 (rowSum[i]+colSum[j]-cropField[i][j]) 最大。时间复杂度 O(mn),空间复杂度 O(m+n)(用以存储行列和的列表)。

例2:给定一个长度为 n 的序列a=[a1,a2,...,an],可以选择删去其中最多n-1个数,得到一个新序列b1,b2,...,bm,新序列保留原来的相对顺序。你的目标是删除某些数,使得新序列的第i个数bi=i。求出最少删除多少个数才能得到这样的序列,如果无法得到,输出-1。

(思路)正繁求反,为了使被删除的数尽可能少,现考查最多能留下多少个数。

设变量num,初值为1,下标j遍历a,一旦遇到num=a[j],则num递增。

最后,如果num保持为1的初值,说明原序列无法变为新序列,返回-1;反之,则得到需要删除的数有 (n-num+1) 个。

例3:小C和小U从三个区间:[l1,r1],[l2,r2],[l3,r3]中分别选择一个区间(不能相同)。接着,在各自的区间内选择一个数,这个数要在对方的区间内找到。目标是使选择的两个数的和尽可能大。如果不存在这样的两个数,输出-1。

(思路)区间贪心,这里利用差分数组diff来解决问题。

首先,找到r1,r2,r3中的最大值maxn。初始化差分数组为长度等于 (maxn+2) 的全0数组。

然后,对于第i个区间[li,ri],令diff[li]递增,diff[ri+1]递减。这样,在还原diff数组为累加数组时,只需设前缀和变量preSum,在每个diff[i]处,preSum+=diff[i],再用preSum赋值diff[i]。

如果diff[i]>=2,说明至少有两个区间覆盖了端点i,本题答案更新为i*2。

通过差分数组,在确认区间覆盖的端点时可以做到一次遍历。如果有m个区间,区间最右端端点值为n,那么时间复杂度就是O(m+n),空间复杂度为O(n)。