diff --git a/problems/0018.四数之和.md b/problems/0018.四数之和.md index 0caf12be..4a8fa947 100644 --- a/problems/0018.四数之和.md +++ b/problems/0018.四数之和.md @@ -201,6 +201,54 @@ class Solution(object): ``` Go: +```go +func fourSum(nums []int, target int) [][]int { + if len(nums) < 4 { + return nil + } + sort.Ints(nums) + var res [][]int + for i := 0; i < len(nums)-3; i++ { + n1 := nums[i] + // if n1 > target { // 不能这样写,因为可能是负数 + // break + // } + if i > 0 && n1 == nums[i-1] { + continue + } + for j := i + 1; j < len(nums)-2; j++ { + n2 := nums[j] + if j > i+1 && n2 == nums[j-1] { + continue + } + l := j + 1 + r := len(nums) - 1 + for l < r { + n3 := nums[l] + n4 := nums[r] + sum := n1 + n2 + n3 + n4 + if sum < target { + l++ + } else if sum > target { + r-- + } else { + res = append(res, []int{n1, n2, n3, n4}) + for l < r && n3 == nums[l+1] { // 去重 + l++ + } + for l < r && n4 == nums[r-1] { // 去重 + r-- + } + // 找到答案时,双指针同时靠近 + r-- + l++ + } + } + } + } + return res +} +``` javaScript: diff --git a/problems/0053.最大子序和(动态规划).md b/problems/0053.最大子序和(动态规划).md index ada378b2..20a8c66c 100644 --- a/problems/0053.最大子序和(动态规划).md +++ b/problems/0053.最大子序和(动态规划).md @@ -168,6 +168,23 @@ func max(a,b int) int{ } ``` +JavaScript: + +```javascript +const maxSubArray = nums => { + // 数组长度,dp初始化 + const [len, dp] = [nums.length, [nums[0]]]; + // 最大值初始化为dp[0] + let max = dp[0]; + for (let i = 1; i < len; i++) { + dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]); + // 更新最大值 + max = Math.max(max, dp[i]); + } + return max; +}; +``` + ----------------------- diff --git a/problems/0098.验证二叉搜索树.md b/problems/0098.验证二叉搜索树.md index 248d10f1..a7634849 100644 --- a/problems/0098.验证二叉搜索树.md +++ b/problems/0098.验证二叉搜索树.md @@ -337,6 +337,8 @@ class Solution { ``` Python: + +**递归** - 利用BST中序遍历特性,把树"压缩"成数组 ```python # Definition for a binary tree node. # class TreeNode: @@ -344,29 +346,56 @@ Python: # self.val = val # self.left = left # self.right = right -# 递归法 class Solution: def isValidBST(self, root: TreeNode) -> bool: - res = [] //把二叉搜索树按中序遍历写成list - def buildalist(root): - if not root: return - buildalist(root.left) //左 - res.append(root.val) //中 - buildalist(root.right) //右 - return res - buildalist(root) - return res == sorted(res) and len(set(res)) == len(res) //检查list里的数有没有重复元素,以及是否按从小到大排列 + # 思路: 利用BST中序遍历的特性. + # 中序遍历输出的二叉搜索树节点的数值是有序序列 + candidate_list = [] + + def __traverse(root: TreeNode) -> None: + nonlocal candidate_list + if not root: + return + __traverse(root.left) + candidate_list.append(root.val) + __traverse(root.right) + + def __is_sorted(nums: list) -> bool: + for i in range(1, len(nums)): + if nums[i] <= nums[i - 1]: # ⚠️ 注意: Leetcode定义二叉搜索树中不能有重复元素 + return False + return True + + __traverse(root) + res = __is_sorted(candidate_list) + + return res +``` -# 简单递归法 +**递归** - 标准做法 + +```python class Solution: def isValidBST(self, root: TreeNode) -> bool: - def isBST(root, min_val, max_val): - if not root: return True - if root.val >= max_val or root.val <= min_val: + # 规律: BST的中序遍历节点数值是从小到大. + cur_max = -float("INF") + def __isValidBST(root: TreeNode) -> bool: + nonlocal cur_max + + if not root: + return True + + is_left_valid = __isValidBST(root.left) + if cur_max < root.val: + cur_max = root.val + else: return False - return isBST(root.left, min_val, root.val) and isBST(root.right, root.val, max_val) - return isBST(root, float("-inf"), float("inf")) - + is_right_valid = __isValidBST(root.right) + + return is_left_valid and is_right_valid + return __isValidBST(root) +``` +``` # 迭代-中序遍历 class Solution: def isValidBST(self, root: TreeNode) -> bool: diff --git a/problems/0100.相同的树.md b/problems/0100.相同的树.md index b536ffe3..c40f79fd 100644 --- a/problems/0100.相同的树.md +++ b/problems/0100.相同的树.md @@ -172,6 +172,22 @@ public: Java: +```java +class Solution { + public boolean isSameTree(TreeNode p, TreeNode q) { + if (p == null && q == null) { + return true; + } else if (q == null || p == null) { + return false; + } else if (q.val != p.val) { + return false; + } else { + return isSameTree(q.left, p.left) && isSameTree(q.right, p.right); + } + } +} + +``` Python: Go: diff --git a/problems/0392.判断子序列.md b/problems/0392.判断子序列.md index d97d2684..09ee2c4d 100644 --- a/problems/0392.判断子序列.md +++ b/problems/0392.判断子序列.md @@ -180,7 +180,30 @@ class Solution: return False ``` -Go: +JavaScript: + +```javascript +const isSubsequence = (s, t) => { + // s、t的长度 + const [m, n] = [s.length, t.length]; + // dp全初始化为0 + const dp = new Array(m + 1).fill(0).map(x => new Array(n + 1).fill(0)); + for (let i = 1; i <= m; i++) { + for (let j = 1; j <= n; j++) { + // 更新dp[i][j],两种情况 + if (s[i - 1] === t[j - 1]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + dp[i][j] = dp[i][j - 1]; + } + } + } + // 遍历结束,判断dp右下角的数是否等于s的长度 + return dp[m][n] === m ? true : false; +}; +``` + + diff --git a/problems/0617.合并二叉树.md b/problems/0617.合并二叉树.md index 19b58bd3..09d844f3 100644 --- a/problems/0617.合并二叉树.md +++ b/problems/0617.合并二叉树.md @@ -312,6 +312,8 @@ class Solution { ``` Python: + +**递归法 - 前序遍历** ```python # Definition for a binary tree node. # class TreeNode: @@ -319,41 +321,57 @@ Python: # self.val = val # self.left = left # self.right = right -# 递归法*前序遍历 class Solution: def mergeTrees(self, root1: TreeNode, root2: TreeNode) -> TreeNode: - if not root1: return root2 // 如果t1为空,合并之后就应该是t2 - if not root2: return root1 // 如果t2为空,合并之后就应该是t1 - root1.val = root1.val + root2.val //中 - root1.left = self.mergeTrees(root1.left , root2.left) //左 - root1.right = self.mergeTrees(root1.right , root2.right) //右 - return root1 //root1修改了结构和数值 + # 递归终止条件: + # 但凡有一个节点为空, 就立刻返回另外一个. 如果另外一个也为None就直接返回None. + if not root1: + return root2 + if not root2: + return root1 + # 上面的递归终止条件保证了代码执行到这里root1, root2都非空. + root1.val += root2.val # 中 + root1.left = self.mergeTrees(root1.left, root2.left) #左 + root1.right = self.mergeTrees(root1.right, root2.right) # 右 + + return root1 # ⚠️ 注意: 本题我们重复使用了题目给出的节点而不是创建新节点. 节省时间, 空间. -# 迭代法-覆盖原来的树 +``` + +**迭代法** +```python class Solution: def mergeTrees(self, root1: TreeNode, root2: TreeNode) -> TreeNode: - if not root1: return root2 - if not root2: return root1 - # 迭代,将树2覆盖到树1 - queue1 = [root1] - queue2 = [root2] - root = root1 - while queue1 and queue2: - root1 = queue1.pop(0) - root2 = queue2.pop(0) - root1.val += root2.val - if not root1.left: # 如果树1左儿子不存在,则覆盖后树1的左儿子为树2的左儿子 - root1.left = root2.left - elif root1.left and root2.left: - queue1.append(root1.left) - queue2.append(root2.left) + if not root1: + return root2 + if not root2: + return root1 - if not root1.right: # 同理,处理右儿子 - root1.right = root2.right - elif root1.right and root2.right: - queue1.append(root1.right) - queue2.append(root2.right) - return root + queue = deque() + queue.append(root1) + queue.append(root2) + + while queue: + node1 = queue.popleft() + node2 = queue.popleft() + # 更新queue + # 只有两个节点都有左节点时, 再往queue里面放. + if node1.left and node2.left: + queue.append(node1.left) + queue.append(node2.left) + # 只有两个节点都有右节点时, 再往queue里面放. + if node1.right and node2.right: + queue.append(node1.right) + queue.append(node2.right) + + # 更新当前节点. 同时改变当前节点的左右孩子. + node1.val += node2.val + if not node1.left and node2.left: + node1.left = node2.left + if not node1.right and node2.right: + node1.right = node2.right + + return root1 ``` Go: diff --git a/problems/0700.二叉搜索树中的搜索.md b/problems/0700.二叉搜索树中的搜索.md index d6899ac5..4b02f8af 100644 --- a/problems/0700.二叉搜索树中的搜索.md +++ b/problems/0700.二叉搜索树中的搜索.md @@ -220,9 +220,18 @@ Python: # self.right = right class Solution: def searchBST(self, root: TreeNode, val: int) -> TreeNode: - if not root or root.val == val: return root //为空或者已经找到都是直接返回root,所以合并了 - if root.val > val: return self.searchBST(root.left,val) //注意一定要加return - else: return self.searchBST(root.right,val) + # 为什么要有返回值: + # 因为搜索到目标节点就要立即return, + # 这样才是找到节点就返回(搜索某一条边),如果不加return,就是遍历整棵树了。 + + if not root or root.val == val: + return root + + if root.val > val: + return self.searchBST(root.left, val) + + if root.val < val: + return self.searchBST(root.right, val) ``` diff --git a/problems/0707.设计链表.md b/problems/0707.设计链表.md index 8be28f88..349e2409 100644 --- a/problems/0707.设计链表.md +++ b/problems/0707.设计链表.md @@ -154,7 +154,129 @@ private: ## 其他语言版本 +C: +```C +typedef struct { + int val; + struct MyLinkedList* next; +}MyLinkedList; +/** Initialize your data structure here. */ + +MyLinkedList* myLinkedListCreate() { + //这个题必须用虚拟头指针,参数都是一级指针,头节点确定后没法改指向了!!! + MyLinkedList* head = (MyLinkedList *)malloc(sizeof (MyLinkedList)); + head->next = NULL; + return head; +} + +/** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */ +int myLinkedListGet(MyLinkedList* obj, int index) { + MyLinkedList *cur = obj->next; + for (int i = 0; cur != NULL; i++){ + if (i == index){ + return cur->val; + } + else{ + cur = cur->next; + } + } + return -1; +} + +/** Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. */ +void myLinkedListAddAtHead(MyLinkedList* obj, int val) { + MyLinkedList *nhead = (MyLinkedList *)malloc(sizeof (MyLinkedList)); + nhead->val = val; + nhead->next = obj->next; + obj->next = nhead; + +} + +/** Append a node of value val to the last element of the linked list. */ +void myLinkedListAddAtTail(MyLinkedList* obj, int val) { + MyLinkedList *cur = obj; + while(cur->next != NULL){ + cur = cur->next; + } + MyLinkedList *ntail = (MyLinkedList *)malloc(sizeof (MyLinkedList)); + ntail->val = val; + ntail->next = NULL; + cur->next = ntail; +} + +/** Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */ +void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) { + if (index == 0){ + myLinkedListAddAtHead(obj, val); + return; + } + MyLinkedList *cur = obj->next; + for (int i = 1 ;cur != NULL; i++){ + if (i == index){ + MyLinkedList* newnode = (MyLinkedList *)malloc(sizeof (MyLinkedList)); + newnode->val = val; + newnode->next = cur->next; + cur->next = newnode; + return; + } + else{ + cur = cur->next; + } + } +} + +/** Delete the index-th node in the linked list, if the index is valid. */ +void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) { + if (index == 0){ + MyLinkedList *tmp = obj->next; + if (tmp != NULL){ + obj->next = tmp->next; + free(tmp) + } + return; + } + MyLinkedList *cur = obj->next; + for (int i = 1 ;cur != NULL && cur->next != NULL; i++){ + if (i == index){ + MyLinkedList *tmp = cur->next; + if (tmp != NULL) { + cur->next = tmp->next; + free(tmp); + } + return; + } + else{ + cur = cur->next; + } + } + +} + +void myLinkedListFree(MyLinkedList* obj) { + while(obj != NULL){ + MyLinkedList *tmp = obj; + obj = obj->next; + free(tmp); + } +} + +/** + * Your MyLinkedList struct will be instantiated and called as such: + * MyLinkedList* obj = myLinkedListCreate(); + * int param_1 = myLinkedListGet(obj, index); + + * myLinkedListAddAtHead(obj, val); + + * myLinkedListAddAtTail(obj, val); + + * myLinkedListAddAtIndex(obj, index, val); + + * myLinkedListDeleteAtIndex(obj, index); + + * myLinkedListFree(obj); +*/ +``` Java: ```Java diff --git a/problems/1002.查找常用字符.md b/problems/1002.查找常用字符.md index 875340c4..e3014d00 100644 --- a/problems/1002.查找常用字符.md +++ b/problems/1002.查找常用字符.md @@ -169,6 +169,46 @@ class Solution { } } ``` +javaScript +```js +var commonChars = function (words) { + let res = [] + let size = 26 + let firstHash = new Array(size) + for (let i = 0; i < size; i++) { // 初始化 hash 数组 + firstHash[i] = 0 + } + + let a = "a".charCodeAt() + let firstWord = words[0] + for (let i = 0; i < firstWord.length; i++) { // 第 0 个单词的统计 + let idx = firstWord[i].charCodeAt() + firstHash[idx - a] += 1 + } + + for (let i = 1; i < words.length; i++) { // 1-n 个单词统计 + let otherHash = new Array(size) + for (let i = 0; i < size; i++) { // 初始化 hash 数组 + otherHash[i] = 0 + } + + for (let j = 0; j < words[i].length; j++) { + let idx = words[i][j].charCodeAt() + otherHash[idx - a] += 1 + } + for (let i = 0; i < size; i++) { + firstHash[i] = Math.min(firstHash[i], otherHash[i]) + } + } + for (let i = 0; i < size; i++) { + while (firstHash[i] > 0) { + res.push(String.fromCharCode(i + a)) + firstHash[i]-- + } + } + return res +}; +``` ----------------------- * 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw) diff --git a/problems/1035.不相交的线.md b/problems/1035.不相交的线.md index cb74ef75..3a0e6a68 100644 --- a/problems/1035.不相交的线.md +++ b/problems/1035.不相交的线.md @@ -109,7 +109,28 @@ class Solution: return dp[-1][-1] ``` -Go: +JavaScript: + +```javascript +const maxUncrossedLines = (nums1, nums2) => { + // 两个数组长度 + const [m, n] = [nums1.length, nums2.length]; + // 创建dp数组并都初始化为0 + const dp = new Array(m + 1).fill(0).map(x => new Array(n + 1).fill(0)); + for (let i = 1; i <= m; i++) { + for (let j = 1; j <= n; j++) { + // 根据两种情况更新dp[i][j] + if (nums1[i - 1] === nums2[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]); + } + } + } + // 返回dp数组中右下角的元素 + return dp[m][n]; +}; +```