diff --git a/problems/0019.删除链表的倒数第N个节点.md b/problems/0019.删除链表的倒数第N个节点.md index dbd053d1..28bb61ee 100644 --- a/problems/0019.删除链表的倒数第N个节点.md +++ b/problems/0019.删除链表的倒数第N个节点.md @@ -110,7 +110,7 @@ public ListNode removeNthFromEnd(ListNode head, int n){ fastIndex = fastIndex.next; } - while (fastIndex.next != null){ + while (fastIndex != null){ fastIndex = fastIndex.next; slowIndex = slowIndex.next; } diff --git a/problems/0053.最大子序和(动态规划).md b/problems/0053.最大子序和(动态规划).md index f1b64709..70ad7a84 100644 --- a/problems/0053.最大子序和(动态规划).md +++ b/problems/0053.最大子序和(动态规划).md @@ -226,18 +226,20 @@ object Solution { ```typescript function maxSubArray(nums: number[]): number { - /** - dp[i]:以nums[i]结尾的最大和 - */ - const dp: number[] = [] - dp[0] = nums[0]; - let resMax: number = 0; - for (let i = 1; i < nums.length; i++) { - dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]); - resMax = Math.max(resMax, dp[i]); + const len = nums.length + if (len === 1) return nums[0] + + const dp: number[] = new Array(len) + let resMax: number = dp[0] = nums[0] + + for (let i = 1; i < len; i++) { + dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]) + // 注意值为负数的情况 + if (dp[i] > resMax) resMax = dp[i] } - return resMax; -}; + + return resMax +} ``` diff --git a/problems/0098.验证二叉搜索树.md b/problems/0098.验证二叉搜索树.md index 0a64266e..184060a5 100644 --- a/problems/0098.验证二叉搜索树.md +++ b/problems/0098.验证二叉搜索树.md @@ -595,6 +595,43 @@ var isValidBST = function (root) { }; ``` +> 迭代法: + +```JavaScript +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {boolean} + */ +let pre = null; +var isValidBST = function (root) { + const queue = []; + let cur = root; + let pre = null; + while (cur !== null || queue.length !== 0) { + if (cur !== null) { + queue.push(cur); + cur = cur.left; + } else { + cur = queue.pop(); + if (pre !== null && cur.val <= pre.val) { + return false; + } + pre = cur; + cur = cur.right; + } + } + return true; +}; +``` + ### TypeScript > 辅助数组解决: @@ -637,6 +674,30 @@ function isValidBST(root: TreeNode | null): boolean { }; ``` +> 迭代法: + +```TypeScript +function isValidBST(root: TreeNode | null): boolean { + const queue: TreeNode[] = []; + let cur: TreeNode | null = root; + let pre: TreeNode | null = null; + while (cur !== null || queue.length !== 0) { + if (cur !== null) { + queue.push(cur); + cur = cur.left; + } else { + cur = queue.pop()!; + if (pre !== null && cur!.val <= pre.val) { + return false; + } + pre = cur; + cur = cur!.right; + } + } + return true; +} +``` + ### Scala 辅助数组解决: diff --git a/problems/0239.滑动窗口最大值.md b/problems/0239.滑动窗口最大值.md index 6f420479..19ac1261 100644 --- a/problems/0239.滑动窗口最大值.md +++ b/problems/0239.滑动窗口最大值.md @@ -62,9 +62,9 @@ public: 每次窗口移动的时候,调用que.pop(滑动窗口中移除元素的数值),que.push(滑动窗口添加元素的数值),然后que.front()就返回我们要的最大值。 -这么个队列香不香,要是有现成的这种数据结构是不是更香了! +这么个队列香不香,要是有现成的这种数据结构是不是更香了! -**可惜了,没有! 我们需要自己实现这么个队列。** +其实在C++中,可以使用 multiset 来模拟这个过程,文末提供这个解法仅针对C++,以下讲解我们还是靠自己来实现这个单调队列。 然后再分析一下,队列里的元素一定是要排序的,而且要最大值放在出队口,要不然怎么知道最大值呢。 @@ -839,6 +839,28 @@ impl Solution { } ``` +### C++ +使用multiset作为单调队列 + +多重集合(`multiset`) 用以有序地存储元素的容器。允许存在相等的元素。 + +在遍历原数组的时候,只需要把窗口的头元素加入到multiset中,然后把窗口的尾元素删除即可。因为multiset是有序的,并且提供了*rbegin(),可以直接获取窗口最大值。 +```cpp +class Solution { +public: + vector maxSlidingWindow(vector& nums, int k) { + multiset st; + vector ans; + for (int i = 0; i < nums.size(); i++) { + if (i >= k) st.erase(st.find(nums[i - k])); + st.insert(nums[i]); + if (i >= k - 1) ans.push_back(*st.rbegin()); + } + return ans; + } +}; +``` +

diff --git a/problems/0392.判断子序列.md b/problems/0392.判断子序列.md index f7863c94..ebd567cb 100644 --- a/problems/0392.判断子序列.md +++ b/problems/0392.判断子序列.md @@ -216,26 +216,51 @@ const isSubsequence = (s, t) => { ### TypeScript: +> 二维数组 + ```typescript function isSubsequence(s: string, t: string): boolean { /** dp[i][j]: s的前i-1个,t的前j-1个,最长公共子序列的长度 */ - const sLen: number = s.length, - tLen: number = t.length; - const dp: number[][] = new Array(sLen + 1).fill(0) - .map(_ => new Array(tLen + 1).fill(0)); + const sLen = s.length + const tLen = t.length + const dp: number[][] = new Array(sLen + 1).fill(0).map(_ => new Array(tLen + 1).fill(0)) + for (let i = 1; i <= sLen; i++) { for (let j = 1; j <= tLen; j++) { - if (s[i - 1] === t[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1; - } else { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); - } + if (s[i - 1] === t[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1 + // 只需要取 j-2 的 dp 值即可,不用考虑 i-2 + else dp[i][j] = dp[i][j - 1] } } - return dp[sLen][tLen] === s.length; -}; + return dp[sLen][tLen] === s.length +} +``` + +> 滚动数组 +```typescript +function isSubsequence(s: string, t: string): boolean { + const sLen = s.length + const tLen = t.length + const dp: number[] = new Array(tLen + 1).fill(0) + + for (let i = 1; i <= sLen; i++) { + let prev: number = 0; + let temp: number = 0; + for (let j = 1; j <= tLen; j++) { + // 备份一下当前状态(经过上层迭代后的) + temp = dp[j] + // prev 相当于 dp[j-1](累加了上层的状态) + // 如果单纯 dp[j-1] 则不会包含上层状态 + if (s[i - 1] === t[j - 1]) dp[j] = prev + 1 + else dp[j] = dp[j - 1] + // 继续使用上一层状态更新参数用于当前层下一个状态 + prev = temp + } + } + return dp[tLen] === sLen +} ``` ### Go: diff --git a/problems/0827.最大人工岛.md b/problems/0827.最大人工岛.md index 71b90a78..4feb78de 100644 --- a/problems/0827.最大人工岛.md +++ b/problems/0827.最大人工岛.md @@ -345,6 +345,7 @@ class Solution: res = max(res, count) return res + ```

diff --git a/problems/1035.不相交的线.md b/problems/1035.不相交的线.md index ff9e5dc4..e0625a2b 100644 --- a/problems/1035.不相交的线.md +++ b/problems/1035.不相交的线.md @@ -221,6 +221,8 @@ const maxUncrossedLines = (nums1, nums2) => { ### TypeScript: +> 二维数组 + ```typescript function maxUncrossedLines(nums1: number[], nums2: number[]): number { /** @@ -243,6 +245,34 @@ function maxUncrossedLines(nums1: number[], nums2: number[]): number { }; ``` +> 滚动数组 +```typescript +function maxUncrossedLines(nums1: number[], nums2: number[]): number { + const len1 = nums1.length + const len2 = nums2.length + + const dp: number[] = new Array(len2 + 1).fill(0) + + for (let i = 1; i <= len1; i++) { + let prev: number = 0; + let temp: number = 0; + for (let j = 1; j <= len2; j++) { + // 备份一下当前状态(经过上层迭代后的) + temp = dp[j] + // prev 相当于 dp[j-1](累加了上层的状态) + // 如果单纯 dp[j-1] 则不会包含上层状态 + if (nums1[i - 1] === nums2[j - 1]) dp[j] = prev + 1 + // dp[j] 表示之前的 dp[i][j-1],dp[j-1] 表示 dp[i-1][j] + else dp[j] = Math.max(dp[j], dp[j - 1]) + // 继续使用上一层状态更新参数用于当前层下一个状态 + prev = temp + } + } + return dp[len2] +} +``` + +