mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-09 19:44:45 +08:00
Merge branch 'master' of https://github.com/youngyangyang04/leetcode
This commit is contained in:
@ -135,6 +135,28 @@ func removeNthFromEnd(head *ListNode, n int) *ListNode {
|
||||
}
|
||||
```
|
||||
|
||||
JavaScript:
|
||||
|
||||
```js
|
||||
/**
|
||||
* @param {ListNode} head
|
||||
* @param {number} n
|
||||
* @return {ListNode}
|
||||
*/
|
||||
var removeNthFromEnd = function(head, n) {
|
||||
let ret = new ListNode(0, head),
|
||||
slow = fast = ret;
|
||||
while(n--) fast = fast.next;
|
||||
if(!fast) return ret.next;
|
||||
while (fast.next) {
|
||||
fast = fast.next;
|
||||
slow = slow.next
|
||||
};
|
||||
slow.next = slow.next.next;
|
||||
return ret.next;
|
||||
};
|
||||
```
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
* B站视频:[代码随想录](https://space.bilibili.com/525438321)
|
||||
|
@ -193,6 +193,26 @@ class Solution:
|
||||
```
|
||||
|
||||
Go:
|
||||
```Go
|
||||
func jump(nums []int) int {
|
||||
dp:=make([]int ,len(nums))
|
||||
dp[0]=0
|
||||
|
||||
for i:=1;i<len(nums);i++{
|
||||
dp[i]=i
|
||||
for j:=0;j<i;j++{
|
||||
if nums[j]+j>i{
|
||||
dp[i]=min(dp[j]+1,dp[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp[len(nums)-1]
|
||||
}
|
||||
/*
|
||||
dp[i]表示从起点到当前位置的最小跳跃次数
|
||||
dp[i]=min(dp[j]+1,dp[i]) 表示从j位置用一步跳跃到当前位置,这个j位置可能有很多个,却最小一个就可以
|
||||
*/
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
@ -122,6 +122,24 @@ class Solution:
|
||||
```
|
||||
|
||||
Go:
|
||||
```Go
|
||||
func canJUmp(nums []int) bool {
|
||||
if len(nums)<=1{
|
||||
return true
|
||||
}
|
||||
dp:=make([]bool,len(nums))
|
||||
dp[0]=true
|
||||
for i:=1;i<len(nums);i++{
|
||||
for j:=i-1;j>=0;j--{
|
||||
if dp[j]&&nums[j]+j>=i{
|
||||
dp[i]=true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp[len(nums)-1]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
@ -370,8 +370,45 @@ class Solution {
|
||||
|
||||
|
||||
Python:
|
||||
```python
|
||||
class Solution:
|
||||
result: List[List[int]] = []
|
||||
path: List[int] = []
|
||||
def combine(self, n: int, k: int) -> List[List[int]]:
|
||||
self.result = []
|
||||
self.combineHelper(n, k, 1)
|
||||
return self.result
|
||||
|
||||
|
||||
def combineHelper(self, n: int, k: int, startIndex: int):
|
||||
if (l := len(self.path)) == k:
|
||||
self.result.append(self.path.copy())
|
||||
return
|
||||
for i in range(startIndex, n - (k - l) + 2):
|
||||
self.path.append(i)
|
||||
self.combineHelper(n, k, i + 1)
|
||||
self.path.pop()
|
||||
```
|
||||
javascript
|
||||
```javascript
|
||||
let result = []
|
||||
let path = []
|
||||
var combine = function(n, k) {
|
||||
result = []
|
||||
combineHelper(n, k, 1)
|
||||
return result
|
||||
};
|
||||
const combineHelper = (n, k, startIndex) => {
|
||||
if (path.length === k) {
|
||||
result.push([...path])
|
||||
return
|
||||
}
|
||||
for (let i = startIndex; i <= n - (k - path.length) + 1; ++i) {
|
||||
path.push(i)
|
||||
combineHelper(n, k, i + 1)
|
||||
path.pop()
|
||||
}
|
||||
}
|
||||
```
|
||||
Go:
|
||||
```Go
|
||||
var res [][]int
|
||||
|
@ -336,8 +336,26 @@ class Solution {
|
||||
```
|
||||
|
||||
Python:
|
||||
|
||||
|
||||
```python
|
||||
# Definition for a binary tree node.
|
||||
# class TreeNode:
|
||||
# def __init__(self, val=0, left=None, right=None):
|
||||
# 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里的数有没有重复元素,以及是否按从小到大排列
|
||||
```
|
||||
Go:
|
||||
```Go
|
||||
import "math"
|
||||
|
@ -302,6 +302,53 @@ class Solution:
|
||||
Go:
|
||||
|
||||
|
||||
JavaScript:
|
||||
|
||||
递归法:
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* @param {TreeNode} root
|
||||
* @return {number}
|
||||
*/
|
||||
var minDepth1 = function(root) {
|
||||
if(!root) return 0;
|
||||
// 到叶子节点 返回 1
|
||||
if(!root.left && !root.right) return 1;
|
||||
// 只有右节点时 递归右节点
|
||||
if(!root.left) return 1 + minDepth(root.right);、
|
||||
// 只有左节点时 递归左节点
|
||||
if(!root.right) return 1 + minDepth(root.left);
|
||||
return Math.min(minDepth(root.left), minDepth(root.right)) + 1;
|
||||
};
|
||||
```
|
||||
|
||||
迭代法:
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* @param {TreeNode} root
|
||||
* @return {number}
|
||||
*/
|
||||
var minDepth = function(root) {
|
||||
if(!root) return 0;
|
||||
const queue = [root];
|
||||
let dep = 0;
|
||||
while(true) {
|
||||
let size = queue.length;
|
||||
dep++;
|
||||
while(size--){
|
||||
const node = queue.shift();
|
||||
// 到第一个叶子节点 返回 当前深度
|
||||
if(!node.left && !node.right) return dep;
|
||||
node.left && queue.push(node.left);
|
||||
node.right && queue.push(node.right);
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
|
@ -254,7 +254,25 @@ Python:
|
||||
|
||||
|
||||
Go:
|
||||
|
||||
```Go
|
||||
func wordBreak(s string,wordDict []string) bool {
|
||||
wordDictSet:=make(map[string]bool)
|
||||
for _,w:=range wordDict{
|
||||
wordDictSet[w]=true
|
||||
}
|
||||
dp:=make([]bool,len(s)+1)
|
||||
dp[0]=true
|
||||
for i:=1;i<=len(s);i++{
|
||||
for j:=0;j<i;j++{
|
||||
if dp[j]&& wordDictSet[s[j:i]]{
|
||||
dp[i]=true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp[len(s)]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
@ -258,6 +258,50 @@ Go:
|
||||
}
|
||||
```
|
||||
|
||||
javaScript
|
||||
|
||||
```js
|
||||
// 两种循环实现方式
|
||||
/**
|
||||
* @param {ListNode} head
|
||||
* @return {ListNode}
|
||||
*/
|
||||
// 先判断是否是环形链表
|
||||
var detectCycle = function(head) {
|
||||
if(!head || !head.next) return null;
|
||||
let slow =head.next, fast = head.next.next;
|
||||
while(fast && fast.next && fast!== slow) {
|
||||
slow = slow.next;
|
||||
fast = fast.next.next;
|
||||
}
|
||||
if(!fast || !fast.next ) return null;
|
||||
slow = head;
|
||||
while (fast !== slow) {
|
||||
slow = slow.next;
|
||||
fast = fast.next;
|
||||
}
|
||||
return slow;
|
||||
};
|
||||
|
||||
var detectCycle = function(head) {
|
||||
if(!head || !head.next) return null;
|
||||
let slow =head.next, fast = head.next.next;
|
||||
while(fast && fast.next) {
|
||||
slow = slow.next;
|
||||
fast = fast.next.next;
|
||||
if(fast == slow) {
|
||||
slow = head;
|
||||
while (fast !== slow) {
|
||||
slow = slow.next;
|
||||
fast = fast.next;
|
||||
}
|
||||
return slow;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
* 作者微信:[程序员Carl](https://mp.weixin.qq.com/s/b66DFkOp8OOxdZC_xLZxfw)
|
||||
|
@ -112,6 +112,40 @@ Python:
|
||||
|
||||
Go:
|
||||
|
||||
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);
|
||||
}
|
||||
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));
|
||||
// 如果 a === b
|
||||
while (b !== 1 && getN(b) !== 1 && a !== b) {
|
||||
a = getN(a);
|
||||
b = getN(getN(b));
|
||||
}
|
||||
return b === 1 || getN(b) === 1 ;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
@ -156,6 +156,7 @@ public:
|
||||
|
||||
Java:
|
||||
|
||||
使用两个 Queue 实现
|
||||
```java
|
||||
class MyStack {
|
||||
|
||||
@ -205,7 +206,94 @@ class MyStack {
|
||||
* boolean param_4 = obj.empty();
|
||||
*/
|
||||
```
|
||||
使用两个 Deque 实现
|
||||
```java
|
||||
class MyStack {
|
||||
// Deque 接口继承了 Queue 接口
|
||||
// 所以 Queue 中的 add、poll、peek等效于 Deque 中的 addLast、pollFirst、peekFirst
|
||||
Deque<Integer> que1; // 和栈中保持一样元素的队列
|
||||
Deque<Integer> que2; // 辅助队列
|
||||
/** Initialize your data structure here. */
|
||||
public MyStack() {
|
||||
que1 = new ArrayDeque<>();
|
||||
que2 = new ArrayDeque<>();
|
||||
}
|
||||
|
||||
/** Push element x onto stack. */
|
||||
public void push(int x) {
|
||||
que1.addLast(x);
|
||||
}
|
||||
|
||||
/** Removes the element on top of the stack and returns that element. */
|
||||
public int pop() {
|
||||
int size = que1.size();
|
||||
size--;
|
||||
// 将 que1 导入 que2 ,但留下最后一个值
|
||||
while (size-- > 0) {
|
||||
que2.addLast(que1.peekFirst());
|
||||
que1.pollFirst();
|
||||
}
|
||||
|
||||
int res = que1.pollFirst();
|
||||
// 将 que2 对象的引用赋给了 que1 ,此时 que1,que2 指向同一个队列
|
||||
que1 = que2;
|
||||
// 如果直接操作 que2,que1 也会受到影响,所以为 que2 分配一个新的空间
|
||||
que2 = new ArrayDeque<>();
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Get the top element. */
|
||||
public int top() {
|
||||
return que1.peekLast();
|
||||
}
|
||||
|
||||
/** Returns whether the stack is empty. */
|
||||
public boolean empty() {
|
||||
return que1.isEmpty();
|
||||
}
|
||||
}
|
||||
```
|
||||
优化,使用一个 Deque 实现
|
||||
```java
|
||||
class MyStack {
|
||||
// Deque 接口继承了 Queue 接口
|
||||
// 所以 Queue 中的 add、poll、peek等效于 Deque 中的 addLast、pollFirst、peekFirst
|
||||
Deque<Integer> que1;
|
||||
/** Initialize your data structure here. */
|
||||
public MyStack() {
|
||||
que1 = new ArrayDeque<>();
|
||||
}
|
||||
|
||||
/** Push element x onto stack. */
|
||||
public void push(int x) {
|
||||
que1.addLast(x);
|
||||
}
|
||||
|
||||
/** Removes the element on top of the stack and returns that element. */
|
||||
public int pop() {
|
||||
int size = que1.size();
|
||||
size--;
|
||||
// 将 que1 导入 que2 ,但留下最后一个值
|
||||
while (size-- > 0) {
|
||||
que1.addLast(que1.peekFirst());
|
||||
que1.pollFirst();
|
||||
}
|
||||
|
||||
int res = que1.pollFirst();
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Get the top element. */
|
||||
public int top() {
|
||||
return que1.peekLast();
|
||||
}
|
||||
|
||||
/** Returns whether the stack is empty. */
|
||||
public boolean empty() {
|
||||
return que1.isEmpty();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Python:
|
||||
|
||||
|
@ -131,6 +131,101 @@ public:
|
||||
|
||||
Java:
|
||||
|
||||
使用Stack(堆栈)同名方法:
|
||||
```java
|
||||
class MyQueue {
|
||||
// java中的 Stack 有设计上的缺陷,官方推荐使用 Deque(双端队列) 代替 Stack
|
||||
Deque<Integer> stIn;
|
||||
Deque<Integer> stOut;
|
||||
/** Initialize your data structure here. */
|
||||
public MyQueue() {
|
||||
stIn = new ArrayDeque<>();
|
||||
stOut = new ArrayDeque<>();
|
||||
}
|
||||
|
||||
/** Push element x to the back of queue. */
|
||||
public void push(int x) {
|
||||
stIn.push(x);
|
||||
}
|
||||
|
||||
/** Removes the element from in front of queue and returns that element. */
|
||||
public int pop() {
|
||||
// 只要 stOut 为空,那么就应该将 stIn 中所有的元素倒腾到 stOut 中
|
||||
if (stOut.isEmpty()) {
|
||||
while (!stIn.isEmpty()) {
|
||||
stOut.push(stIn.pop());
|
||||
}
|
||||
}
|
||||
// 再返回 stOut 中的元素
|
||||
return stOut.pop();
|
||||
}
|
||||
|
||||
/** Get the front element. */
|
||||
public int peek() {
|
||||
// 直接使用已有的pop函数
|
||||
int res = this.pop();
|
||||
// 因为pop函数弹出了元素res,所以再添加回去
|
||||
stOut.push(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Returns whether the queue is empty. */
|
||||
public boolean empty() {
|
||||
// 当 stIn 栈为空时,说明没有元素可以倒腾到 stOut 栈了
|
||||
// 并且 stOut 栈也为空时,说明没有以前从 stIn 中倒腾到的元素了
|
||||
return stIn.isEmpty() && stOut.isEmpty();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
个人习惯写法,使用Deque通用api:
|
||||
```java
|
||||
class MyQueue {
|
||||
// java中的 Stack 有设计上的缺陷,官方推荐使用 Deque(双端队列) 代替 Stack
|
||||
// Deque 中的 addFirst、removeFirst、peekFirst 等方法等效于 Stack(堆栈) 中的 push、pop、peek
|
||||
Deque<Integer> stIn;
|
||||
Deque<Integer> stOut;
|
||||
/** Initialize your data structure here. */
|
||||
public MyQueue() {
|
||||
stIn = new ArrayDeque<>();
|
||||
stOut = new ArrayDeque<>();
|
||||
}
|
||||
|
||||
/** Push element x to the back of queue. */
|
||||
public void push(int x) {
|
||||
stIn.addLast(x);
|
||||
}
|
||||
|
||||
/** Removes the element from in front of queue and returns that element. */
|
||||
public int pop() {
|
||||
// 只要 stOut 为空,那么就应该将 stIn 中所有的元素倒腾到 stOut 中
|
||||
if (stOut.isEmpty()) {
|
||||
while (!stIn.isEmpty()) {
|
||||
stOut.addLast(stIn.pollLast());
|
||||
}
|
||||
}
|
||||
// 再返回 stOut 中的元素
|
||||
return stOut.pollLast();
|
||||
}
|
||||
|
||||
/** Get the front element. */
|
||||
public int peek() {
|
||||
// 直接使用已有的pop函数
|
||||
int res = this.pop();
|
||||
// 因为pop函数弹出了元素res,所以再添加回去
|
||||
stOut.addLast(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Returns whether the queue is empty. */
|
||||
public boolean empty() {
|
||||
// 当 stIn 栈为空时,说明没有元素可以倒腾到 stOut 栈了
|
||||
// 并且 stOut 栈也为空时,说明没有以前从 stIn 中倒腾到的元素了
|
||||
return stIn.isEmpty() && stOut.isEmpty();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
class MyQueue {
|
||||
|
||||
@ -190,6 +285,73 @@ Python:
|
||||
|
||||
|
||||
Go:
|
||||
```Go
|
||||
type MyQueue struct {
|
||||
stack []int
|
||||
back []int
|
||||
}
|
||||
|
||||
/** Initialize your data structure here. */
|
||||
func Constructor() MyQueue {
|
||||
return MyQueue{
|
||||
stack: make([]int, 0),
|
||||
back: make([]int, 0),
|
||||
}
|
||||
}
|
||||
|
||||
/** Push element x to the back of queue. */
|
||||
func (this *MyQueue) Push(x int) {
|
||||
for len(this.back) != 0 {
|
||||
val := this.back[len(this.back)-1]
|
||||
this.back = this.back[:len(this.back)-1]
|
||||
this.stack = append(this.stack, val)
|
||||
}
|
||||
this.stack = append(this.stack, x)
|
||||
}
|
||||
|
||||
/** Removes the element from in front of queue and returns that element. */
|
||||
func (this *MyQueue) Pop() int {
|
||||
for len(this.stack) != 0 {
|
||||
val := this.stack[len(this.stack)-1]
|
||||
this.stack = this.stack[:len(this.stack)-1]
|
||||
this.back = append(this.back, val)
|
||||
}
|
||||
if len(this.back) == 0 {
|
||||
return 0
|
||||
}
|
||||
val := this.back[len(this.back)-1]
|
||||
this.back = this.back[:len(this.back)-1]
|
||||
return val
|
||||
}
|
||||
|
||||
/** Get the front element. */
|
||||
func (this *MyQueue) Peek() int {
|
||||
for len(this.stack) != 0 {
|
||||
val := this.stack[len(this.stack)-1]
|
||||
this.stack = this.stack[:len(this.stack)-1]
|
||||
this.back = append(this.back, val)
|
||||
}
|
||||
if len(this.back) == 0 {
|
||||
return 0
|
||||
}
|
||||
val := this.back[len(this.back)-1]
|
||||
return val
|
||||
}
|
||||
|
||||
/** Returns whether the queue is empty. */
|
||||
func (this *MyQueue) Empty() bool {
|
||||
return len(this.stack) == 0 && len(this.back) == 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Your MyQueue object will be instantiated and called as such:
|
||||
* obj := Constructor();
|
||||
* obj.Push(x);
|
||||
* param_2 := obj.Pop();
|
||||
* param_3 := obj.Peek();
|
||||
* param_4 := obj.Empty();
|
||||
*/
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
@ -136,7 +136,34 @@ class Solution {
|
||||
```
|
||||
|
||||
Python:
|
||||
```
|
||||
class Solution(object):
|
||||
def canConstruct(self, ransomNote, magazine):
|
||||
"""
|
||||
:type ransomNote: str
|
||||
:type magazine: str
|
||||
:rtype: bool
|
||||
"""
|
||||
|
||||
# use a dict to store the number of letter occurance in ransomNote
|
||||
hashmap = dict()
|
||||
for s in ransomNote:
|
||||
if s in hashmap:
|
||||
hashmap[s] += 1
|
||||
else:
|
||||
hashmap[s] = 1
|
||||
|
||||
# check if the letter we need can be found in magazine
|
||||
for l in magazine:
|
||||
if l in hashmap:
|
||||
hashmap[l] -= 1
|
||||
|
||||
for key in hashmap:
|
||||
if hashmap[key] > 0:
|
||||
return False
|
||||
|
||||
return True
|
||||
```
|
||||
|
||||
Go:
|
||||
|
||||
|
@ -121,6 +121,37 @@ class Solution {
|
||||
|
||||
Python:
|
||||
|
||||
```
|
||||
class Solution(object):
|
||||
def fourSumCount(self, nums1, nums2, nums3, nums4):
|
||||
"""
|
||||
:type nums1: List[int]
|
||||
:type nums2: List[int]
|
||||
:type nums3: List[int]
|
||||
:type nums4: List[int]
|
||||
:rtype: int
|
||||
"""
|
||||
# use a dict to store the elements in nums1 and nums2 and their sum
|
||||
hashmap = dict()
|
||||
for n1 in nums1:
|
||||
for n2 in nums2:
|
||||
if n1 + n2 in hashmap:
|
||||
hashmap[n1+n2] += 1
|
||||
else:
|
||||
hashmap[n1+n2] = 1
|
||||
|
||||
# if the -(a+b) exists in nums3 and nums4, we shall add the count
|
||||
count = 0
|
||||
for n3 in nums3:
|
||||
for n4 in nums4:
|
||||
key = - n3 - n4
|
||||
if key in hashmap:
|
||||
count += hashmap[key]
|
||||
return count
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
Go:
|
||||
|
||||
|
@ -149,9 +149,38 @@ public:
|
||||
|
||||
## 其他语言版本
|
||||
|
||||
|
||||
Java:
|
||||
|
||||
```java
|
||||
class Solution {
|
||||
public boolean repeatedSubstringPattern(String s) {
|
||||
if (s.equals("")) return false;
|
||||
|
||||
int len = s.length();
|
||||
// 原串加个空格(哨兵),使下标从1开始,这样j从0开始,也不用初始化了
|
||||
s = " " + s;
|
||||
char[] chars = s.toCharArray();
|
||||
int[] next = new int[len + 1];
|
||||
|
||||
// 构造 next 数组过程,j从0开始(空格),i从2开始
|
||||
for (int i = 2, j = 0; i <= len; i++) {
|
||||
// 匹配不成功,j回到前一位置 next 数组所对应的值
|
||||
while (j > 0 && chars[i] != chars[j + 1]) j = next[j];
|
||||
// 匹配成功,j往后移
|
||||
if (chars[i] == chars[j + 1]) j++;
|
||||
// 更新 next 数组的值
|
||||
next[i] = j;
|
||||
}
|
||||
|
||||
// 最后判断是否是重复的子字符串,这里 next[len] 即代表next数组末尾的值
|
||||
if (next[len] > 0 && len % (len - next[len]) == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Python:
|
||||
|
||||
|
@ -173,6 +173,33 @@ Python:
|
||||
|
||||
|
||||
Go:
|
||||
```Go
|
||||
func longestPalindromeSubseq(s string) int {
|
||||
lenth:=len(s)
|
||||
dp:=make([][]int,lenth)
|
||||
for i:=0;i<lenth;i++{
|
||||
for j:=0;j<lenth;j++{
|
||||
if dp[i]==nil{
|
||||
dp[i]=make([]int,lenth)
|
||||
}
|
||||
if i==j{
|
||||
dp[i][j]=1
|
||||
}
|
||||
}
|
||||
}
|
||||
for i:=lenth-1;i>=0;i--{
|
||||
for j:=i+1;j<lenth;j++{
|
||||
if s[i]==s[j]{
|
||||
dp[i][j]=dp[i+1][j-1]+2
|
||||
}else {
|
||||
dp[i][j]=max(dp[i+1][j],dp[i][j-1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dp[0][lenth-1]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
@ -177,8 +177,29 @@ class Solution {
|
||||
```
|
||||
|
||||
Python:
|
||||
```python
|
||||
# Definition for a binary tree node.
|
||||
# class TreeNode:
|
||||
# def __init__(self, val=0, left=None, right=None):
|
||||
# self.val = val
|
||||
# self.left = left
|
||||
# self.right = right
|
||||
class Solution:
|
||||
def getMinimumDifference(self, root: TreeNode) -> int:
|
||||
res = []
|
||||
r = float("inf")
|
||||
def buildaList(root): //把二叉搜索树转换成有序数组
|
||||
if not root: return None
|
||||
if root.left: buildaList(root.left) //左
|
||||
res.append(root.val) //中
|
||||
if root.right: buildaList(root.right) //右
|
||||
return res
|
||||
|
||||
|
||||
buildaList(root)
|
||||
for i in range(len(res)-1): // 统计有序数组的最小差值
|
||||
r = min(abs(res[i]-res[i+1]),r)
|
||||
return r
|
||||
```
|
||||
Go:
|
||||
|
||||
|
||||
|
@ -312,7 +312,23 @@ class Solution {
|
||||
```
|
||||
|
||||
Python:
|
||||
|
||||
```python
|
||||
# Definition for a binary tree node.
|
||||
# class TreeNode:
|
||||
# def __init__(self, val=0, left=None, right=None):
|
||||
# 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修改了结构和数值
|
||||
```
|
||||
|
||||
Go:
|
||||
|
||||
|
@ -212,13 +212,18 @@ Python:
|
||||
递归法:
|
||||
|
||||
```python
|
||||
# Definition for a binary tree node.
|
||||
# class TreeNode:
|
||||
# def __init__(self, val=0, left=None, right=None):
|
||||
# self.val = val
|
||||
# self.left = left
|
||||
# self.right = right
|
||||
class Solution:
|
||||
def searchBST(self, root: TreeNode, val: int) -> TreeNode:
|
||||
if root is None:
|
||||
return None
|
||||
if val < root.val: return self.searchBST(root.left, val)
|
||||
elif val > root.val: return self.searchBST(root.right, val)
|
||||
else: return root
|
||||
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)
|
||||
|
||||
```
|
||||
|
||||
迭代法:
|
||||
|
@ -153,6 +153,10 @@ Java:
|
||||
```java
|
||||
class Solution {
|
||||
public int search(int[] nums, int target) {
|
||||
// 避免当 target 小于nums[0] nums[nums.length - 1]时多次循环运算
|
||||
if (target < nums[0] || target > nums[nums.length - 1]) {
|
||||
return -1;
|
||||
}
|
||||
int left = 0, right = nums.length - 1;
|
||||
while (left <= right) {
|
||||
int mid = left + ((right - left) >> 1);
|
||||
@ -210,6 +214,47 @@ class Solution:
|
||||
|
||||
Go:
|
||||
|
||||
(版本一)左闭右闭区间
|
||||
|
||||
```go
|
||||
func search(nums []int, target int) int {
|
||||
high := len(nums)-1
|
||||
low := 0
|
||||
for low <= high {
|
||||
mid := low + (high-low)/2
|
||||
if nums[mid] == target {
|
||||
return mid
|
||||
} else if nums[mid] > target {
|
||||
high = mid-1
|
||||
} else {
|
||||
low = mid+1
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
```
|
||||
|
||||
(版本二)左闭右开区间
|
||||
|
||||
```go
|
||||
func search(nums []int, target int) int {
|
||||
high := len(nums)
|
||||
low := 0
|
||||
for low < high {
|
||||
mid := low + (high-low)/2
|
||||
if nums[mid] == target {
|
||||
return mid
|
||||
} else if nums[mid] > target {
|
||||
high = mid
|
||||
} else {
|
||||
low = mid+1
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -73,7 +73,24 @@ public:
|
||||
|
||||
|
||||
Java:
|
||||
|
||||
```java
|
||||
class Solution {
|
||||
public int maxUncrossedLines(int[] A, int[] B) {
|
||||
int [][] dp = new int[A.length+1][B.length+1];
|
||||
for(int i=1;i<=A.length;i++) {
|
||||
for(int j=1;j<=B.length;j++) {
|
||||
if (A[i-1]==B[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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dp[A.length][B.length];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Python:
|
||||
|
||||
|
@ -175,7 +175,85 @@ if (cur->right) {
|
||||
|
||||
|
||||
Java:
|
||||
100. 相同的树:递归代码
|
||||
```java
|
||||
class Solution {
|
||||
public boolean compare(TreeNode tree1, TreeNode tree2) {
|
||||
|
||||
if(tree1==null && tree2==null)return true;
|
||||
if(tree1==null || tree2==null)return false;
|
||||
if(tree1.val!=tree2.val)return false;
|
||||
// 此时就是:左右节点都不为空,且数值相同的情况
|
||||
// 此时才做递归,做下一层的判断
|
||||
boolean compareLeft = compare(tree1.left, tree2.left); // 左子树:左、 右子树:左
|
||||
boolean compareRight = compare(tree1.right, tree2.right); // 左子树:右、 右子树:右
|
||||
boolean isSame = compareLeft && compareRight; // 左子树:中、 右子树:中(逻辑处理)
|
||||
return isSame;
|
||||
|
||||
}
|
||||
boolean isSameTree(TreeNode p, TreeNode q) {
|
||||
return compare(p, q);
|
||||
}
|
||||
}
|
||||
```
|
||||
257. 二叉树的所有路径: 回溯代码
|
||||
```java
|
||||
class Solution {
|
||||
public void traversal(TreeNode cur, List<Integer> path, List<String> result) {
|
||||
path.add(cur.val);
|
||||
// 这才到了叶子节点
|
||||
if (cur.left == null && cur.right == null) {
|
||||
String sPath="";
|
||||
for (int i = 0; i < path.size() - 1; i++) {
|
||||
sPath += ""+path.get(i);
|
||||
sPath += "->";
|
||||
}
|
||||
sPath += path.get(path.size() - 1);
|
||||
result.add(sPath);
|
||||
return;
|
||||
}
|
||||
if (cur.left!=null) {
|
||||
traversal(cur.left, path, result);
|
||||
path.remove(path.size()-1); // 回溯
|
||||
}
|
||||
if (cur.right!=null) {
|
||||
traversal(cur.right, path, result);
|
||||
path.remove(path.size()-1); // 回溯
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> binaryTreePaths(TreeNode root) {
|
||||
List<String> result = new LinkedList<>();
|
||||
List<Integer> path = new LinkedList<>();
|
||||
if (root == null) return result;
|
||||
traversal(root, path, result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
如下为精简之后的递归代码:(257. 二叉树的所有路径)
|
||||
```java
|
||||
class Solution {
|
||||
public void traversal(TreeNode cur, String path, List<String> result) {
|
||||
path += cur.val; // 中
|
||||
if (cur.left == null && cur.right == null) {
|
||||
result.add(path);
|
||||
return;
|
||||
}
|
||||
if (cur.left!=null) traversal(cur.left, path + "->", result); // 左 回溯就隐藏在这里
|
||||
if (cur.right!=null) traversal(cur.right, path + "->", result); // 右 回溯就隐藏在这里
|
||||
}
|
||||
|
||||
public List<String> binaryTreePaths(TreeNode root) {
|
||||
List<String> result = new LinkedList<>();
|
||||
String path = "";
|
||||
if (root == null) return result;
|
||||
traversal(root, path, result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Python:
|
||||
|
||||
|
@ -153,8 +153,91 @@ public:
|
||||
|
||||
|
||||
Java:
|
||||
迭代法前序遍历代码如下:
|
||||
```java
|
||||
class Solution {
|
||||
|
||||
public List<Integer> preorderTraversal(TreeNode root) {
|
||||
List<Integer> result = new LinkedList<>();
|
||||
Stack<TreeNode> st = new Stack<>();
|
||||
if (root != null) st.push(root);
|
||||
while (!st.empty()) {
|
||||
TreeNode node = st.peek();
|
||||
if (node != null) {
|
||||
st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
|
||||
if (node.right!=null) st.push(node.right); // 添加右节点(空节点不入栈)
|
||||
if (node.left!=null) st.push(node.left); // 添加左节点(空节点不入栈)
|
||||
st.push(node); // 添加中节点
|
||||
st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。
|
||||
|
||||
} else { // 只有遇到空节点的时候,才将下一个节点放进结果集
|
||||
st.pop(); // 将空节点弹出
|
||||
node = st.peek(); // 重新取出栈中元素
|
||||
st.pop();
|
||||
result.add(node.val); // 加入到结果集
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
迭代法中序遍历代码如下:
|
||||
```java
|
||||
class Solution {
|
||||
public List<Integer> inorderTraversal(TreeNode root) {
|
||||
List<Integer> result = new LinkedList<>();
|
||||
Stack<TreeNode> st = new Stack<>();
|
||||
if (root != null) st.push(root);
|
||||
while (!st.empty()) {
|
||||
TreeNode node = st.peek();
|
||||
if (node != null) {
|
||||
st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
|
||||
if (node.right!=null) st.push(node.right); // 添加右节点(空节点不入栈)
|
||||
st.push(node); // 添加中节点
|
||||
st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。
|
||||
|
||||
if (node.left!=null) st.push(node.left); // 添加左节点(空节点不入栈)
|
||||
} else { // 只有遇到空节点的时候,才将下一个节点放进结果集
|
||||
st.pop(); // 将空节点弹出
|
||||
node = st.peek(); // 重新取出栈中元素
|
||||
st.pop();
|
||||
result.add(node.val); // 加入到结果集
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
```
|
||||
迭代法后序遍历代码如下:
|
||||
```java
|
||||
class Solution {
|
||||
|
||||
public List<Integer> postorderTraversal(TreeNode root) {
|
||||
List<Integer> result = new LinkedList<>();
|
||||
Stack<TreeNode> st = new Stack<>();
|
||||
if (root != null) st.push(root);
|
||||
while (!st.empty()) {
|
||||
TreeNode node = st.peek();
|
||||
if (node != null) {
|
||||
st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中
|
||||
st.push(node); // 添加中节点
|
||||
st.push(null); // 中节点访问过,但是还没有处理,加入空节点做为标记。
|
||||
if (node.right!=null) st.push(node.right); // 添加右节点(空节点不入栈)
|
||||
if (node.left!=null) st.push(node.left); // 添加左节点(空节点不入栈)
|
||||
|
||||
} else { // 只有遇到空节点的时候,才将下一个节点放进结果集
|
||||
st.pop(); // 将空节点弹出
|
||||
node = st.peek(); // 重新取出栈中元素
|
||||
st.pop();
|
||||
result.add(node.val); // 加入到结果集
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
Python:
|
||||
|
||||
|
||||
|
@ -160,11 +160,239 @@ Java:
|
||||
|
||||
|
||||
Python:
|
||||
```python3
|
||||
# 前序遍历-迭代-LC144_二叉树的前序遍历
|
||||
class Solution:
|
||||
def preorderTraversal(self, root: TreeNode) -> List[int]:
|
||||
# 根结点为空则返回空列表
|
||||
if not root:
|
||||
return []
|
||||
stack = [root]
|
||||
result = []
|
||||
while stack:
|
||||
node = stack.pop()
|
||||
# 中结点先处理
|
||||
result.append(node.val)
|
||||
# 右孩子先入栈
|
||||
if node.right:
|
||||
stack.append(node.right)
|
||||
# 左孩子后入栈
|
||||
if node.left:
|
||||
stack.append(node.left)
|
||||
return result
|
||||
|
||||
# 中序遍历-迭代-LC94_二叉树的中序遍历
|
||||
class Solution:
|
||||
def inorderTraversal(self, root: TreeNode) -> List[int]:
|
||||
if not root:
|
||||
return []
|
||||
stack = [] # 不能提前将root结点加入stack中
|
||||
result = []
|
||||
cur = root
|
||||
while cur or stack:
|
||||
# 先迭代访问最底层的左子树结点
|
||||
if cur:
|
||||
stack.append(cur)
|
||||
cur = cur.left
|
||||
# 到达最左结点后处理栈顶结点
|
||||
else:
|
||||
cur = stack.pop()
|
||||
result.append(cur.val)
|
||||
# 取栈顶元素右结点
|
||||
cur = cur.right
|
||||
return result
|
||||
|
||||
# 后序遍历-迭代-LC145_二叉树的后序遍历
|
||||
class Solution:
|
||||
def postorderTraversal(self, root: TreeNode) -> List[int]:
|
||||
if not root:
|
||||
return []
|
||||
stack = [root]
|
||||
result = []
|
||||
while stack:
|
||||
node = stack.pop()
|
||||
# 中结点先处理
|
||||
result.append(node.val)
|
||||
# 左孩子先入栈
|
||||
if node.left:
|
||||
stack.append(node.left)
|
||||
# 右孩子后入栈
|
||||
if node.right:
|
||||
stack.append(node.right)
|
||||
# 将最终的数组翻转
|
||||
return result[::-1]
|
||||
```
|
||||
|
||||
|
||||
Go:
|
||||
> 迭代法前序遍历
|
||||
|
||||
```go
|
||||
//迭代法前序遍历
|
||||
/**
|
||||
type Element struct {
|
||||
// 元素保管的值
|
||||
Value interface{}
|
||||
// 内含隐藏或非导出字段
|
||||
}
|
||||
|
||||
func (l *List) Back() *Element
|
||||
前序遍历:中左右
|
||||
压栈顺序:右左中
|
||||
**/
|
||||
func preorderTraversal(root *TreeNode) []int {
|
||||
if root == nil {
|
||||
return nil
|
||||
}
|
||||
var stack = list.New()
|
||||
stack.PushBack(root.Right)
|
||||
stack.PushBack(root.Left)
|
||||
res:=[]int{}
|
||||
res=append(res,root.Val)
|
||||
for stack.Len()>0 {
|
||||
e:=stack.Back()
|
||||
stack.Remove(e)
|
||||
node := e.Value.(*TreeNode)//e是Element类型,其值为e.Value.由于Value为接口,所以要断言
|
||||
if node==nil{
|
||||
continue
|
||||
}
|
||||
res=append(res,node.Val)
|
||||
stack.PushBack(node.Right)
|
||||
stack.PushBack(node.Left)
|
||||
}
|
||||
return res
|
||||
}
|
||||
```
|
||||
|
||||
> 迭代法后序遍历
|
||||
|
||||
```go
|
||||
//迭代法后序遍历
|
||||
//后续遍历:左右中
|
||||
//压栈顺序:中右左(按照前序遍历思路),再反转结果数组
|
||||
func postorderTraversal(root *TreeNode) []int {
|
||||
if root == nil {
|
||||
return nil
|
||||
}
|
||||
var stack = list.New()
|
||||
stack.PushBack(root.Left)
|
||||
stack.PushBack(root.Right)
|
||||
res:=[]int{}
|
||||
res=append(res,root.Val)
|
||||
for stack.Len()>0 {
|
||||
e:=stack.Back()
|
||||
stack.Remove(e)
|
||||
node := e.Value.(*TreeNode)//e是Element类型,其值为e.Value.由于Value为接口,所以要断言
|
||||
if node==nil{
|
||||
continue
|
||||
}
|
||||
res=append(res,node.Val)
|
||||
stack.PushBack(node.Left)
|
||||
stack.PushBack(node.Right)
|
||||
}
|
||||
for i:=0;i<len(res)/2;i++{
|
||||
res[i],res[len(res)-i-1] = res[len(res)-i-1],res[i]
|
||||
}
|
||||
return res
|
||||
}
|
||||
```
|
||||
|
||||
> 迭代法中序遍历
|
||||
|
||||
```go
|
||||
//迭代法中序遍历
|
||||
func inorderTraversal(root *TreeNode) []int {
|
||||
rootRes:=[]int{}
|
||||
if root==nil{
|
||||
return nil
|
||||
}
|
||||
stack:=list.New()
|
||||
node:=root
|
||||
//先将所有左节点找到,加入栈中
|
||||
for node!=nil{
|
||||
stack.PushBack(node)
|
||||
node=node.Left
|
||||
}
|
||||
//其次对栈中的每个节点先弹出加入到结果集中,再找到该节点的右节点的所有左节点加入栈中
|
||||
for stack.Len()>0{
|
||||
e:=stack.Back()
|
||||
node:=e.Value.(*TreeNode)
|
||||
stack.Remove(e)
|
||||
//找到该节点的右节点,再搜索他的所有左节点加入栈中
|
||||
rootRes=append(rootRes,node.Val)
|
||||
node=node.Right
|
||||
for node!=nil{
|
||||
stack.PushBack(node)
|
||||
node=node.Left
|
||||
}
|
||||
}
|
||||
return rootRes
|
||||
}
|
||||
```
|
||||
|
||||
javaScript
|
||||
|
||||
```js
|
||||
|
||||
前序遍历:
|
||||
|
||||
// 入栈 右 -> 左
|
||||
// 出栈 中 -> 左 -> 右
|
||||
var preorderTraversal = function(root, res = []) {
|
||||
if(!root) return res;
|
||||
const stack = [root];
|
||||
let cur = null;
|
||||
while(stack.length) {
|
||||
cur = stack.pop();
|
||||
res.push(cur.val);
|
||||
cur.right && stack.push(cur.right);
|
||||
cur.left && stack.push(cur.left);
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
中序遍历:
|
||||
|
||||
// 入栈 左 -> 右
|
||||
// 出栈 左 -> 中 -> 右
|
||||
|
||||
var inorderTraversal = function(root, res = []) {
|
||||
const stack = [];
|
||||
let cur = root;
|
||||
while(stack.length || cur) {
|
||||
if(cur) {
|
||||
stack.push(cur);
|
||||
// 左
|
||||
cur = cur.left;
|
||||
} else {
|
||||
// --> 弹出 中
|
||||
cur = stack.pop();
|
||||
res.push(cur.val);
|
||||
// 右
|
||||
cur = cur.right;
|
||||
}
|
||||
};
|
||||
return res;
|
||||
};
|
||||
|
||||
后序遍历:
|
||||
|
||||
// 入栈 左 -> 右
|
||||
// 出栈 中 -> 右 -> 左 结果翻转
|
||||
|
||||
var postorderTraversal = function(root, res = []) {
|
||||
if (!root) return res;
|
||||
const stack = [root];
|
||||
let cur = null;
|
||||
do {
|
||||
cur = stack.pop();
|
||||
res.push(cur.val);
|
||||
cur.left && stack.push(cur.left);
|
||||
cur.right && stack.push(cur.right);
|
||||
} while(stack.length);
|
||||
return res.reverse();
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
-----------------------
|
||||
|
@ -272,6 +272,41 @@ func PostorderTraversal(root *TreeNode) (res []int) {
|
||||
}
|
||||
```
|
||||
|
||||
javaScript:
|
||||
|
||||
```js
|
||||
|
||||
前序遍历:
|
||||
|
||||
var preorderTraversal = function(root, res = []) {
|
||||
if (!root) return res;
|
||||
res.push(root.val);
|
||||
preorderTraversal(root.left, res)
|
||||
preorderTraversal(root.right, res)
|
||||
return res;
|
||||
};
|
||||
|
||||
中序遍历:
|
||||
|
||||
var inorderTraversal = function(root, res = []) {
|
||||
if (!root) return res;
|
||||
inorderTraversal(root.left, res);
|
||||
res.push(root.val);
|
||||
inorderTraversal(root.right, res);
|
||||
return res;
|
||||
};
|
||||
|
||||
后序遍历:
|
||||
|
||||
var postorderTraversal = function(root, res = []) {
|
||||
if (!root) return res;
|
||||
postorderTraversal(root.left, res);
|
||||
postorderTraversal(root.right, res);
|
||||
res.push(root.val);
|
||||
return res;
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user