diff --git a/problems/0027.移除元素.md b/problems/0027.移除元素.md index 78f9afb7..4afd347a 100644 --- a/problems/0027.移除元素.md +++ b/problems/0027.移除元素.md @@ -185,7 +185,7 @@ func removeElement(nums []int, val int) int { ``` JavaScript: -``` +```javascript //时间复杂度O(n) //空间复杂度O(1) var removeElement = (nums, val) => { diff --git a/problems/0077.组合.md b/problems/0077.组合.md index 8ce1497b..c63e45f5 100644 --- a/problems/0077.组合.md +++ b/problems/0077.组合.md @@ -368,6 +368,34 @@ class Solution { } ``` +Python2: +```python +class Solution(object): + def combine(self, n, k): + """ + :type n: int + :type k: int + :rtype: List[List[int]] + """ + result = [] + path = [] + def backtracking(n, k, startidx): + if len(path) == k: + result.append(path[:]) + return + + # 剪枝, 最后k - len(path)个节点直接构造结果,无需递归 + last_startidx = n - (k - len(path)) + 1 + result.append(path + [idx for idx in range(last_startidx, n + 1)]) + + for x in range(startidx, last_startidx): + path.append(x) + backtracking(n, k, x + 1) # 递归 + path.pop() # 回溯 + + backtracking(n, k, 1) + return result +``` ## Python ```python diff --git a/problems/0078.子集.md b/problems/0078.子集.md index fb4a8740..747b89d1 100644 --- a/problems/0078.子集.md +++ b/problems/0078.子集.md @@ -263,6 +263,63 @@ var subsets = function(nums) { }; ``` +C: +```c +int* path; +int pathTop; +int** ans; +int ansTop; +//记录二维数组中每个一维数组的长度 +int* length; +//将当前path数组复制到ans中 +void copy() { + int* tempPath = (int*)malloc(sizeof(int) * pathTop); + int i; + for(i = 0; i < pathTop; i++) { + tempPath[i] = path[i]; + } + ans = (int**)realloc(ans, sizeof(int*) * (ansTop+1)); + length[ansTop] = pathTop; + ans[ansTop++] = tempPath; +} + +void backTracking(int* nums, int numsSize, int startIndex) { + //收集子集,要放在终止添加的上面,否则会漏掉自己 + copy(); + //若startIndex大于数组大小,返回 + if(startIndex >= numsSize) { + return; + } + int j; + for(j = startIndex; j < numsSize; j++) { + //将当前下标数字放入path中 + path[pathTop++] = nums[j]; + backTracking(nums, numsSize, j+1); + //回溯 + pathTop--; + } +} + +int** subsets(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){ + //初始化辅助变量 + path = (int*)malloc(sizeof(int) * numsSize); + ans = (int**)malloc(0); + length = (int*)malloc(sizeof(int) * 1500); + ansTop = pathTop = 0; + //进入回溯 + backTracking(nums, numsSize, 0); + //设置二维数组中元素个数 + *returnSize = ansTop; + //设置二维数组中每个一维数组的长度 + *returnColumnSizes = (int*)malloc(sizeof(int) * ansTop); + int i; + for(i = 0; i < ansTop; i++) { + (*returnColumnSizes)[i] = length[i]; + } + return ans; +} +``` + ----------------------- * 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw) diff --git a/problems/0093.复原IP地址.md b/problems/0093.复原IP地址.md index 6d01319a..52db821a 100644 --- a/problems/0093.复原IP地址.md +++ b/problems/0093.复原IP地址.md @@ -476,6 +476,82 @@ func isNormalIp(s string,startIndex,end int)bool{ ``` +C: +```c +//记录结果 +char** result; +int resultTop; +//记录应该加入'.'的位置 +int segments[3]; +int isValid(char* s, int start, int end) { + if(start > end) + return 0; + if (s[start] == '0' && start != end) { // 0开头的数字不合法 + return false; + } + int num = 0; + for (int i = start; i <= end; i++) { + if (s[i] > '9' || s[i] < '0') { // 遇到非数字字符不合法 + return false; + } + num = num * 10 + (s[i] - '0'); + if (num > 255) { // 如果大于255了不合法 + return false; + } + } + return true; +} + +//startIndex为起始搜索位置,pointNum为'.'对象 +void backTracking(char* s, int startIndex, int pointNum) { + //若'.'数量为3,分隔结束 + if(pointNum == 3) { + //若最后一段字符串符合要求,将当前的字符串放入result种 + if(isValid(s, startIndex, strlen(s) - 1)) { + char* tempString = (char*)malloc(sizeof(char) * strlen(s) + 4); + int j; + //记录添加字符时tempString的下标 + int count = 0; + //记录添加字符时'.'的使用数量 + int count1 = 0; + for(j = 0; j < strlen(s); j++) { + tempString[count++] = s[j]; + //若'.'的使用数量小于3且当前下标等于'.'下标,添加'.'到数组 + if(count1 < 3 && j == segments[count1]) { + tempString[count++] = '.'; + count1++; + } + } + tempString[count] = 0; + //扩容result数组 + result = (char**)realloc(result, sizeof(char*) * (resultTop + 1)); + result[resultTop++] = tempString; + } + return ; + } + + int i; + for(i = startIndex; i < strlen(s); i++) { + if(isValid(s, startIndex, i)) { + //记录应该添加'.'的位置 + segments[pointNum] = i; + backTracking(s, i + 1, pointNum + 1); + } + else { + break; + } + } +} + +char ** restoreIpAddresses(char * s, int* returnSize){ + result = (char**)malloc(0); + resultTop = 0; + backTracking(s, 0, 0); + *returnSize = resultTop; + return result; +} +``` + ----------------------- * 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw) diff --git a/problems/0101.对称二叉树.md b/problems/0101.对称二叉树.md index 03d3acaa..3abf26cb 100644 --- a/problems/0101.对称二叉树.md +++ b/problems/0101.对称二叉树.md @@ -185,7 +185,8 @@ public: queue que; que.push(root->left); // 将左子树头结点加入队列 que.push(root->right); // 将右子树头结点加入队列 - while (!que.empty()) { // 接下来就要判断这这两个树是否相互翻转 + + while (!que.empty()) { // 接下来就要判断这两个树是否相互翻转 TreeNode* leftNode = que.front(); que.pop(); TreeNode* rightNode = que.front(); que.pop(); if (!leftNode && !rightNode) { // 左节点为空、右节点为空,此时说明是对称的 diff --git a/problems/0188.买卖股票的最佳时机IV.md b/problems/0188.买卖股票的最佳时机IV.md index bcb8a1ab..a166db72 100644 --- a/problems/0188.买卖股票的最佳时机IV.md +++ b/problems/0188.买卖股票的最佳时机IV.md @@ -280,6 +280,7 @@ Go: Javascript: ```javascript +// 方法一:动态规划 const maxProfit = (k,prices) => { if (prices == null || prices.length < 2 || k == 0) { return 0; @@ -300,6 +301,30 @@ const maxProfit = (k,prices) => { return dp[prices.length - 1][2 * k]; }; + +// 方法二:动态规划+空间优化 +var maxProfit = function(k, prices) { + let n = prices.length; + let dp = new Array(2*k+1).fill(0); + // dp 买入状态初始化 + for (let i = 1; i <= 2*k; i += 2) { + dp[i] = - prices[0]; + } + + for (let i = 1; i < n; i++) { + for (let j = 1; j < 2*k+1; j++) { + // j 为奇数:买入状态 + if (j % 2) { + dp[j] = Math.max(dp[j], dp[j-1] - prices[i]); + } else { + // j为偶数:卖出状态 + dp[j] = Math.max(dp[j], dp[j-1] + prices[i]); + } + } + } + + return dp[2*k]; +}; ``` ----------------------- diff --git a/problems/0202.快乐数.md b/problems/0202.快乐数.md index 710c824d..02db507a 100644 --- a/problems/0202.快乐数.md +++ b/problems/0202.快乐数.md @@ -159,26 +159,28 @@ func getSum(n int) int { javaScript: ```js -function getN(n) { - if (n == 1 || n == 0) return n; - let res = 0; - while (n) { - res += (n % 10) * (n % 10); - n = parseInt(n / 10); +var isHappy = function (n) { + let m = new Map() + + const getSum = (num) => { + let sum = 0 + while (n) { + sum += (n % 10) ** 2 + n = Math.floor(n / 10) + } + return sum + } + + while (true) { + // n出现过,证明已陷入无限循环 + if (m.has(n)) return false + if (n === 1) return true + m.set(n, 1) + n = getSum(n) } - return res; } -var isHappy = function(n) { - const sumSet = new Set(); - while (n != 1 && !sumSet.has(n)) { - sumSet.add(n); - n = getN(n); - } - return n == 1; -}; - -// 使用环形链表的思想 说明出现闭环 退出循环 +// 方法二:使用环形链表的思想 说明出现闭环 退出循环 var isHappy = function(n) { if (getN(n) == 1) return true; let a = getN(n), b = getN(getN(n)); diff --git a/problems/0235.二叉搜索树的最近公共祖先.md b/problems/0235.二叉搜索树的最近公共祖先.md index 25bbf7e4..a828096c 100644 --- a/problems/0235.二叉搜索树的最近公共祖先.md +++ b/problems/0235.二叉搜索树的最近公共祖先.md @@ -268,17 +268,30 @@ class Solution { 递归法: ```python class Solution: + """二叉搜索树的最近公共祖先 递归法""" + def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': - if not root: return root //中 - if root.val >p.val and root.val > q.val: - return self.lowestCommonAncestor(root.left,p,q) //左 - elif root.val < p.val and root.val < q.val: - return self.lowestCommonAncestor(root.right,p,q) //右 - else: return root + if root.val > p.val and root.val > q.val: + return self.lowestCommonAncestor(root.left, p, q) + if root.val < p.val and root.val < q.val: + return self.lowestCommonAncestor(root.right, p, q) + return root ``` 迭代法: +```python +class Solution: + """二叉搜索树的最近公共祖先 迭代法""" + def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': + while True: + if root.val > p.val and root.val > q.val: + root = root.left + elif root.val < p.val and root.val < q.val: + root = root.right + else: + return root +``` ## Go diff --git a/problems/0236.二叉树的最近公共祖先.md b/problems/0236.二叉树的最近公共祖先.md index 59345a24..46dcb545 100644 --- a/problems/0236.二叉树的最近公共祖先.md +++ b/problems/0236.二叉树的最近公共祖先.md @@ -264,16 +264,21 @@ class Solution { ## Python ```python -//递归 class Solution: + """二叉树的最近公共祖先 递归法""" + def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': - if not root or root == p or root == q: return root //找到了节点p或者q,或者遇到空节点 - left = self.lowestCommonAncestor(root.left,p,q) //左 - right = self.lowestCommonAncestor(root.right,p,q) //右 - if left and right: return root //中: left和right不为空,root就是最近公共节点 - elif left and not right: return left //目标节点是通过left返回的 - elif not left and right: return right //目标节点是通过right返回的 - else: return None //没找到 + if not root or root == p or root == q: + return root + + left = self.lowestCommonAncestor(root.left, p, q) + right = self.lowestCommonAncestor(root.right, p, q) + + if left and right: + return root + if left: + return left + return right ``` ## Go diff --git a/problems/0455.分发饼干.md b/problems/0455.分发饼干.md index 8e20c402..bae1566c 100644 --- a/problems/0455.分发饼干.md +++ b/problems/0455.分发饼干.md @@ -217,6 +217,29 @@ var findContentChildren = function(g, s) { ``` +C: +```c +int cmp(int* a, int* b) { + return *a - *b; +} + +int findContentChildren(int* g, int gSize, int* s, int sSize){ + if(sSize == 0) + return 0; + + //将两个数组排序为升序 + qsort(g, gSize, sizeof(int), cmp); + qsort(s, sSize, sizeof(int), cmp); + + int numFedChildren = 0; + int i = 0; + for(i = 0; i < sSize; ++i) { + if(numFedChildren < gSize && g[numFedChildren] <= s[i]) + numFedChildren++; + } + return numFedChildren; +} +``` ----------------------- * 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw) diff --git a/problems/0718.最长重复子数组.md b/problems/0718.最长重复子数组.md index 9e3da663..712b5eeb 100644 --- a/problems/0718.最长重复子数组.md +++ b/problems/0718.最长重复子数组.md @@ -278,7 +278,26 @@ const findLength = (A, B) => { return res; }; ``` - +> 滚动数组 +```javascript +const findLength = (nums1, nums2) => { + let len1 = nums1.length, len2 = nums2.length; + // dp[i][j]: 以nums1[i-1]、nums2[j-1]为结尾的最长公共子数组的长度 + let dp = new Array(len2+1).fill(0); + let res = 0; + for (let i = 1; i <= len1; i++) { + for (let j = len2; j > 0; j--) { + if (nums1[i-1] === nums2[j-1]) { + dp[j] = dp[j-1] + 1; + } else { + dp[j] = 0; + } + res = Math.max(res, dp[j]); + } + } + return res; +} +``` ----------------------- diff --git a/problems/0739.每日温度.md b/problems/0739.每日温度.md index b00701ed..53ce1133 100644 --- a/problems/0739.每日温度.md +++ b/problems/0739.每日温度.md @@ -276,6 +276,36 @@ func dailyTemperatures(num []int) []int { } ``` +JavaScript: +```javascript +/** + * @param {number[]} temperatures + * @return {number[]} + */ +var dailyTemperatures = function(temperatures) { + let n = temperatures.length; + let res = new Array(n).fill(0); + let stack = []; // 递减栈:用于存储元素右面第一个比他大的元素下标 + stack.push(0); + for (let i = 1; i < n; i++) { + // 栈顶元素 + let top = stack[stack.length - 1]; + if (temperatures[i] < temperatures[top]) { + stack.push(i); + } else if (temperatures[i] === temperatures[top]) { + stack.push(i); + } else { + while (stack.length && temperatures[i] > temperatures[stack[stack.length - 1]]) { + let top = stack.pop(); + res[top] = i - top; + } + stack.push(i); + } + } + return res; +}; +``` + ----------------------- diff --git a/problems/0841.钥匙和房间.md b/problems/0841.钥匙和房间.md index 4a0185ec..caa0edaf 100644 --- a/problems/0841.钥匙和房间.md +++ b/problems/0841.钥匙和房间.md @@ -121,10 +121,109 @@ public: Java: +```java +class Solution { + private void dfs(int key, List> rooms, List visited) { + if (visited.get(key)) { + return; + } + + visited.set(key, true); + for (int k : rooms.get(key)) { + // 深度优先搜索遍历 + dfs(k, rooms, visited); + } + } + + + public boolean canVisitAllRooms(List> rooms) { + List visited = new ArrayList(){{ + for(int i = 0 ; i < rooms.size(); i++){ + add(false); + } + }}; + + dfs(0, rooms, visited); + + //检查是否都访问到了 + for (boolean flag : visited) { + if (!flag) { + return false; + } + } + return true; + } +} +``` + + + + Python: +python3 + +```python + +class Solution: + + def dfs(self, key: int, rooms: List[List[int]] , visited : List[bool] ) : + if visited[key] : + return + + visited[key] = True + keys = rooms[key] + for i in range(len(keys)) : + # 深度优先搜索遍历 + self.dfs(keys[i], rooms, visited) + + def canVisitAllRooms(self, rooms: List[List[int]]) -> bool: + visited = [False for i in range(len(rooms))] + + self.dfs(0, rooms, visited) + + # 检查是否都访问到了 + for i in range(len(visited)): + if not visited[i] : + return False + return True + +``` + + Go: +```go + +func dfs(key int, rooms [][]int, visited []bool ) { + if visited[key] { + return; + } + + visited[key] = true + keys := rooms[key] + for _ , key := range keys { + // 深度优先搜索遍历 + dfs(key, rooms, visited); + } +} + +func canVisitAllRooms(rooms [][]int) bool { + + visited := make([]bool, len(rooms)); + + dfs(0, rooms, visited); + + //检查是否都访问到了 + for i := 0; i < len(visited); i++ { + if !visited[i] { + return false; + } + } + return true; +} +``` + JavaScript: ----------------------- diff --git a/problems/0844.比较含退格的字符串.md b/problems/0844.比较含退格的字符串.md index e6bf3493..74455ace 100644 --- a/problems/0844.比较含退格的字符串.md +++ b/problems/0844.比较含退格的字符串.md @@ -188,8 +188,49 @@ class Solution { Python: +python3 + +```python +class Solution: + + def get_string(self, s: str) -> str : + bz = [] + for i in range(len(s)) : + c = s[i] + if c != '#' : + bz.append(c) # 模拟入栈 + elif len(bz) > 0: # 栈非空才能弹栈 + bz.pop() # 模拟弹栈 + return str(bz) + + def backspaceCompare(self, s: str, t: str) -> bool: + return self.get_string(s) == self.get_string(t) + pass +``` + + Go: +```go + +func getString(s string) string { + bz := []rune{} + for _, c := range s { + if c != '#' { + bz = append(bz, c); // 模拟入栈 + } else if len(bz) > 0 { // 栈非空才能弹栈 + bz = bz[:len(bz)-1] // 模拟弹栈 + } + } + return string(bz) +} + +func backspaceCompare(s string, t string) bool { + return getString(s) == getString(t) +} + +``` + JavaScript: ----------------------- diff --git a/problems/0922.按奇偶排序数组II.md b/problems/0922.按奇偶排序数组II.md index 97d7091e..5b66247e 100644 --- a/problems/0922.按奇偶排序数组II.md +++ b/problems/0922.按奇偶排序数组II.md @@ -11,6 +11,8 @@ # 922. 按奇偶排序数组II +[力扣题目链接](https://leetcode-cn.com/problems/sort-array-by-parity-ii/) + 给定一个非负整数数组 A, A 中一半整数是奇数,一半整数是偶数。 对数组进行排序,以便当 A[i] 为奇数时,i 也是奇数;当 A[i] 为偶数时, i 也是偶数。 @@ -147,9 +149,9 @@ class Solution { } ``` -## Python +## Python3 -```python3 +```python #方法2 class Solution: def sortArrayByParityII(self, nums: List[int]) -> List[int]: @@ -180,6 +182,28 @@ class Solution: ## Go ```go + +// 方法一 +func sortArrayByParityII(nums []int) []int { + // 分别存放 nums 中的奇数、偶数 + even, odd := []int{}, []int{} + for i := 0; i < len(nums); i++ { + if (nums[i] % 2 == 0) { + even = append(even, nums[i]) + } else { + odd = append(odd, nums[i]) + } + } + + // 把奇偶数组重新存回 nums + result := make([]int, len(nums)) + index := 0 + for i := 0; i < len(even); i++ { + result[index] = even[i]; index++; + result[index] = odd[i]; index++; + } + return result; +} ``` ## JavaScript diff --git a/problems/0925.长按键入.md b/problems/0925.长按键入.md index 3502f2fb..70597508 100644 --- a/problems/0925.长按键入.md +++ b/problems/0925.长按键入.md @@ -134,7 +134,7 @@ Python: class Solution: def isLongPressedName(self, name: str, typed: str) -> bool: i, j = 0, 0 - m, n = len(name) , len(typed) + m, n = len(name) , len(typed) while i< m and j < n: if name[i] == typed[j]: # 相同时向后匹配 i += 1 @@ -155,8 +155,32 @@ class Solution: else: return False return True ``` + Go: +```go + +func isLongPressedName(name string, typed string) bool { + if(name[0] != typed[0] || len(name) > len(typed)) { + return false; + } + + idx := 0 // name的索引 + var last byte // 上个匹配字符 + for i := 0; i < len(typed); i++ { + if idx < len(name) && name[idx] == typed[i] { + last = name[idx] + idx++ + } else if last == typed[i] { + continue + } else { + return false + } + } + return idx == len(name) +} +``` + JavaScript: ----------------------- diff --git a/problems/0941.有效的山脉数组.md b/problems/0941.有效的山脉数组.md index 607031da..c4c8ebfa 100644 --- a/problems/0941.有效的山脉数组.md +++ b/problems/0941.有效的山脉数组.md @@ -7,7 +7,7 @@

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

-# 941.有效的山脉数组 +# 941.有效的山脉数组 [力扣题目链接](https://leetcode-cn.com/problems/valid-mountain-array/) @@ -103,14 +103,52 @@ class Solution { } ``` -## Python +## Python3 ```python +class Solution: + def validMountainArray(self, arr: List[int]) -> bool: + if len(arr) < 3 : + return False + + i = 1 + flagIncrease = False # 上升 + flagDecrease = False # 下降 + + while i < len(arr) and arr[i-1] < arr[i]: + flagIncrease = True + i += 1 + + while i < len(arr) and arr[i-1] > arr[i]: + flagDecrease = True + i += 1 + + return i == len(arr) and flagIncrease and flagDecrease + ``` ## Go ```go +func validMountainArray(arr []int) bool { + if len(arr) < 3 { + return false + } + + i := 1 + flagIncrease := false // 上升 + flagDecrease := false // 下降 + + for ; i < len(arr) && arr[i-1] < arr[i]; i++ { + flagIncrease = true; + } + + for ; i < len(arr) && arr[i-1] > arr[i]; i++ { + flagDecrease = true; + } + + return i == len(arr) && flagIncrease && flagDecrease; +} ``` ## JavaScript diff --git a/problems/数组理论基础.md b/problems/数组理论基础.md index 6d7b9f9a..146cd2de 100644 --- a/problems/数组理论基础.md +++ b/problems/数组理论基础.md @@ -88,7 +88,7 @@ int main() { **所以可以看出在C++中二维数组在地址空间上是连续的**。 -像Java是没有指针的,同时也不对程序员暴漏其元素的地址,寻址操作完全交给虚拟机。 +像Java是没有指针的,同时也不对程序员暴露其元素的地址,寻址操作完全交给虚拟机。 所以看不到每个元素的地址情况,这里我以Java为例,也做一个实验。 diff --git a/problems/背包理论基础01背包-1.md b/problems/背包理论基础01背包-1.md index 7d04b514..32ad30d3 100644 --- a/problems/背包理论基础01背包-1.md +++ b/problems/背包理论基础01背包-1.md @@ -315,7 +315,6 @@ Python: def test_2_wei_bag_problem1(bag_size, weight, value) -> int: rows, cols = len(weight), bag_size + 1 dp = [[0 for _ in range(cols)] for _ in range(rows)] - res = 0 # 初始化dp数组. for i in range(rows): @@ -334,8 +333,6 @@ def test_2_wei_bag_problem1(bag_size, weight, value) -> int: else: # 定义dp数组: dp[i][j] 前i个物品里,放进容量为j的背包,价值总和最大是多少。 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - cur_weight]+ cur_val) - if dp[i][j] > res: - res = dp[i][j] print(dp)