mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-08 08:50:15 +08:00
Merge branch 'youngyangyang04:master' into master
This commit is contained in:
@ -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:
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
|
@ -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 = []
|
||||
|
||||
# 简单递归法
|
||||
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:
|
||||
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 isBST(root.left, min_val, root.val) and isBST(root.right, root.val, max_val)
|
||||
return isBST(root, float("-inf"), float("inf"))
|
||||
return True
|
||||
|
||||
__traverse(root)
|
||||
res = __is_sorted(candidate_list)
|
||||
|
||||
return res
|
||||
```
|
||||
|
||||
**递归** - 标准做法
|
||||
|
||||
```python
|
||||
class Solution:
|
||||
def isValidBST(self, root: TreeNode) -> bool:
|
||||
# 规律: 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
|
||||
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:
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
||||
```
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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];
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user