贪心思想

193 阅读3分钟

💣435. 无重叠区间

贪心思想

从起点的贪心算法

先按照起点对区间进行排序。利用一个 prev 指针追踪刚刚添加到最终列表中的区间。考虑三种情况:

蓝色表示前一个已加入最终列表的区间,绿色为当前区间

  • Case 1:
    不移除任何区间,将 prev 赋值为后面的区间,移除区间数量不变。

  • Case 2:(一开始只是单纯丢弃了后面的区间)
    只保留后一个区间。因为后一个区间的长度更小,可以留下更多的空间(AB),容纳更多的区间。因此, prev 更新为当前区间,移除区间的数量 +1。

  • Case 3:
    这种情况下,我们用贪心策略处理问题,保留前一个区间。(因为前一个区间的右端点更小,可以为后面区间腾出更多空间)prev 不变,移除区间的数量 +1。

从终点的贪心算法

先按照终点对区间进行排序。利用一个 prev 指针追踪刚刚添加到最终列表中的区间。同样地,也考虑上述三种情况:


Case 2, Case 3 都是保留前一个区间。

动态规划

官方题解

452. 用最少数量的箭引爆气球

与上一题思路一样

406. 根据身高重建队列

从逆序生成排列算法

算法如下:

组合数学第五版

注:

  • 二维数组通过 Arrays.deepToString 可直接 sout
  • toArray() 方法导出的是 Object 类型数组,而 toArray[T[] a] 方法导出的是指定类型的数组,参考这里

121. 买卖股票的最佳时机 I & II & III

I(一次交易)

参考链接
论坛里也有动规解法

II(多次买卖一支股票)

后一天价格大于前一天则累加。

III(最多两次交易)

正反贪心(很难想到)

  • 正向遍历,记录每天卖出时可赚得的最大利润到 forwardMax[]
  • 反向遍历,记录 backwardMaxforwardMax[j] + backwardMax 的最大值即为答案。

动态规划解法在“动态规划 markdown”中

605. 种花问题

端点可一起判断
if (flowerbed[i] == 0 && (i == 0 || flowerbed[i - 1] == 0) && (i == flowerbed.length - 1 || flowerbed[i + 1] == 0))

392. 判断子序列

双指针🉑
用 ⭐String.indexOf(Char, fromIndex) 判断更佳。fromIndex 从上一个匹配的位置开始搜索。

665. 非递减数列

在出现 nums[i + 1] < nums[i] 时,需要考虑的是应该修改数组的哪个数,使得本次修改能使 i 之前的数组成为非递减数组,并且不影响后续的操作。考虑以下测试用例:

用例 0 1 ... i - 1 i i + 1 ...
... ... ... -1 (4) 2 ...
... ... ... 3 3 (2) ...
... ... ... 3 4 2 ...
(4) 2 ... ... ... ... ...

可以发现,若 nums[i - 1] > nums[i + 1] ,则修改 nums[i + 1],否则修改 nums[i],并考虑数组首位情况(用例 4)。

⭐53. 最大子序和

动态规划

状态转移方程: dp[i]=\left\lbrace\begin{array}{ll}
{dp[i-1]+nums[i],} & {\text { if } \quad dp[i-1] \geq 0}\cr
{nums[i],} & {\text { if } \quad dp[i-1]<0}
\end{array}\right.
dp[i] :表示以 nums[i] 结尾的连续子数组的最大和。dp[i - 1] < 0 时,直接抛弃之前的和。

分治法(没看懂)