Press "Enter" to skip to content

Huahua's Tech Road

花花酱 LeetCode 2011. Final Value of Variable After Performing Operations

C++ 也能写one-liner了。

时间复杂度:O(n)
空间复杂度:O(1)

花花酱 LeetCode 1992. Find All Groups of Farmland

已经告诉你所有的农田都是规整的矩形,题目难度一下子降低了。
对于每一个农田的左上角,找到它的宽度和高度即可。
然后把整个农田矩形标记为林地/非农田即可。

时间复杂度:O(m*n) 每个格子最多遍历3遍。
空间复杂度:O(1)

花花酱 LeetCode 650. 2 Keys Keyboard

这道题目还是可以的。每个阶段有两种选择,求最短的决策次数。有好多种不同的做法,我们一个一个来。

方法1: BFS

把问题看成求无权重图中的最短路径,BFS可以找到最优解。

我们的节点有两个状态,当前的长度,剪贴板(上次复制后)的长度。
长度超过n一定无解,所以我们的状态最多只有n2种,每个状态最多拓展2个新的节点。

时间复杂度:O(n2)
空间复杂度:O(n2)

花花酱 LeetCode 646. Maximum Length of Pair Chain

这题我选DP,因为不需要证明,直接干就行了。

方法1: DP

首先还是需要对pairs的right进行排序。一方面是为了方便chaining,另一方面是可以去重。

然后定义 dp[i] := 以pairs[i]作为结尾,最长的序列的长度。

状态转移:dp[i] = max(dp[j] + 1) where pairs[i].left > pairs[j].right and 0 < j < i.

解释:对于pairs[i],找一个最优的pairs[j],满足pairs[i].left > pairs[j].right,这样我就可以把pairs[i]追加到以pairs[j]结尾的最长序列后面了,长度+1。

边检条件:dp[0:n] = 1,每个pair以自己作为序列的最后元素,长度为1。

时间复杂度:O(n2)
空间复杂度:O(n)

方法2: 贪心

和DP一样,对数据进行排序。

每当我看到 cur.left > prev.right,那么就直接把cur接在prev后面。我们需要证明这么做是最优的,而不是跳过它选后面的元素。

Case 0: cur已经是最后一个元素了,跳过就不是最优解了。

假设cur后面有next, 因为已经排序过了,我们可以得知 next.right >= cur.right。

Case 1: next.right == cur.right。这时候选cur和选next对后面的决策来说是一样的,但由于Case 0的存在,我必须选cur。

Case 2: next.right > cur.right。不管left的情况怎么样,由于right更小,这时候选择cur一定是优于next。

综上所述,看到有元素可以连接起来就贪心的选它就对了。

时间复杂度:O(nlogn)
空间复杂度:O(1)

花花酱 LeetCode 514. Freedom Trail

一眼DP,看数据规模标程应该是O(1003)。

阶段肯定就是吟唱完一个字符,状态和哪个字符在12:00点有关。

所以我们定义 dp[i][j] := 吟唱完keys[0~i]后,rings[j]停在12:00点所需要的最少步数。

转移方程:dp[i][j] = min(dp[i-1][k] + steps(k, j) + 1) if keys[i] == rings[j] else +inf.

第i-1字符吟唱完ring停留在k,第i个字符吟唱完ring停留在j (rings[j] 必须和 keys[i] 相同),steps(k, j)表示ring从k转到j所需要的最少步数,最后还要+1,表示吟唱当前字符所需要的额外步骤。

边界条件:对于第0个字符,ring一开始停留在第0个字符,最小步数就是1 + steps(0, key[0])。

时间复杂度:O(mn2)
空间复杂度:O(mn) 可以降维到 O(n)