diff --git a/README.md b/README.md index 82c65c7a..05fc0627 100644 --- a/README.md +++ b/README.md @@ -305,7 +305,8 @@ 背包问题系列: -背包问题大纲 +背包问题大纲 + 11. [动态规划:关于01背包问题,你该了解这些!](./problems/背包理论基础01背包-1.md) 12. [动态规划:关于01背包问题,你该了解这些!(滚动数组)](./problems/背包理论基础01背包-2.md) @@ -334,7 +335,8 @@ 股票系列: -股票问题总结 +股票问题总结 + 32. [动态规划:买卖股票的最佳时机](./problems/0121.买卖股票的最佳时机.md) 33. [动态规划:本周我们都讲了这些(系列六)](./problems/周总结/20210225动规周末总结.md) @@ -348,6 +350,9 @@ 子序列系列: + + + 40. [动态规划:最长递增子序列](./problems/0300.最长上升子序列.md) 41. [动态规划:最长连续递增序列](./problems/0674.最长连续递增序列.md) 42. [动态规划:最长重复子数组](./problems/0718.最长重复子数组.md) diff --git a/problems/0001.两数之和.md b/problems/0001.两数之和.md index f81c35ca..77318294 100644 --- a/problems/0001.两数之和.md +++ b/problems/0001.两数之和.md @@ -57,7 +57,9 @@ std::unordered_map 底层实现为哈希表,std::map 和std::multimap 的底 解题思路动画如下: - + +![](https://code-thinking.cdn.bcebos.com/gifs/1.两数之和.gif) + C++代码: diff --git a/problems/0017.电话号码的字母组合.md b/problems/0017.电话号码的字母组合.md index 0a69c69c..fa135d8d 100644 --- a/problems/0017.电话号码的字母组合.md +++ b/problems/0017.电话号码的字母组合.md @@ -282,6 +282,43 @@ class Solution { ``` Python: + +```Python +class Solution: + ans = [] + s = '' + letterMap = { + '2': 'abc', + '3': 'def', + '4': 'ghi', + '5': 'jkl', + '6': 'mno', + '7': 'pqrs', + '8': 'tuv', + '9': 'wxyz' + } + + def letterCombinations(self, digits): + self.ans.clear() + if digits == '': + return self.ans + self.backtracking(digits, 0) + return self.ans + + def backtracking(self, digits, index): + if index == len(digits): + self.ans.append(self.s) + return + else: + letters = self.letterMap[digits[index]] # 取出数字对应的字符集 + for letter in letters: + self.s = self.s + letter # 处理 + self.backtracking(digits, index + 1) + self.s = self.s[:-1] # 回溯 +``` + +python3: + ```python3 class Solution: def letterCombinations(self, digits: str) -> List[str]: @@ -302,6 +339,7 @@ class Solution: return res ``` + Go: diff --git a/problems/0019.删除链表的倒数第N个节点.md b/problems/0019.删除链表的倒数第N个节点.md index 65651768..7d2fe97e 100644 --- a/problems/0019.删除链表的倒数第N个节点.md +++ b/problems/0019.删除链表的倒数第N个节点.md @@ -114,24 +114,28 @@ class Solution { ``` Go: ```Go +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ func removeNthFromEnd(head *ListNode, n int) *ListNode { - result:=&ListNode{} - result.Next=head - var pre *ListNode - cur:=result - - i:=1 - for head!=nil{ - if i>=n{ - pre=cur - cur=cur.Next + dummyHead := &ListNode{} + dummyHead.Next = head + cur := head + prev := dummyHead + i := 1 + for cur != nil { + cur = cur.Next + if i > n { + prev = prev.Next } - head=head.Next i++ } - pre.Next=pre.Next.Next - return result.Next - + prev.Next = prev.Next.Next + return dummyHead.Next } ``` diff --git a/problems/0020.有效的括号.md b/problems/0020.有效的括号.md index 315ff384..dae84354 100644 --- a/problems/0020.有效的括号.md +++ b/problems/0020.有效的括号.md @@ -271,6 +271,23 @@ var isValid = function (s) { } return stack.length === 0; }; +// 简化版本 +var isValid = function(s) { + const stack = [], + map = { + "(":")", + "{":"}", + "[":"]" + }; + for(const x of s) { + if(x in map) { + stack.push(x); + continue; + }; + if(map[stack.pop()] !== x) return false; + } + return !stack.length; +}; ``` diff --git a/problems/0024.两两交换链表中的节点.md b/problems/0024.两两交换链表中的节点.md index 8d6a394d..643f6055 100644 --- a/problems/0024.两两交换链表中的节点.md +++ b/problems/0024.两两交换链表中的节点.md @@ -153,6 +153,19 @@ func swapPairs(head *ListNode) *ListNode { } ``` +```go +// 递归版本 +func swapPairs(head *ListNode) *ListNode { + if head == nil || head.Next == nil { + return head + } + next := head.Next + head.Next = swapPairs(next.Next) + next.Next = head + return next +} +``` + Javascript: ```javascript var swapPairs = function (head) { diff --git a/problems/0039.组合总和.md b/problems/0039.组合总和.md index e3e79295..0eba785f 100644 --- a/problems/0039.组合总和.md +++ b/problems/0039.组合总和.md @@ -292,7 +292,32 @@ class Solution: ``` Go: +JavaScript +```js +var strStr = function (haystack, needle) { + if (needle === '') { + return 0; + } + let hayslen = haystack.length; + let needlen = needle.length; + + if (haystack === '' || hayslen < needlen) { + return -1; + } + + for (let i = 0; i <= hayslen - needlen; i++) { + if (haystack[i] === needle[0]) { + if (haystack.substr(i, needlen) === needle) { + return i; + } + } + if (i === hayslen - needlen) { + return -1; + } + } +}; +``` ----------------------- diff --git a/problems/0056.合并区间.md b/problems/0056.合并区间.md index 1c2da854..eb8e7bff 100644 --- a/problems/0056.合并区间.md +++ b/problems/0056.合并区间.md @@ -212,6 +212,26 @@ func max(a, b int) int { } ``` +Javascript: +```javascript +var merge = function (intervals) { + intervals.sort((a, b) => a[0] - b[0]); + let prev = intervals[0] + let result = [] + for(let i =0; i prev[1]){ + result.push(prev) + prev = cur + }else{ + prev[1] = Math.max(cur[1],prev[1]) + } + } + result.push(prev) + return result +}; +``` + ----------------------- diff --git a/problems/0062.不同路径.md b/problems/0062.不同路径.md index c4673a23..60b65818 100644 --- a/problems/0062.不同路径.md +++ b/problems/0062.不同路径.md @@ -86,7 +86,7 @@ public: ### 动态规划 -机器人从(0 , 0) 位置触发,到(m - 1, n - 1)终点。 +机器人从(0 , 0) 位置出发,到(m - 1, n - 1)终点。 按照动规五部曲来分析: @@ -243,10 +243,50 @@ public: Java: +```java + /** + * 1. 确定dp数组下表含义 dp[i][j] 到每一个坐标可能的路径种类 + * 2. 递推公式 dp[i][j] = dp[i-1][j] dp[i][j-1] + * 3. 初始化 dp[i][0]=1 dp[0][i]=1 初始化横竖就可 + * 4. 遍历顺序 一行一行遍历 + * 5. 推导结果 。。。。。。。。 + * + * @param m + * @param n + * @return + */ + public static int uniquePaths(int m, int n) { + int[][] dp = new int[m][n]; + //初始化 + for (int i = 0; i < m; i++) { + dp[i][0] = 1; + } + for (int i = 0; i < n; i++) { + dp[0][i] = 1; + } + for (int i = 1; i < m; i++) { + for (int j = 1; j < n; j++) { + dp[i][j] = dp[i-1][j]+dp[i][j-1]; + } + } + return dp[m-1][n-1]; + } + +``` Python: - +```python +class Solution: # 动态规划 + def uniquePaths(self, m: int, n: int) -> int: + dp = [[0 for i in range(n)] for j in range(m)] + for i in range(m): dp[i][0] = 1 + for j in range(n): dp[0][j] = 1 + for i in range(1, m): + for j in range(1, n): + dp[i][j] = dp[i][j - 1] + dp[i - 1][j] + return dp[m - 1][n - 1] +``` Go: ```Go diff --git a/problems/0063.不同路径II.md b/problems/0063.不同路径II.md index 72189e0f..eeecad70 100644 --- a/problems/0063.不同路径II.md +++ b/problems/0063.不同路径II.md @@ -235,6 +235,49 @@ class Solution: Go: +```go +func uniquePathsWithObstacles(obstacleGrid [][]int) int { + m,n:= len(obstacleGrid),len(obstacleGrid[0]) + // 定义一个dp数组 + dp := make([][]int,m) + for i,_ := range dp { + dp[i] = make([]int,n) + } + // 初始化 + for i:=0;i()); return result; } - Arrays.sort(nums); subsetsHelper(nums, 0); return result; } diff --git a/problems/0110.平衡二叉树.md b/problems/0110.平衡二叉树.md index dfc27344..1cd54849 100644 --- a/problems/0110.平衡二叉树.md +++ b/problems/0110.平衡二叉树.md @@ -142,7 +142,7 @@ int getDepth(TreeNode* node) 2. 明确终止条件 -递归的过程中依然是遇到空节点了为终止,返回0,表示当前节点为根节点的书高度为0 +递归的过程中依然是遇到空节点了为终止,返回0,表示当前节点为根节点的树高度为0 代码如下: @@ -534,7 +534,34 @@ func abs(a int)int{ return a } ``` - +JavaScript: +```javascript +var isBalanced = function(root) { + //还是用递归三部曲 + 后序遍历 左右中 当前左子树右子树高度相差大于1就返回-1 + // 1. 确定递归函数参数以及返回值 + const getDepth=function(node){ + // 2. 确定递归函数终止条件 + if(node===null){ + return 0; + } + // 3. 确定单层递归逻辑 + let leftDepth=getDepth(node.left);//左子树高度 + if(leftDepth===-1){ + return -1; + } + let rightDepth=getDepth(node.right);//右子树高度 + if(rightDepth===-1){ + return -1; + } + if(Math.abs(leftDepth-rightDepth)>1){ + return -1; + }else{ + return 1+Math.max(leftDepth,rightDepth); + } + } + return getDepth(root)===-1?false:true; +}; +``` ----------------------- diff --git a/problems/0131.分割回文串.md b/problems/0131.分割回文串.md index 9b2401de..c722af37 100644 --- a/problems/0131.分割回文串.md +++ b/problems/0131.分割回文串.md @@ -292,7 +292,24 @@ class Solution { ``` Python: - +```python3 +class Solution: + def partition(self, s: str) -> List[List[str]]: + res = [] + path = [] #放已经回文的子串 + def backtrack(s,startIndex): + if startIndex >= len(s): #如果起始位置已经大于s的大小,说明已经找到了一组分割方案了 + return res.append(path[:]) + for i in range(startIndex,len(s)): + p = s[startIndex:i+1] #获取[startIndex,i+1]在s中的子串 + if p == p[::-1]: path.append(p) #是回文子串 + else: continue #不是回文,跳过 + backtrack(s,i+1) #寻找i+1为起始位置的子串 + path.pop() #回溯过程,弹出本次已经填在path的子串 + backtrack(s,0) + return res + +``` Go: diff --git a/problems/0150.逆波兰表达式求值.md b/problems/0150.逆波兰表达式求值.md index 618a6830..e38bc1a3 100644 --- a/problems/0150.逆波兰表达式求值.md +++ b/problems/0150.逆波兰表达式求值.md @@ -197,6 +197,32 @@ func evalRPN(tokens []string) int { } ``` +javaScript: + +```js + +/** + * @param {string[]} tokens + * @return {number} + */ +var evalRPN = function(tokens) { + const s = new Map([ + ["+", (a, b) => a * 1 + b * 1], + ["-", (a, b) => b - a], + ["*", (a, b) => b * a], + ["/", (a, b) => (b / a) | 0] + ]); + const stack = []; + for (const i of tokens) { + if(!s.has(i)) { + stack.push(i); + continue; + } + stack.push(s.get(i)(stack.pop(),stack.pop())) + } + return stack.pop(); +}; +``` ----------------------- diff --git a/problems/0202.快乐数.md b/problems/0202.快乐数.md index 06a6914c..c07405ec 100644 --- a/problems/0202.快乐数.md +++ b/problems/0202.快乐数.md @@ -22,13 +22,13 @@ https://leetcode-cn.com/problems/happy-number/ **示例:** -输入:19 -输出:true -解释: -1^2 + 9^2 = 82 -8^2 + 2^2 = 68 -6^2 + 8^2 = 100 -1^2 + 0^2 + 0^2 = 1 +输入:19 +输出:true +解释: +1^2 + 9^2 = 82 +8^2 + 2^2 = 68 +6^2 + 8^2 = 100 +1^2 + 0^2 + 0^2 = 1 # 思路 @@ -36,7 +36,7 @@ https://leetcode-cn.com/problems/happy-number/ 题目中说了会 **无限循环**,那么也就是说**求和的过程中,sum会重复出现,这对解题很重要!** -正如:[关于哈希表,你该了解这些!](https://mp.weixin.qq.com/s/g8N6WmoQmsCUw3_BaWxHZA)中所说,**当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。** +正如:[关于哈希表,你该了解这些!](https://mp.weixin.qq.com/s/RSUANESA_tkhKhYe3ZR8Jg)中所说,**当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。** 所以这道题目使用哈希法,来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止。 @@ -80,7 +80,7 @@ public: -## 其他语言版本 +# 其他语言版本 Java: diff --git a/problems/0203.移除链表元素.md b/problems/0203.移除链表元素.md index 7735f6c4..dce5d265 100644 --- a/problems/0203.移除链表元素.md +++ b/problems/0203.移除链表元素.md @@ -15,7 +15,18 @@ https://leetcode-cn.com/problems/remove-linked-list-elements/ 题意:删除链表中等于给定值 val 的所有节点。 -![203题目示例](https://img-blog.csdnimg.cn/20200814104441179.png) +示例 1: +输入:head = [1,2,6,3,4,5,6], val = 6 +输出:[1,2,3,4,5] + +示例 2: +输入:head = [], val = 1 +输出:[] + +示例 3: +输入:head = [7,7,7,7], val = 7 +输出:[] + # 思路 @@ -201,6 +212,29 @@ Python: Go: +```go +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +func removeElements(head *ListNode, val int) *ListNode { + dummyHead := &ListNode{} + dummyHead.Next = head + cur := dummyHead + for cur != nil && cur.Next != nil { + if cur.Next.Val == val { + cur.Next = cur.Next.Next + } else { + cur = cur.Next + } + } + return dummyHead.Next +} +``` + javaScript: ```js diff --git a/problems/0209.长度最小的子数组.md b/problems/0209.长度最小的子数组.md index bd25083e..90280451 100644 --- a/problems/0209.长度最小的子数组.md +++ b/problems/0209.长度最小的子数组.md @@ -116,26 +116,6 @@ public: 不要以为for里放一个while就以为是$O(n^2)$啊, 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被被操作两次,所以时间复杂度是2 * n 也就是$O(n)$。 -## 其他语言补充 - -python: - -```python -class Solution: - def minSubArrayLen(self, s: int, nums: List[int]) -> int: - # 定义一个无限大的数 - res = float("inf") - Sum = 0 - index = 0 - for i in range(len(nums)): - Sum += nums[i] - while Sum >= s: - res = min(res, i-index+1) - Sum -= nums[index] - index += 1 - return 0 if res==float("inf") else res -``` - ## 相关题目推荐 * 904.水果成篮 @@ -170,6 +150,22 @@ class Solution { Python: +```python +class Solution: + def minSubArrayLen(self, s: int, nums: List[int]) -> int: + # 定义一个无限大的数 + res = float("inf") + Sum = 0 + index = 0 + for i in range(len(nums)): + Sum += nums[i] + while Sum >= s: + res = min(res, i-index+1) + Sum -= nums[index] + index += 1 + return 0 if res==float("inf") else res +``` + Go: ```go diff --git a/problems/0222.完全二叉树的节点个数.md b/problems/0222.完全二叉树的节点个数.md index 5a3cfcbc..2e2fed99 100644 --- a/problems/0222.完全二叉树的节点个数.md +++ b/problems/0222.完全二叉树的节点个数.md @@ -243,6 +243,74 @@ Python: Go: +JavaScript: + +递归版本 +```javascript +var countNodes = function(root) { + //递归法计算二叉树节点数 + // 1. 确定递归函数参数 + const getNodeSum=function(node){ + //2. 确定终止条件 + if(node===null){ + return 0; + } + //3. 确定单层递归逻辑 + let leftNum=getNodeSum(node.left); + let rightNum=getNodeSum(node.right); + return leftNum+rightNum+1; + } + return getNodeSum(root); +}; +``` + +迭代(层序遍历)版本 +```javascript +var countNodes = function(root) { + //层序遍历 + let queue=[]; + if(root===null){ + return 0; + } + queue.push(root); + let nodeNums=0; + while(queue.length){ + let length=queue.length; + while(length--){ + let node=queue.shift(); + nodeNums++; + node.left&&queue.push(node.left); + node.right&&queue.push(node.right); + } + } + return nodeNums; +}; +``` + +利用完全二叉树性质 +```javascript +var countNodes = function(root) { + //利用完全二叉树的特点 + if(root===null){ + return 0; + } + let left=root.left; + let right=root.right; + let leftHeight=0,rightHeight=0; + while(left){ + left=left.left; + leftHeight++; + } + while(right){ + right=right.right; + rightHeight++; + } + if(leftHeight==rightHeight){ + return Math.pow(2,leftHeight+1)-1; + } + return countNodes(root.left)+countNodes(root.right)+1; +}; +``` diff --git a/problems/0225.用队列实现栈.md b/problems/0225.用队列实现栈.md index e045229f..055c2e3d 100644 --- a/problems/0225.用队列实现栈.md +++ b/problems/0225.用队列实现栈.md @@ -357,8 +357,115 @@ class MyStack: Go: +javaScript: +使用数组(push, shift)模拟队列 +```js + +// 使用两个队列实现 +/** + * Initialize your data structure here. + */ +var MyStack = function() { + this.queue1 = []; + this.queue2 = []; +}; + +/** + * Push element x onto stack. + * @param {number} x + * @return {void} + */ +MyStack.prototype.push = function(x) { + this.queue1.push(x); +}; + +/** + * Removes the element on top of the stack and returns that element. + * @return {number} + */ +MyStack.prototype.pop = function() { + // 减少两个队列交换的次数, 只有当queue1为空时,交换两个队列 + if(!this.queue1.length) { + [this.queue1, this.queue2] = [this.queue2, this.queue1]; + } + while(this.queue1.length > 1) { + this.queue2.push(this.queue1.shift()); + } + return this.queue1.shift(); +}; + +/** + * Get the top element. + * @return {number} + */ +MyStack.prototype.top = function() { + const x = this.pop(); + this.queue1.push(x); + return x; +}; + +/** + * Returns whether the stack is empty. + * @return {boolean} + */ +MyStack.prototype.empty = function() { + return !this.queue1.length && !this.queue2.length; +}; + +``` + +```js + +// 使用一个队列实现 +/** + * Initialize your data structure here. + */ +var MyStack = function() { + this.queue = []; +}; + +/** + * Push element x onto stack. + * @param {number} x + * @return {void} + */ +MyStack.prototype.push = function(x) { + this.queue.push(x); +}; + +/** + * Removes the element on top of the stack and returns that element. + * @return {number} + */ +MyStack.prototype.pop = function() { + let size = this.queue.length; + while(size-- > 1) { + this.queue.push(this.queue.shift()); + } + return this.queue.shift(); +}; + +/** + * Get the top element. + * @return {number} + */ +MyStack.prototype.top = function() { + const x = this.pop(); + this.queue.push(x); + return x; +}; + +/** + * Returns whether the stack is empty. + * @return {boolean} + */ +MyStack.prototype.empty = function() { + return !this.queue.length; +}; + +``` ----------------------- * 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw) diff --git a/problems/0232.用栈实现队列.md b/problems/0232.用栈实现队列.md index 7c91a0dd..10314a08 100644 --- a/problems/0232.用栈实现队列.md +++ b/problems/0232.用栈实现队列.md @@ -353,6 +353,61 @@ func (this *MyQueue) Empty() bool { */ ``` + javaScript: + + ```js + // 使用两个数组的栈方法(push, pop) 实现队列 + /** + * Initialize your data structure here. + */ +var MyQueue = function() { + this.stack1 = []; + this.stack2 = []; +}; + +/** + * Push element x to the back of queue. + * @param {number} x + * @return {void} + */ +MyQueue.prototype.push = function(x) { + this.stack1.push(x); +}; + +/** + * Removes the element from in front of queue and returns that element. + * @return {number} + */ +MyQueue.prototype.pop = function() { + const size = this.stack2.length; + if(size) { + return this.stack2.pop(); + } + while(this.stack1.length) { + this.stack2.push(this.stack1.pop()); + } + return this.stack2.pop(); +}; + +/** + * Get the front element. + * @return {number} + */ +MyQueue.prototype.peek = function() { + const x = this.pop(); + this.stack2.push(x); + return x; +}; + +/** + * Returns whether the queue is empty. + * @return {boolean} + */ +MyQueue.prototype.empty = function() { + return !this.stack1.length && !this.stack2.length +}; + ``` + diff --git a/problems/0257.二叉树的所有路径.md b/problems/0257.二叉树的所有路径.md index 964bd7fd..fe7a2604 100644 --- a/problems/0257.二叉树的所有路径.md +++ b/problems/0257.二叉树的所有路径.md @@ -351,6 +351,30 @@ class Solution: ``` Go: +JavaScript: +1.递归版本 +```javascript +var binaryTreePaths = function(root) { + //递归遍历+递归三部曲 + let res=[]; + //1. 确定递归函数 函数参数 + const getPath=function(node,curPath){ + //2. 确定终止条件,到叶子节点就终止 + if(node.left===null&&node.right===null){ + curPath+=node.val; + res.push(curPath); + return ; + } + //3. 确定单层递归逻辑 + curPath+=node.val+'->'; + node.left&&getPath(node.left,curPath); + node.right&&getPath(node.right,curPath); + } + getPath(root,''); + return res; +}; +``` + diff --git a/problems/0343.整数拆分.md b/problems/0343.整数拆分.md index a6bd7211..c9423a1a 100644 --- a/problems/0343.整数拆分.md +++ b/problems/0343.整数拆分.md @@ -194,7 +194,23 @@ public: Java: - +```Java +class Solution { + public int integerBreak(int n) { + //dp[i]为正整数i拆分结果的最大乘积 + int[] dp = new int[n+1]; + dp[2] = 1; + for (int i = 3; i <= n; ++i) { + for (int j = 1; j < i - 1; ++j) { + //j*(i-j)代表把i拆分为j和i-j两个数相乘 + //j*dp[i-j]代表把i拆分成j和继续把(i-j)这个数拆分,取(i-j)拆分结果中的最大乘积与j相乘 + dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j])); + } + } + return dp[n]; + } +} +``` Python: diff --git a/problems/0349.两个数组的交集.md b/problems/0349.两个数组的交集.md index 46e15482..fe019a0a 100644 --- a/problems/0349.两个数组的交集.md +++ b/problems/0349.两个数组的交集.md @@ -118,6 +118,17 @@ class Solution { ``` Python: +```python3 +class Solution: + def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]: + result_set = set() + + set1 = set(nums1) + for num in nums2: + if num in set1: + result_set.add(num) # set1里出现的nums2元素 存放到结果 + return result_set +``` Go: diff --git a/problems/0494.目标和.md b/problems/0494.目标和.md index 84f99b1d..a9ddc768 100644 --- a/problems/0494.目标和.md +++ b/problems/0494.目标和.md @@ -19,15 +19,15 @@ 示例: -输入:nums: [1, 1, 1, 1, 1], S: 3 -输出:5 -解释: +输入:nums: [1, 1, 1, 1, 1], S: 3 +输出:5 --1+1+1+1+1 = 3 -+1-1+1+1+1 = 3 -+1+1-1+1+1 = 3 -+1+1+1-1+1 = 3 -+1+1+1+1-1 = 3 +解释: +-1+1+1+1+1 = 3 ++1-1+1+1+1 = 3 ++1+1-1+1+1 = 3 ++1+1+1-1+1 = 3 ++1+1+1+1-1 = 3 一共有5种方法让最终目标和为3。 diff --git a/problems/0669.修剪二叉搜索树.md b/problems/0669.修剪二叉搜索树.md index 0b49bea2..06d99b9d 100644 --- a/problems/0669.修剪二叉搜索树.md +++ b/problems/0669.修剪二叉搜索树.md @@ -265,7 +265,9 @@ class Solution { ``` Python: + ```python3 + # Definition for a binary tree node. # class TreeNode: # def __init__(self, val=0, left=None, right=None): diff --git a/problems/0707.设计链表.md b/problems/0707.设计链表.md index 2d76fffc..2fa1af29 100644 --- a/problems/0707.设计链表.md +++ b/problems/0707.设计链表.md @@ -158,6 +158,14 @@ private: Java: ```Java +class ListNode { +int val; +ListNode next; +ListNode(){} +ListNode(int val) { +this.val=val; +} +} class MyLinkedList { //size存储链表元素的个数 int size; diff --git a/problems/0746.使用最小花费爬楼梯.md b/problems/0746.使用最小花费爬楼梯.md index 5ddcae0f..1e8e8038 100644 --- a/problems/0746.使用最小花费爬楼梯.md +++ b/problems/0746.使用最小花费爬楼梯.md @@ -225,7 +225,16 @@ class Solution { ``` Python: - +```python +class Solution: + def minCostClimbingStairs(self, cost: List[int]) -> int: + dp = [0] * (len(cost)) + dp[0] = cost[0] + dp[1] = cost[1] + for i in range(2, len(cost)): + dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i] + return min(dp[len(cost) - 1], dp[len(cost) - 2]) +``` Go: ```Go diff --git a/problems/0977.有序数组的平方.md b/problems/0977.有序数组的平方.md new file mode 100644 index 00000000..167a258c --- /dev/null +++ b/problems/0977.有序数组的平方.md @@ -0,0 +1,112 @@ +

+ + + + +

+

欢迎大家参与本项目,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!

+ +> 双指针风骚起来,也是无敌 + +# 977.有序数组的平方 + +https://leetcode-cn.com/problems/squares-of-a-sorted-array/ + +给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。 + +示例 1: +输入:nums = [-4,-1,0,3,10] +输出:[0,1,9,16,100] +解释:平方后,数组变为 [16,1,0,9,100],排序后,数组变为 [0,1,9,16,100] + +示例 2: +输入:nums = [-7,-3,2,3,11] +输出:[4,9,9,49,121] + +# 思路 + +## 暴力排序 + +最直观的相反,莫过于:每个数平方之后,排个序,美滋滋,代码如下: + +```C++ +class Solution { +public: + vector sortedSquares(vector& A) { + for (int i = 0; i < A.size(); i++) { + A[i] *= A[i]; + } + sort(A.begin(), A.end()); // 快速排序 + return A; + } +}; +``` + +这个时间复杂度是 O(n + nlogn), 可以说是O(nlogn)的时间复杂度,但为了和下面双指针法算法时间复杂度有鲜明对比,我记为 O(n + nlogn)。 + +## 双指针法 + +数组其实是有序的, 只不过负数平方之后可能成为最大数了。 + +那么数组平方的最大值就在数组的两端,不是最左边就是最右边,不可能是中间。 + +此时可以考虑双指针法了,i指向起始位置,j指向终止位置。 + +定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。 + +如果`A[i] * A[i] < A[j] * A[j]` 那么`result[k--] = A[j] * A[j];` 。 + +如果`A[i] * A[i] >= A[j] * A[j]` 那么`result[k--] = A[i] * A[i];` 。 + +如动画所示: + +![](https://code-thinking.cdn.bcebos.com/gifs/977.有序数组的平方.gif) + +不难写出如下代码: + +```C++ +class Solution { +public: + vector sortedSquares(vector& A) { + int k = A.size() - 1; + vector result(A.size(), 0); + for (int i = 0, j = A.size() - 1; i <= j;) { // 注意这里要i <= j,因为最后要处理两个元素 + if (A[i] * A[i] < A[j] * A[j]) { + result[k--] = A[j] * A[j]; + j--; + } + else { + result[k--] = A[i] * A[i]; + i++; + } + } + return result; + } +}; +``` + +此时的时间复杂度为O(n),相对于暴力排序的解法O(n + nlogn)还是提升不少的。 + + +**这里还是说一下,大家不必太在意leetcode上执行用时,打败多少多少用户,这个就是一个玩具,非常不准确。** + +做题的时候自己能分析出来时间复杂度就可以了,至于leetcode上执行用时,大概看一下就行,只要达到最优的时间复杂度就可以了, + +一样的代码多提交几次可能就击败百分之百了..... + +## 其他语言版本 + + +Java: + +Python: + + +Go: + + +----------------------- +* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw) +* B站视频:[代码随想录](https://space.bilibili.com/525438321) +* 知识星球:[代码随想录](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) +
diff --git a/problems/1047.删除字符串中的所有相邻重复项.md b/problems/1047.删除字符串中的所有相邻重复项.md index 8b761be7..9ca08c96 100644 --- a/problems/1047.删除字符串中的所有相邻重复项.md +++ b/problems/1047.删除字符串中的所有相邻重复项.md @@ -186,6 +186,24 @@ class Solution: Go: +javaScript: + +```js +/** + * @param {string} s + * @return {string} + */ +var removeDuplicates = function(s) { + const stack = []; + for(const x of s) { + let c = null; + if(stack.length && x === (c = stack.pop())) continue; + c && stack.push(c); + stack.push(x); + } + return stack.join(""); +}; +``` diff --git a/problems/算法模板.md b/problems/算法模板.md index 3b9eee8c..888ae773 100644 --- a/problems/算法模板.md +++ b/problems/算法模板.md @@ -82,13 +82,13 @@ void traversal(TreeNode* cur, vector& vec) { traversal(cur->right, vec); // 右 } ``` -前序遍历(中左右) +后序遍历(左右中) ``` void traversal(TreeNode* cur, vector& vec) { if (cur == NULL) return; - vec.push_back(cur->val); // 中 ,同时也是处理节点逻辑的地方 traversal(cur->left, vec); // 左 traversal(cur->right, vec); // 右 + vec.push_back(cur->val); // 中 ,同时也是处理节点逻辑的地方 } ``` diff --git a/problems/背包总结篇.md b/problems/背包总结篇.md index c04dfbec..0dd407ac 100644 --- a/problems/背包总结篇.md +++ b/problems/背包总结篇.md @@ -95,18 +95,6 @@ -## 其他语言版本 - - -Java: - - -Python: - - -Go: - - -----------------------