Merge branch 'master' into master

This commit is contained in:
程序员Carl
2023-07-25 10:01:13 +08:00
committed by GitHub
116 changed files with 2937 additions and 1556 deletions

View File

@@ -396,7 +396,7 @@
* [图论:深度优先搜索理论基础](./problems/图论深搜理论基础.md)
* [图论797.所有可能的路径](./problems/0797.所有可能的路径.md)
* [图论:广度优先搜索理论基础](./problems/图论广理论基础.md)
* [图论:广度优先搜索理论基础](./problems/图论广理论基础.md)
* [图论200.岛屿数量.深搜版](./problems/0200.岛屿数量.深搜版.md)
* [图论200.岛屿数量.广搜版](./problems/0200.岛屿数量.广搜版.md)
* [图论695.岛屿的最大面积](./problems/0695.岛屿的最大面积.md)

View File

@@ -5,7 +5,7 @@
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
## 1. 两数之和
# 1. 两数之和
[力扣题目链接](https://leetcode.cn/problems/two-sum/)
@@ -21,11 +21,13 @@
所以返回 [0, 1]
## 算法公开课
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[梦开始的地方Leetcode1.两数之和](https://www.bilibili.com/video/BV1aT41177mK),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
建议看一下我录的这期视频:[梦开始的地方Leetcode1.两数之和](https://www.bilibili.com/video/BV1aT41177mK),结合本题解来学习,事半功倍。
很明显暴力的解法是两层for循环查找时间复杂度是O(n^2)。
建议大家做这道题目之前,先做一下这两道
@@ -128,8 +130,8 @@ public:
## 其他语言版本
### Java
Java
```java
public int[] twoSum(int[] nums, int target) {
int[] res = new int[2];
@@ -150,8 +152,9 @@ public int[] twoSum(int[] nums, int target) {
}
```
Python
### Python
(版本一) 使用字典
```python
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
@@ -211,7 +214,7 @@ class Solution:
return [i,j]
```
Go
### Go
```go
// 暴力解法
@@ -242,7 +245,7 @@ func twoSum(nums []int, target int) []int {
}
```
Rust
### Rust:
```rust
use std::collections::HashMap;
@@ -263,9 +266,7 @@ impl Solution {
}
}
```
Rust
```
```rust
use std::collections::HashMap;
impl Solution {
@@ -284,7 +285,7 @@ impl Solution {
}
```
Javascript
### Javascript:
```javascript
var twoSum = function (nums, target) {
@@ -299,7 +300,7 @@ var twoSum = function (nums, target) {
};
```
TypeScript
### TypeScript
```typescript
function twoSum(nums: number[], target: number): number[] {
@@ -317,7 +318,7 @@ function twoSum(nums: number[], target: number): number[] {
};
```
php
### php:
```php
function twoSum(array $nums, int $target): array
@@ -337,7 +338,8 @@ function twoSum(array $nums, int $target): array
}
```
Swift
### Swift
```swift
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
// 值: 下标
@@ -353,8 +355,8 @@ func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
}
```
### Scala:
Scala:
```scala
object Solution {
// 导入包
@@ -377,7 +379,8 @@ object Solution {
}
```
C#:
### C#:
```csharp
public class Solution {
public int[] TwoSum(int[] nums, int target) {
@@ -396,7 +399,8 @@ public class Solution {
}
```
Dart:
### Dart:
```dart
List<int> twoSum(List<int> nums, int target) {
var tmp = [];
@@ -411,7 +415,8 @@ List<int> twoSum(List<int> nums, int target) {
}
```
C:
### C:
```c

View File

@@ -26,14 +26,15 @@
[-1, -1, 2]
]
## 算法公开课
# 思路
针对本题,我录制了视频讲解:[梦破碎的地方!| LeetCode15.三数之和](https://www.bilibili.com/video/BV1GW4y127qo),结合本题解一起看,事半功倍!
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[梦破碎的地方!| LeetCode15.三数之和](https://www.bilibili.com/video/BV1GW4y127qo),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
**注意[0 0 0 0] 这组数据**
## 哈希解法
## 思路
### 哈希解法
两层for循环就可以确定 a 和b 的数值了,可以使用哈希法来确定 0-(a+b) 是否在 数组里出现过,其实这个思路是正确的,但是我们有一个非常棘手的问题,就是题目中说的不可以包含重复的三元组。
@@ -87,7 +88,7 @@ public:
* 空间复杂度: O(n),额外的 set 开销
## 双指针
### 双指针
**其实这道题目使用哈希法并不十分合适**因为在去重的操作中有很多细节需要注意在面试中很难直接写出没有bug的代码。
@@ -166,9 +167,9 @@ public:
* 空间复杂度: O(1)
## 去重逻辑的思考
### 去重逻辑的思考
### a的去重
#### a的去重
说道去重其实主要考虑三个数的去重 a, b ,c, 对应的就是 nums[i]nums[left]nums[right]
@@ -188,7 +189,7 @@ a 如果重复了怎么办a是nums里遍历的元素那么应该直接跳
if (nums[i] == nums[i + 1]) { // 去重操作
continue;
}
```
```
那就我们就把 三元组中出现重复元素的情况直接pass掉了。 例如{-1, -1 ,2} 这组数据,当遍历到第一个-1 的时候,判断 下一个也是-1那这组数据就pass了。
@@ -208,7 +209,7 @@ if (i > 0 && nums[i] == nums[i - 1]) {
这是一个非常细节的思考过程。
### b与c的去重
#### b与c的去重
很多同学写本题的时候,去重的逻辑多加了 对right 和left 的去重:(代码中注释部分)
@@ -225,7 +226,7 @@ while (right > left) {
} else {
}
}
```
```
但细想一下,这种去重其实对提升程序运行效率是没有帮助的。
@@ -238,7 +239,7 @@ while (right > left) {
所以这种去重 是可以不加的。 仅仅是 把去重的逻辑提前了而已。
# 思考题
## 思考题
既然三数之和可以使用双指针法,我们之前讲过的[1.两数之和](https://programmercarl.com/0001.两数之和.html),可不可以使用双指针法呢?
@@ -254,8 +255,8 @@ while (right > left) {
## 其他语言版本
### Java
Java
```Java
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
@@ -297,8 +298,9 @@ class Solution {
}
```
Python
### Python
(版本一) 双指针
```Python
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
@@ -366,7 +368,7 @@ class Solution:
return result
```
Go
### Go
```Go
func threeSum(nums []int) [][]int {
@@ -407,7 +409,7 @@ func threeSum(nums []int) [][]int {
}
```
javaScript:
### JavaScript:
```js
var threeSum = function(nums) {
@@ -512,7 +514,7 @@ var threeSum = function (nums) {
};
```
TypeScript:
### TypeScript:
```typescript
function threeSum(nums: number[]): number[][] {
@@ -553,7 +555,8 @@ function threeSum(nums: number[]): number[][] {
};
```
ruby:
### Ruby:
```ruby
def is_valid(strs)
symbol_map = {')' => '(', '}' => '{', ']' => '['}
@@ -571,8 +574,8 @@ def is_valid(strs)
end
```
### PHP:
PHP:
```php
class Solution {
/**
@@ -613,7 +616,8 @@ class Solution {
}
```
Swift:
### Swift:
```swift
// 双指针法
func threeSum(_ nums: [Int]) -> [[Int]] {
@@ -654,7 +658,8 @@ func threeSum(_ nums: [Int]) -> [[Int]] {
}
```
Rust:
### Rust:
```Rust
// 哈希解法
use std::collections::HashSet;
@@ -718,7 +723,8 @@ impl Solution {
}
```
C:
### C:
```C
//qsort辅助cmp函数
int cmp(const void* ptr1, const void* ptr2) {
@@ -792,7 +798,8 @@ int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes
}
```
C#:
### C#:
```csharp
public class Solution
{
@@ -850,7 +857,8 @@ public class Solution
}
}
```
Scala:
### Scala:
```scala
object Solution {
// 导包
@@ -898,3 +906,4 @@ object Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -21,12 +21,12 @@
说明:尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[还得用回溯算法!| LeetCode17.电话号码的字母组合](https://www.bilibili.com/video/BV1yV4y1V7Ug),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[还得用回溯算法!| LeetCode17.电话号码的字母组合](https://www.bilibili.com/video/BV1yV4y1V7Ug),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
从示例上来说,输入"23"最直接的想法就是两层for循环遍历了吧正好把组合的情况都输出了。
@@ -40,7 +40,7 @@
2. 两个字母就两个for循环三个字符我就三个for循环以此类推然后发现代码根本写不出来
3. 输入1 * #按键等等异常情况
## 数字和字母如何映射
### 数字和字母如何映射
可以使用map或者定义一个二维数组例如string letterMap[10],来做映射,我这里定义一个二维数组,代码如下:
@@ -59,7 +59,7 @@ const string letterMap[10] = {
};
```
## 回溯法来解决n个for循环的问题
### 回溯法来解决n个for循环的问题
对于回溯法还不了解的同学看这篇:[关于回溯算法,你该了解这些!](https://programmercarl.com/回溯算法理论基础.html)
@@ -134,9 +134,6 @@ for (int i = 0; i < letters.size(); i++) {
**但是要知道会有这些异常,如果是现场面试中,一定要考虑到!**
## C++代码
关键地方都讲完了,按照[关于回溯算法,你该了解这些!](https://programmercarl.com/回溯算法理论基础.html)中的回溯法模板不难写出如下C++代码:
@@ -233,7 +230,7 @@ public:
所以大家可以按照版本一来写就可以了。
# 总结
## 总结
本篇将题目的三个要点一一列出,并重点强调了和前面讲解过的[77. 组合](https://programmercarl.com/0077.组合.html)和[216.组合总和III](https://programmercarl.com/0216.组合总和III.html)的区别,本题是多个集合求组合,所以在回溯的搜索过程中,都有一些细节需要注意的。
@@ -241,10 +238,10 @@ public:
# 其他语言版本
## 其他语言版本
## Java
### Java
```Java
class Solution {
@@ -286,7 +283,7 @@ class Solution {
}
```
## Python
### Python
回溯
```python
class Solution:
@@ -435,7 +432,7 @@ class Solution:
## Go
### Go
主要在于递归中传递下一个数字
@@ -470,7 +467,7 @@ func dfs(digits string, start int) {
}
```
## javaScript
### JavaScript
```js
var letterCombinations = function(digits) {
@@ -497,7 +494,7 @@ var letterCombinations = function(digits) {
};
```
## TypeScript
### TypeScript
```typescript
function letterCombinations(digits: string): string[] {
@@ -531,7 +528,7 @@ function letterCombinations(digits: string): string[] {
};
```
## Rust
### Rust
```Rust
const map: [&str; 10] = [
@@ -563,7 +560,7 @@ impl Solution {
}
```
## C
### C
```c
char* path;
@@ -625,7 +622,7 @@ char ** letterCombinations(char * digits, int* returnSize){
}
```
## Swift
### Swift
```swift
func letterCombinations(_ digits: String) -> [String] {
@@ -666,7 +663,7 @@ func letterCombinations(_ digits: String) -> [String] {
}
```
## Scala:
### Scala
```scala
object Solution {
@@ -702,3 +699,4 @@ object Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -27,9 +27,11 @@
[-2, 0, 0, 2]
]
# 思路
## 算法公开课
针对本题,我录制了视频讲解[难在去重和剪枝!| LeetCode18. 四数之和](https://www.bilibili.com/video/BV1DS4y147US)结合本题解一起看,事半功倍!
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[难在去重和剪枝!| LeetCode18. 四数之和](https://www.bilibili.com/video/BV1DS4y147US)相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
四数之和,和[15.三数之和](https://programmercarl.com/0015.三数之和.html)是一个思路,都是使用双指针法, 基本解法就是在[15.三数之和](https://programmercarl.com/0015.三数之和.html) 的基础上再套一层for循环。
@@ -141,22 +143,16 @@ if (nums[k] + nums[i] > target && nums[k] + nums[i] >= 0) {
if (nums[k] + nums[i] > target && nums[i] >= 0) {
break;
}
```
```
因为只要 nums[k] + nums[i] > target那么 nums[i] 后面的数都是正数的话,就一定 不符合条件了。
不过这种剪枝 其实有点 小绕,大家能够理解 文章给的完整代码的剪枝 就够了。
## 其他语言版本
### Java
Java
```Java
class Solution {
public List<List<Integer>> fourSum(int[] nums, int target) {
@@ -206,8 +202,9 @@ class Solution {
}
```
Python
### Python
(版本一) 双指针
```python
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
@@ -273,7 +270,8 @@ class Solution(object):
```
Go
### Go
```go
func fourSum(nums []int, target int) [][]int {
if len(nums) < 4 {
@@ -323,7 +321,7 @@ func fourSum(nums []int, target int) [][]int {
}
```
javaScript:
### JavaScript:
```js
/**
@@ -359,7 +357,7 @@ var fourSum = function(nums, target) {
};
```
TypeScript
### TypeScript
```typescript
function fourSum(nums: number[], target: number): number[][] {
@@ -400,7 +398,7 @@ function fourSum(nums: number[], target: number): number[][] {
};
```
PHP:
### PHP:
```php
class Solution {
@@ -445,7 +443,8 @@ class Solution {
}
```
Swift:
### Swift:
```swift
func fourSum(_ nums: [Int], _ target: Int) -> [[Int]] {
var res = [[Int]]()
@@ -493,7 +492,8 @@ func fourSum(_ nums: [Int], _ target: Int) -> [[Int]] {
}
```
C#:
### C#:
```csharp
public class Solution
{
@@ -555,7 +555,8 @@ public class Solution
}
```
Rust:
### Rust:
```Rust
use std::cmp::Ordering;
impl Solution {
@@ -603,7 +604,8 @@ impl Solution {
}
```
Scala:
### Scala:
```scala
object Solution {
// 导包
@@ -651,3 +653,4 @@ object Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -7,7 +7,7 @@
## 19.删除链表的倒数第N个节点
# 19.删除链表的倒数第N个节点
[力扣题目链接](https://leetcode.cn/problems/remove-nth-node-from-end-of-list/)
@@ -31,11 +31,13 @@
输入head = [1,2], n = 1
输出:[1]
## 算法公开课
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[链表遍历学清楚! | LeetCode19.删除链表倒数第N个节点](https://www.bilibili.com/video/BV1vW4y1U7Gf),相信结合视频再看本篇题解,更有助于大家对链表的理解。**
## 思路
《代码随想录》算法公开课:[链表遍历学清楚! | LeetCode19.删除链表倒数第N个节点](https://www.bilibili.com/video/BV1vW4y1U7Gf),相信结合视频在看本篇题解,更有助于大家对链表的理解。
双指针的经典应用如果要删除倒数第n个节点让fast移动n步然后让fast和slow同时移动直到fast指向链表末尾。删掉slow所指向的节点就可以了。
@@ -93,7 +95,7 @@ public:
## 其他语言版本
java:
### Java:
```java
public ListNode removeNthFromEnd(ListNode head, int n){
@@ -120,7 +122,8 @@ public ListNode removeNthFromEnd(ListNode head, int n){
}
```
Python:
### Python:
```python
# Definition for singly-linked list.
# class ListNode:
@@ -151,7 +154,8 @@ class Solution:
return dummy_head.next
```
Go:
### Go:
```Go
/**
* Definition for singly-linked list.
@@ -178,7 +182,7 @@ func removeNthFromEnd(head *ListNode, n int) *ListNode {
}
```
JavaScript:
### JavaScript:
```js
/**
@@ -198,7 +202,7 @@ var removeNthFromEnd = function(head, n) {
return ret.next;
};
```
TypeScript:
### TypeScript:
版本一(快慢指针法):
@@ -263,7 +267,7 @@ function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null {
};
```
Kotlin:
### Kotlin:
```Kotlin
fun removeNthFromEnd(head: ListNode?, n: Int): ListNode? {
@@ -284,7 +288,8 @@ fun removeNthFromEnd(head: ListNode?, n: Int): ListNode? {
}
```
Swift
### Swift
```swift
func removeNthFromEnd(_ head: ListNode?, _ n: Int) -> ListNode? {
if head == nil {
@@ -309,8 +314,8 @@ func removeNthFromEnd(_ head: ListNode?, _ n: Int) -> ListNode? {
}
```
### PHP:
PHP:
```php
function removeNthFromEnd($head, $n) {
// 设置虚拟头节点
@@ -332,7 +337,8 @@ function removeNthFromEnd($head, $n) {
}
```
Scala:
### Scala:
```scala
object Solution {
def removeNthFromEnd(head: ListNode, n: Int): ListNode = {
@@ -356,7 +362,8 @@ object Solution {
}
```
Rust:
### Rust:
```rust
impl Solution {
pub fn remove_nth_from_end(head: Option<Box<ListNode>>, mut n: i32) -> Option<Box<ListNode>> {
@@ -377,7 +384,8 @@ impl Solution {
}
}
```
C语言
### C
```c
/**c语言单链表的定义
* Definition for singly-linked list.
@@ -412,7 +420,8 @@ struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
```
C#
### C#
```csharp
public class Solution {
public ListNode RemoveNthFromEnd(ListNode head, int n) {

View File

@@ -39,12 +39,13 @@
* 输入: "{[]}"
* 输出: true
# 思路
## 算法公开课
《代码随想录》算法视频公开课:[栈的拿手好戏!| LeetCode20. 有效的括号](https://www.bilibili.com/video/BV1AF411w78g),相信结合视频看本篇题解,更有助于大家对链表的理解。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[栈的拿手好戏!| LeetCode20. 有效的括号](https://www.bilibili.com/video/BV1AF411w78g),相信结合视频看本篇题解,更有助于大家对本题的理解**
## 思路
## 题外话
### 题外话
**括号匹配是使用栈解决的经典问题。**
@@ -68,7 +69,7 @@ cd a/b/c/../../
这里我就不过多展开了,先来看题。
## 进入正题
### 进入正题
由于栈结构的特殊性,非常适合做对称匹配类的题目。
@@ -143,8 +144,8 @@ public:
## 其他语言版本
### Java
Java
```Java
class Solution {
public boolean isValid(String s) {
@@ -171,7 +172,8 @@ class Solution {
}
```
Python
### Python
```python
# 方法一,仅使用栈,更省空间
class Solution:
@@ -213,7 +215,8 @@ class Solution:
return True if not stack else False
```
Go
### Go
```Go
func isValid(s string) bool {
hash := map[byte]byte{')':'(', ']':'[', '}':'{'}
@@ -235,7 +238,8 @@ func isValid(s string) bool {
}
```
Ruby:
### Ruby:
```ruby
def is_valid(strs)
symbol_map = {')' => '(', '}' => '{', ']' => '['}
@@ -253,7 +257,8 @@ def is_valid(strs)
end
```
Javascript:
### Javascript:
```javascript
var isValid = function (s) {
const stack = [];
@@ -296,7 +301,7 @@ var isValid = function(s) {
};
```
TypeScript:
### TypeScript:
版本一:普通版
@@ -348,7 +353,7 @@ function isValid(s: string): boolean {
};
```
Swift
### Swift:
```swift
func isValid(_ s: String) -> Bool {
@@ -373,7 +378,8 @@ func isValid(_ s: String) -> Bool {
}
```
C:
### C:
```C
//辅助函数判断栈顶元素与输入的括号是否为一对。若不是则返回False
int notMatch(char par, char* stack, int stackTop) {
@@ -414,8 +420,8 @@ bool isValid(char * s){
}
```
### C#:
C#:
```csharp
public class Solution {
public bool IsValid(string s) {
@@ -447,7 +453,8 @@ public class Solution {
}
```
PHP:
### PHP:
```php
// https://www.php.net/manual/zh/class.splstack.php
class Solution
@@ -475,8 +482,8 @@ class Solution
}
```
### Scala:
Scala:
```scala
object Solution {
import scala.collection.mutable
@@ -499,7 +506,7 @@ object Solution {
}
```
rust:
### Rust:
```rust
impl Solution {

View File

@@ -5,7 +5,7 @@
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
## 24. 两两交换链表中的节点
# 24. 两两交换链表中的节点
[力扣题目链接](https://leetcode.cn/problems/swap-nodes-in-pairs/)
@@ -16,9 +16,11 @@
<img src='https://code-thinking.cdn.bcebos.com/pics/24.%E4%B8%A4%E4%B8%A4%E4%BA%A4%E6%8D%A2%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B9-%E9%A2%98%E6%84%8F.jpg' width=600 alt='24.两两交换链表中的节点-题意'> </img></div>
## 思路
## 算法公开课
《代码随想录》算法公开课:[帮你把链表细节学清楚! | LeetCode24. 两两交换链表中的节点](https://www.bilibili.com/video/BV1YT411g7br),相信结合视频看本篇题解,更有助于大家对链表的理解。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[帮你把链表细节学清楚! | LeetCode24. 两两交换链表中的节点](https://www.bilibili.com/video/BV1YT411g7br),相信结合视频看本篇题解,更有助于大家对本题的理解**
## 思路
这道题目正常模拟就可以了。
@@ -88,7 +90,8 @@ public:
## 其他语言版本
C:
### C:
```c
/**
* Definition for singly-linked list.
@@ -132,7 +135,7 @@ struct ListNode* swapPairs(struct ListNode* head){
}
```
Java
### Java
```Java
// 递归版本
@@ -176,7 +179,32 @@ class Solution {
}
```
Python
### Python
```python
# 递归版本
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
if head is None or head.next is None:
return head
# 待翻转的两个node分别是pre和cur
pre = head
cur = head.next
next = head.next.next
cur.next = pre # 交换
pre.next = self.swapPairs(next) # 将以next为head的后续链表两两交换
return cur
```
```python
# Definition for singly-linked list.
# class ListNode:
@@ -202,7 +230,8 @@ class Solution:
```
Go
### Go
```go
func swapPairs(head *ListNode) *ListNode {
dummy := &ListNode{
@@ -238,7 +267,8 @@ func swapPairs(head *ListNode) *ListNode {
}
```
Javascript:
### Javascript:
```javascript
var swapPairs = function (head) {
let ret = new ListNode(0, head), temp = ret;
@@ -253,7 +283,7 @@ var swapPairs = function (head) {
};
```
TypeScript
### TypeScript
```typescript
function swapPairs(head: ListNode | null): ListNode | null {
@@ -272,7 +302,7 @@ function swapPairs(head: ListNode | null): ListNode | null {
};
```
Kotlin:
### Kotlin:
```kotlin
fun swapPairs(head: ListNode?): ListNode? {
@@ -292,7 +322,8 @@ fun swapPairs(head: ListNode?): ListNode? {
}
```
Swift:
### Swift:
```swift
func swapPairs(_ head: ListNode?) -> ListNode? {
if head == nil || head?.next == nil {
@@ -313,7 +344,8 @@ func swapPairs(_ head: ListNode?) -> ListNode? {
return dummyHead.next
}
```
Scala:
### Scala:
```scala
// 虚拟头节点
object Solution {
@@ -337,7 +369,8 @@ object Solution {
}
```
PHP:
### PHP:
```php
//虚拟头结点
function swapPairs($head) {
@@ -380,7 +413,7 @@ function swapPairs($head)
}
```
Rust:
### Rust:
```rust
// 虚拟头节点

View File

@@ -5,7 +5,7 @@
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
## 27. 移除元素
# 27. 移除元素
[力扣题目链接](https://leetcode.cn/problems/remove-element/)
@@ -26,9 +26,12 @@
**你不需要考虑数组中超出新长度后面的元素。**
## 思路
针对本题,我录制了视频讲解:[数组中移除元素并不容易LeetCode27. 移除元素](https://www.bilibili.com/video/BV12A4y1Z7LP),结合本题解一起看,事半功倍!
## 算法公开课
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[数组中移除元素并不容易LeetCode27. 移除元素](https://www.bilibili.com/video/BV12A4y1Z7LP),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
有的同学可能说了,多余的元素,删掉不就得了。
@@ -156,8 +159,8 @@ public:
## 其他语言版本
### Java
Java
```java
class Solution {
public int removeElement(int[] nums, int val) {
@@ -194,7 +197,7 @@ class Solution {
}
```
Python
### Python
``` python 3
@@ -230,8 +233,8 @@ class Solution:
```
### Go
Go
```go
func removeElement(nums []int, val int) int {
length:=len(nums)
@@ -272,7 +275,8 @@ func removeElement(nums []int, val int) int {
}
```
JavaScript:
### JavaScript:
```javascript
//时间复杂度O(n)
//空间复杂度O(1)
@@ -287,7 +291,7 @@ var removeElement = (nums, val) => {
};
```
TypeScript
### TypeScript
```typescript
function removeElement(nums: number[], val: number): number {
@@ -302,7 +306,7 @@ function removeElement(nums: number[], val: number): number {
};
```
Ruby:
### Ruby:
```ruby
def remove_element(nums, val)
@@ -316,7 +320,8 @@ def remove_element(nums, val)
i
end
```
Rust:
### Rust:
```rust
impl Solution {
pub fn remove_element(nums: &mut Vec<i32>, val: i32) -> i32 {
@@ -332,7 +337,7 @@ impl Solution {
}
```
Swift:
### Swift:
```swift
func removeElement(_ nums: inout [Int], _ val: Int) -> Int {
@@ -348,7 +353,8 @@ func removeElement(_ nums: inout [Int], _ val: Int) -> Int {
}
```
PHP:
### PHP:
```php
class Solution {
/**
@@ -372,7 +378,8 @@ class Solution {
}
```
C:
### C:
```c
int removeElement(int* nums, int numsSize, int val){
int slow = 0;
@@ -388,7 +395,8 @@ int removeElement(int* nums, int numsSize, int val){
}
```
Kotlin:
### Kotlin:
```kotlin
fun removeElement(nums: IntArray, `val`: Int): Int {
var slowIndex = 0 // 初始化慢指针
@@ -399,7 +407,8 @@ fun removeElement(nums: IntArray, `val`: Int): Int {
}
```
Scala:
### Scala:
```scala
object Solution {
def removeElement(nums: Array[Int], `val`: Int): Int = {
@@ -415,7 +424,8 @@ object Solution {
}
```
C#:
### C#:
```csharp
public class Solution {
public int RemoveElement(int[] nums, int val) {

View File

@@ -28,7 +28,7 @@
对于本题而言 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。
# 思路
## 思路
本题是KMP 经典题目。
@@ -60,13 +60,13 @@ KMP的经典思想就是:**当出现字符串不匹配时,可以记录一部
读完本篇可以顺便把leetcode上28.实现strStr()题目做了。
# 什么是KMP
### 什么是KMP
说到KMP先说一下KMP这个名字是怎么来的为什么叫做KMP呢。
因为是由这三位学者发明的KnuthMorris和Pratt所以取了三位学者名字的首字母。所以叫做KMP
# KMP有什么用
### KMP有什么用
KMP主要应用在字符串匹配上。
@@ -84,7 +84,7 @@ KMP的主要思想是**当出现字符串不匹配时,可以知道一部分之
下面Carl就带大家把KMP的精髓next数组弄清楚。
# 什么是前缀表
### 什么是前缀表
写过KMP的同学一定都写过next数组那么这个next数组究竟是个啥呢
@@ -122,7 +122,7 @@ next数组就是一个前缀表prefix table
那么什么是前缀表:**记录下标i之前包括i的字符串中有多大长度的相同前缀后缀。**
# 最长公共前后缀
### 最长公共前后缀
文章中字符串的**前缀是指不包含最后一个字符的所有以第一个字符开头的连续子串**。
@@ -144,7 +144,7 @@ next数组就是一个前缀表prefix table
等等.....。
# 为什么一定要用前缀表
### 为什么一定要用前缀表
这就是前缀表,那为啥就能告诉我们 上次匹配的位置,并跳过去呢?
@@ -163,7 +163,7 @@ next数组就是一个前缀表prefix table
**很多介绍KMP的文章或者视频并没有把为什么要用前缀表这个问题说清楚而是直接默认使用前缀表。**
# 如何计算前缀表
### 如何计算前缀表
接下来就要说一说怎么计算前缀表。
@@ -205,7 +205,7 @@ next数组就是一个前缀表prefix table
最后就在文本串中找到了和模式串匹配的子串了。
# 前缀表与next数组
### 前缀表与next数组
很多KMP算法的时间都是使用next数组来做回退操作那么next数组与前缀表有什么关系呢
@@ -217,7 +217,7 @@ next数组就可以是前缀表但是很多实现都是把前缀表统一减
后面我会提供两种不同的实现代码,大家就明白了。
# 使用next数组来匹配
### 使用next数组来匹配
**以下我们以前缀表统一减一之后的next数组来做演示**
@@ -229,7 +229,7 @@ next数组就可以是前缀表但是很多实现都是把前缀表统一减
![KMP精讲4](https://code-thinking.cdn.bcebos.com/gifs/KMP%E7%B2%BE%E8%AE%B24.gif)
# 时间复杂度分析
### 时间复杂度分析
其中n为文本串长度m为模式串长度因为在匹配的过程中根据前缀表不断调整匹配的位置可以看出匹配的过程是O(n)之前还要单独生成next数组时间复杂度是O(m)。所以整个KMP算法的时间复杂度是O(n+m)的。
@@ -239,7 +239,7 @@ next数组就可以是前缀表但是很多实现都是把前缀表统一减
都知道使用KMP算法一定要构造next数组。
# 构造next数组
### 构造next数组
我们定义一个函数getNext来构建next数组函数参数为指向next数组的指针和一个字符串。 代码如下:
@@ -338,7 +338,7 @@ void getNext(int* next, const string& s){
得到了next数组之后就要用这个来做匹配了。
# 使用next数组来做匹配
### 使用next数组来做匹配
在文本串s里 找是否出现过模式串t。
@@ -403,7 +403,7 @@ for (int i = 0; i < s.size(); i++) { // 注意i就从0开始
此时所有逻辑的代码都已经写出来了,力扣 28.实现strStr 题目的整体代码如下:
# 前缀表统一减一 C++代码实现
### 前缀表统一减一 C++代码实现
```CPP
class Solution {
@@ -447,7 +447,7 @@ public:
* 时间复杂度: O(n + m)
* 空间复杂度: O(m), 只需要保存字符串needle的前缀表
# 前缀表不减一C++实现
### 前缀表不减一C++实现
那么前缀表就不减一了,也不右移的,到底行不行呢?
@@ -546,7 +546,7 @@ public:
* 空间复杂度: O(m)
# 总结
## 总结
我们介绍了什么是KMPKMP可以解决什么问题然后分析KMP算法里的next数组知道了next数组就是前缀表再分析为什么要是前缀表而不是什么其他表。
@@ -563,8 +563,7 @@ public:
## 其他语言版本
Java
### Java
```Java
class Solution {
@@ -691,8 +690,9 @@ class Solution {
}
```
Python3
### Python3
(版本一)前缀表(减一)
```python
class Solution:
def getNext(self, next, s):
@@ -781,9 +781,9 @@ class Solution:
def strStr(self, haystack: str, needle: str) -> int:
return haystack.find(needle)
```
```
Go
### Go
```go
// 方法一:前缀表使用减1实现
@@ -871,7 +871,7 @@ func strStr(haystack string, needle string) int {
}
```
JavaScript版本
### JavaScript:
> 前缀表统一减一
@@ -959,7 +959,7 @@ var strStr = function (haystack, needle) {
};
```
TypeScript版本:
### TypeScript:
> 前缀表统一减一
@@ -1036,7 +1036,7 @@ function strStr(haystack: string, needle: string): number {
}
```
Swift 版本
### Swift:
> 前缀表统一减一
@@ -1196,7 +1196,7 @@ func strStr(_ haystack: String, _ needle: String) -> Int {
```
PHP
### PHP
> 前缀表统一减一
```php
@@ -1272,7 +1272,7 @@ function getNext(&$next, $s){
}
```
Rust:
### Rust:
> 前缀表统一不减一
```Rust
@@ -1362,4 +1362,3 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -6,8 +6,7 @@
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
如果对回溯法理论还不清楚的同学,可以先看这个视频[视频来了!!带你学透回溯算法(理论篇)](https://mp.weixin.qq.com/s/wDd5azGIYWjbU0fdua_qBg)
> 如果对回溯法理论还不清楚的同学,可以先看这个视频[视频来了!!带你学透回溯算法(理论篇)](https://mp.weixin.qq.com/s/wDd5azGIYWjbU0fdua_qBg)
# 37. 解数独
@@ -35,11 +34,9 @@
* 你可以假设给定的数独只有唯一解。
* 给定数独永远是 9x9 形式的。
# 算法公开课
**《代码随想录》算法视频公开课:[回溯算法二维递归?解数独不过如此!| LeetCode37. 解数独](https://www.bilibili.com/video/BV1TW4y1471V/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 算法公开课
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[回溯算法二维递归?解数独不过如此!| LeetCode37. 解数独](https://www.bilibili.com/video/BV1TW4y1471V/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -764,3 +761,4 @@ object Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -39,11 +39,11 @@ candidates 中的数字可以无限制重复被选取。
[3,5]
]
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[Leetcode:39. 组合总和讲解](https://www.bilibili.com/video/BV1KT4y1M7HJ),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[Leetcode:39. 组合总和讲解](https://www.bilibili.com/video/BV1KT4y1M7HJ),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
题目中的**无限制重复被选取,吓得我赶紧想想 出现0 可咋办**然后看到下面提示1 <= candidates[i] <= 200我就放心了。
@@ -57,7 +57,7 @@ candidates 中的数字可以无限制重复被选取。
而在[77.组合](https://programmercarl.com/0077.组合.html)和[216.组合总和III](https://programmercarl.com/0216.组合总和III.html) 中都可以知道要递归K层因为要取k个元素的组合。
## 回溯三部曲
### 回溯三部曲
* 递归函数参数
@@ -156,7 +156,7 @@ public:
};
```
## 剪枝优化
### 剪枝优化
在这个树形结构中:
@@ -217,7 +217,7 @@ public:
* 时间复杂度: O(n * 2^n),注意这只是复杂度的上界,因为剪枝的存在,真实的时间复杂度远小于此
* 空间复杂度: O(target)
# 总结
## 总结
本题和我们之前讲过的[77.组合](https://programmercarl.com/0077.组合.html)、[216.组合总和III](https://programmercarl.com/0216.组合总和III.html)有两点不同:
@@ -238,10 +238,10 @@ public:
# 其他语言版本
## 其他语言版本
## Java
### Java
```Java
// 剪枝优化
@@ -271,7 +271,7 @@ class Solution {
}
```
## Python
### Python
回溯(版本一)
@@ -370,7 +370,7 @@ class Solution:
```
## Go
### Go
主要在于递归中传递下一个数字
@@ -404,7 +404,7 @@ func dfs(candidates []int, start int, target int) {
}
```
## JavaScript
### JavaScript
```js
var combinationSum = function(candidates, target) {
@@ -430,7 +430,7 @@ var combinationSum = function(candidates, target) {
};
```
## TypeScript
### TypeScript
```typescript
function combinationSum(candidates: number[], target: number): number[][] {
@@ -456,7 +456,7 @@ function combinationSum(candidates: number[], target: number): number[][] {
};
```
## Rust
### Rust
```Rust
impl Solution {
@@ -485,7 +485,7 @@ impl Solution {
}
```
## C
### C
```c
int* path;
@@ -541,7 +541,7 @@ int** combinationSum(int* candidates, int candidatesSize, int target, int* retur
}
```
## Swift
### Swift
```swift
func combinationSum(_ candidates: [Int], _ target: Int) -> [[Int]] {
@@ -570,7 +570,7 @@ func combinationSum(_ candidates: [Int], _ target: Int) -> [[Int]] {
}
```
## Scala
### Scala
```scala
object Solution {
@@ -604,3 +604,4 @@ object Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -41,13 +41,11 @@ candidates 中的每个数字在每个组合中只能使用一次。
]
```
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[回溯算法中的去重,树层去重树枝去重,你弄清楚了没?| LeetCode:40.组合总和II](https://www.bilibili.com/video/BV12V4y1V73A),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[回溯算法中的去重,树层去重树枝去重,你弄清楚了没?| LeetCode:40.组合总和II](https://www.bilibili.com/video/BV12V4y1V73A),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
这道题目和[39.组合总和](https://programmercarl.com/0039.组合总和.html)如下区别:
@@ -86,7 +84,7 @@ candidates 中的每个数字在每个组合中只能使用一次。
可以看到图中,每个节点相对于 [39.组合总和](https://mp.weixin.qq.com/s/FLg8G6EjVcxBjwCbzpACPw)我多加了used数组这个used数组下面会重点介绍。
## 回溯三部曲
### 回溯三部曲
* **递归函数参数**
@@ -217,7 +215,7 @@ public:
* 时间复杂度: O(n * 2^n)
* 空间复杂度: O(n)
## 补充
### 补充
这里直接用startIndex来去重也是可以的 就不用used数组了。
@@ -257,7 +255,7 @@ public:
```
# 总结
## 总结
本题同样是求组合总和但就是因为其数组candidates有重复元素而要求不能有重复的组合所以相对于[39.组合总和](https://programmercarl.com/0039.组合总和.html)难度提升了不少。
@@ -265,14 +263,10 @@ public:
所以Carl有必要把去重的这块彻彻底底的给大家讲清楚**就连“树层去重”和“树枝去重”都是我自创的词汇,希望对大家理解有帮助!**
## 其他语言版本
# 其他语言版本
## Java
### Java
**使用标记数组**
```Java
class Solution {
@@ -355,7 +349,7 @@ class Solution {
}
```
## Python
### Python
回溯
```python
class Solution:
@@ -442,7 +436,7 @@ class Solution:
self.combinationSumHelper(candidates, target - candidates[i], i + 1, path, results)
path.pop()
```
## Go
### Go
主要在于如何在回溯中去重
**使用used数组**
@@ -518,7 +512,7 @@ func dfs(candidates []int, start int, target int) {
}
}
```
## javaScript
### JavaScript
```js
/**
@@ -588,7 +582,7 @@ var combinationSum2 = function(candidates, target) {
};
```
## TypeScript
### TypeScript
```typescript
function combinationSum2(candidates: number[], target: number): number[][] {
@@ -619,7 +613,7 @@ function combinationSum2(candidates: number[], target: number): number[][] {
};
```
## Rust
### Rust
```Rust
impl Solution {
@@ -654,7 +648,7 @@ impl Solution {
}
```
## C
### C
```c
int* path;
@@ -716,7 +710,7 @@ int** combinationSum2(int* candidates, int candidatesSize, int target, int* retu
}
```
## Swift
### Swift
```swift
func combinationSum2(_ candidates: [Int], _ target: Int) -> [[Int]] {
@@ -749,7 +743,7 @@ func combinationSum2(_ candidates: [Int], _ target: Int) -> [[Int]] {
```
## Scala
### Scala
```scala
object Solution {
@@ -784,3 +778,4 @@ object Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -24,9 +24,9 @@
]
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[组合与排列的区别,回溯算法求解的时候,有何不同?| LeetCode46.全排列](https://www.bilibili.com/video/BV19v4y1S79W/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[组合与排列的区别,回溯算法求解的时候,有何不同?| LeetCode46.全排列](https://www.bilibili.com/video/BV19v4y1S79W/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -491,3 +491,4 @@ object Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -31,9 +31,9 @@
* 1 <= nums.length <= 8
* -10 <= nums[i] <= 10
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[回溯算法求解全排列,如何去重?| LeetCode47.全排列 II](https://www.bilibili.com/video/BV1R84y1i7Tm/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[回溯算法求解全排列,如何去重?| LeetCode47.全排列 II](https://www.bilibili.com/video/BV1R84y1i7Tm/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -58,7 +58,7 @@
在[46.全排列](https://programmercarl.com/0046.全排列.html)中已经详细讲解了排列问题的写法,在[40.组合总和II](https://programmercarl.com/0040.组合总和II.html) 、[90.子集II](https://programmercarl.com/0090.子集II.html)中详细讲解了去重的写法,所以这次我就不用回溯三部曲分析了,直接给出代码,如下:
## C++代码
```CPP
class Solution {
@@ -170,7 +170,7 @@ if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == true) {
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
```
```
其实并不行,一定要加上 `used[i - 1] == false`或者`used[i - 1] == true`,因为 used[i - 1] 要一直是 true 或者一直是false 才可以,而不是 一会是true 一会又是false。 所以这个条件要写上。
@@ -179,7 +179,7 @@ if (i > 0 && nums[i] == nums[i - 1]) {
## 其他语言版本
### java
### Java
```java
class Solution {
@@ -221,7 +221,7 @@ class Solution {
}
```
### python
Python
```python
class Solution:
@@ -526,3 +526,4 @@ object Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -28,9 +28,9 @@ n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,
* 输入n = 1
* 输出:[["Q"]]
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[这就是传说中的N皇后 回溯算法安排!| LeetCode51.N皇后](https://www.bilibili.com/video/BV1Rd4y1c7Bq/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[这就是传说中的N皇后 回溯算法安排!| LeetCode51.N皇后](https://www.bilibili.com/video/BV1Rd4y1c7Bq/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -864,3 +864,4 @@ object Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -43,13 +43,11 @@ n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并
  ".Q.."]
]
# 思路
## 思路
详看:[51.N皇后](https://mp.weixin.qq.com/s/lU_QwCMj6g60nh8m98GAWg) ,基本没有区别
# C++代码
```CPP
class Solution {
private:
@@ -100,8 +98,9 @@ public:
};
```
# 其他语言补充
JavaScript
## 其他语言补充
### JavaScript
```javascript
var totalNQueens = function(n) {
let count = 0;
@@ -146,7 +145,7 @@ var totalNQueens = function(n) {
};
```
TypeScript
### TypeScript
```typescript
// 0-该格为空1-该格有皇后
@@ -199,7 +198,7 @@ function checkValid(chess: GridStatus[][], i: number, j: number, n: number): boo
}
```
C
### C
```c
//path[i]为在i行path[i]列上存在皇后
@@ -258,7 +257,8 @@ int totalNQueens(int n){
return answer;
}
```
Java
### Java
```java
class Solution {
int count = 0;
@@ -310,4 +310,3 @@ class Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -6,7 +6,7 @@
## 59.螺旋矩阵II
# 59.螺旋矩阵II
[力扣题目链接](https://leetcode.cn/problems/spiral-matrix-ii/)
@@ -22,9 +22,12 @@
[ 7, 6, 5 ]
]
## 思路
为了利于录友们理解,我特意录制了视频,[拿下螺旋矩阵LeetCode59.螺旋矩阵II](https://www.bilibili.com/video/BV1SL4y1N7mV),结合视频一起看,事半功倍!
## 算法公开课
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[拿下螺旋矩阵LeetCode59.螺旋矩阵II](https://www.bilibili.com/video/BV1SL4y1N7mV),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
这道题目可以说在面试中出现频率较高的题目,**本题并不涉及到什么算法,就是模拟过程,但却十分考察对代码的掌控能力。**
@@ -122,15 +125,15 @@ public:
## 类似题目
* 54.螺旋矩阵
* 剑指Offer 29.顺时针打印矩阵
* [54.螺旋矩阵](https://leetcode.cn/problems/spiral-matrix/)
* [剑指Offer 29.顺时针打印矩阵](https://leetcode.cn/problems/shun-shi-zhen-da-yin-ju-zhen-lcof/)
## 其他语言版本
Java
### Java
```Java
class Solution {
@@ -173,7 +176,7 @@ class Solution {
}
```
python3:
### python3:
```python
class Solution:
@@ -204,7 +207,7 @@ class Solution:
return nums
```
javaScript
### JavaScript:
```javascript
@@ -256,7 +259,7 @@ var generateMatrix = function(n) {
```
TypeScript:
### TypeScript:
```typescript
function generateMatrix(n: number): number[][] {
@@ -301,7 +304,7 @@ function generateMatrix(n: number): number[][] {
};
```
Go:
### Go:
```go
package main
@@ -394,7 +397,7 @@ func generateMatrix(n int) [][]int {
}
```
Swift:
### Swift:
```swift
func generateMatrix(_ n: Int) -> [[Int]] {
@@ -450,7 +453,7 @@ func generateMatrix(_ n: Int) -> [[Int]] {
}
```
Rust:
### Rust:
```rust
impl Solution {
@@ -503,7 +506,8 @@ impl Solution {
}
```
PHP:
### PHP:
```php
class Solution {
/**
@@ -545,7 +549,8 @@ class Solution {
}
```
C:
### C:
```c
int** generateMatrix(int n, int* returnSize, int** returnColumnSizes){
//初始化返回的结果数组的大小
@@ -604,7 +609,8 @@ int** generateMatrix(int n, int* returnSize, int** returnColumnSizes){
return ans;
}
```
Scala:
### Scala:
```scala
object Solution {
def generateMatrix(n: Int): Array[Array[Int]] = {
@@ -656,7 +662,8 @@ object Solution {
}
}
```
C#
### C#
```csharp
public class Solution {
public int[][] GenerateMatrix(int n) {
@@ -685,3 +692,4 @@ public class Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -5,10 +5,6 @@
</a>
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
# 第77题. 组合
[力扣题目链接](https://leetcode.cn/problems/combinations/ )
@@ -27,13 +23,12 @@
[1,4],
]
# 算法公开课
## 算法公开课
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[带你学透回溯算法-组合问题对应力扣题目77.组合)](https://www.bilibili.com/video/BV1ti4y1L7cv)[组合问题的剪枝操作](https://www.bilibili.com/video/BV1wi4y157er),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**《代码随想录》算法视频公开课:[带你学透回溯算法-组合问题对应力扣题目77.组合)](https://www.bilibili.com/video/BV1ti4y1L7cv)[组合问题的剪枝操作](https://www.bilibili.com/video/BV1wi4y157er),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
本题是回溯法的经典题目。
@@ -108,7 +103,7 @@ for (int i = 1; i <= n; i++) {
在[关于回溯算法,你该了解这些!](https://programmercarl.com/回溯算法理论基础.html)中我们提到了回溯法三部曲,那么我们按照回溯法三部曲开始正式讲解代码了。
## 回溯法三部曲
### 回溯法三部曲
* 递归函数的返回值以及参数
@@ -345,11 +340,10 @@ public:
## 其他语言版本
### Java
未剪枝优化
```java
@@ -474,7 +468,7 @@ func dfs(n int, k int, start int) {
}
```
### javascript
### Javascript
剪枝:
@@ -774,3 +768,4 @@ object Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -7,8 +7,11 @@
# 77.组合优化
## 算法公开课
**《代码随想录》算法视频公开课:[组合问题的剪枝操作](https://www.bilibili.com/video/BV1wi4y157er),相信结合视频在看本篇题解,更有助于大家对本题的理解**
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[组合问题的剪枝操作](https://www.bilibili.com/video/BV1wi4y157er),相信结合视频在看本篇题解,更有助于大家对本题的理解**
## 思路
在[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)中我们通过回溯搜索法解决了n个数中求k个数的组合问题。
@@ -46,7 +49,7 @@ public:
};
```
# 剪枝优化
## 剪枝优化
我们说过,回溯法虽然是暴力搜索,但也有时候可以有点剪枝优化一下的。
@@ -135,7 +138,7 @@ public:
# 总结
## 总结
本篇我们针对求组合问题的回溯法代码做了剪枝优化,这个优化如果不画图的话,其实不好理解,也不好讲清楚。
@@ -143,14 +146,10 @@ public:
**就酱学到了就帮Carl转发一下吧让更多的同学知道这里**
## 其他语言版本
### Java
Java
```java
class Solution {
List<List<Integer>> result = new ArrayList<>();
@@ -179,7 +178,8 @@ class Solution {
}
```
Python
### Python
```python
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
@@ -199,7 +199,8 @@ class Solution:
```
Go
### Go
```Go
var (
path []int
@@ -227,7 +228,7 @@ func dfs(n int, k int, start int) {
}
```
javaScript:
### JavaScript
```js
var combine = function(n, k) {
@@ -249,7 +250,7 @@ var combine = function(n, k) {
};
```
TypeScript
### TypeScript
```typescript
function combine(n: number, k: number): number[][] {
@@ -270,7 +271,7 @@ function combine(n: number, k: number): number[][] {
};
```
Rust:
### Rust
```Rust
impl Solution {
@@ -296,7 +297,7 @@ impl Solution {
}
```
C:
### C
```c
int* path;
@@ -351,7 +352,7 @@ int** combine(int n, int k, int* returnSize, int** returnColumnSizes){
}
```
Swift
### Swift
```swift
func combine(_ n: Int, _ k: Int) -> [[Int]] {
@@ -381,7 +382,7 @@ func combine(_ n: Int, _ k: Int) -> [[Int]] {
}
```
Scala:
### Scala
```scala
object Solution {
@@ -414,3 +415,4 @@ object Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -27,12 +27,12 @@
  []
]
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[回溯算法解决子集问题,树上节点都是目标集和! | LeetCode78.子集](https://www.bilibili.com/video/BV1U84y1q7Ci),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[回溯算法解决子集问题,树上节点都是目标集和! | LeetCode78.子集](https://www.bilibili.com/video/BV1U84y1q7Ci),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
求子集问题和[77.组合](https://programmercarl.com/0077.组合.html)和[131.分割回文串](https://programmercarl.com/0131.分割回文串.html)又不一样了。
@@ -52,7 +52,7 @@
从图中红线部分,可以看出**遍历这个树的时候,把所有节点都记录下来,就是要求的子集集合**。
## 回溯三部曲
### 回溯三部曲
* 递归函数参数
@@ -102,8 +102,6 @@ for (int i = startIndex; i < nums.size(); i++) {
}
```
## C++代码
根据[关于回溯算法,你该了解这些!](https://programmercarl.com/回溯算法理论基础.html)给出的回溯算法模板:
```
@@ -158,7 +156,7 @@ public:
并不会因为每次递归的下一层就是从i+1开始的。
# 总结
## 总结
相信大家经过了
* 组合问题:
@@ -178,10 +176,10 @@ public:
**而组合问题、分割问题是收集树形结构中叶子节点的结果**
# 其他语言版本
## 其他语言版本
## Java
### Java
```java
class Solution {
List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合
@@ -205,7 +203,7 @@ class Solution {
}
```
## Python
### Python
```python
class Solution:
def subsets(self, nums):
@@ -224,7 +222,7 @@ class Solution:
path.pop()
```
## Go
### Go
```Go
var (
path []int
@@ -248,7 +246,7 @@ func dfs(nums []int, start int) {
}
```
## Javascript
### Javascript
```Javascript
var subsets = function(nums) {
@@ -267,7 +265,7 @@ var subsets = function(nums) {
};
```
## TypeScript
### TypeScript
```typescript
function subsets(nums: number[]): number[][] {
@@ -287,7 +285,7 @@ function subsets(nums: number[]): number[][] {
};
```
## Rust
### Rust
```Rust
impl Solution {
@@ -311,7 +309,7 @@ impl Solution {
}
```
## C
### C
```c
int* path;
@@ -369,7 +367,7 @@ int** subsets(int* nums, int numsSize, int* returnSize, int** returnColumnSizes)
}
```
## Swift
### Swift
```swift
func subsets(_ nums: [Int]) -> [[Int]] {
@@ -392,7 +390,7 @@ func subsets(_ nums: [Int]) -> [[Int]] {
}
```
## Scala
### Scala
思路一: 使用本题解思路
@@ -451,3 +449,4 @@ object Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -3,8 +3,6 @@
<img src="../pics/训练营.png" width="1000"/>
</a>
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
# 90.子集II
[力扣题目链接](https://leetcode.cn/problems/subsets-ii/)
@@ -25,9 +23,9 @@
[]
]
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[回溯算法解决子集问题,如何去重?| LeetCode90.子集II](https://www.bilibili.com/video/BV1vm4y1F71J/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[回溯算法解决子集问题,如何去重?| LeetCode90.子集II](https://www.bilibili.com/video/BV1vm4y1F71J/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -240,7 +238,7 @@ class Solution {
#### Python3
### Python3
回溯 利用used数组去重
```python
@@ -646,3 +644,4 @@ object Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -40,16 +40,12 @@
* 0 <= s.length <= 3000
* s 仅由数字组成
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[93.复原IP地址](https://www.bilibili.com/video/BV1XP4y1U73i/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
# 算法公开课
**《代码随想录》算法视频公开课:[回溯算法如何分割字符串并判断是合法IP| LeetCode93.复原IP地址](https://www.bilibili.com/video/BV1XP4y1U73i/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[回溯算法如何分割字符串并判断是合法IP| LeetCode93.复原IP地址](https://www.bilibili.com/video/BV1XP4y1U73i/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
做这道题目之前,最好先把[131.分割回文串](https://programmercarl.com/0131.分割回文串.html)这个做了。
@@ -63,7 +59,7 @@
![93.复原IP地址](https://code-thinking-1253855093.file.myqcloud.com/pics/20201123203735933.png)
## 回溯三部曲
### 回溯三部曲
* 递归参数
@@ -134,7 +130,7 @@ for (int i = startIndex; i < s.size(); i++) {
}
```
## 判断子串是否合法
### 判断子串是否合法
最后就是在写一个判断段位是否是有效段位了。
@@ -169,8 +165,6 @@ bool isValid(const string& s, int start, int end) {
}
```
## C++代码
根据[关于回溯算法,你该了解这些!](https://programmercarl.com/回溯算法理论基础.html)给出的回溯算法模板:
@@ -247,7 +241,7 @@ public:
* 时间复杂度: O(3^4)IP地址最多包含4个数字每个数字最多有3种可能的分割方式则搜索树的最大深度为4每个节点最多有3个子节点。
* 空间复杂度: O(n)
# 总结
## 总结
在[131.分割回文串](https://programmercarl.com/0131.分割回文串.html)中我列举的分割字符串的难点,本题都覆盖了。
@@ -259,9 +253,9 @@ public:
# 其他语言版本
## 其他语言版本
## java
### Java
```java
class Solution {
@@ -402,7 +396,7 @@ class Solution {
```
## python
### Python
回溯(版本一)
```python
@@ -478,9 +472,7 @@ class Solution:
```
## Go
### Go
```go
var (
@@ -517,7 +509,7 @@ func dfs(s string, start int) {
}
```
## JavaScript
### JavaScript
```js
/**
@@ -547,7 +539,7 @@ var restoreIpAddresses = function(s) {
};
```
## TypeScript
### TypeScript
```typescript
function isValidIpSegment(str: string): boolean {
@@ -586,7 +578,7 @@ function restoreIpAddresses(s: string): string[] {
};
```
## Rust
### Rust
```Rust
impl Solution {
@@ -643,7 +635,7 @@ impl Solution {
}
```
## C
### C
```c
//记录结果
char** result;
@@ -719,7 +711,7 @@ char ** restoreIpAddresses(char * s, int* returnSize){
}
```
## Swift
### Swift
```swift
// 判断区间段是否合法
@@ -766,7 +758,7 @@ func restoreIpAddresses(_ s: String) -> [String] {
}
```
## Scala
### Scala
```scala
object Solution {
@@ -813,3 +805,4 @@ object Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -20,18 +20,18 @@
![98.验证二叉搜索树](https://code-thinking-1253855093.file.myqcloud.com/pics/20230310000750.png)
# 视频讲解
## 算法公开课
**《代码随想录》算法视频公开课:[你对二叉搜索树了解的还不够! | LeetCode98.验证二叉搜索树](https://www.bilibili.com/video/BV18P411n7Q4),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[你对二叉搜索树了解的还不够! | LeetCode98.验证二叉搜索树](https://www.bilibili.com/video/BV18P411n7Q4),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
要知道中序遍历下,输出的二叉搜索树节点的数值是有序序列。
有了这个特性,**验证二叉搜索树,就相当于变成了判断一个序列是不是递增的了。**
## 递归法
### 递归法
可以递归中序遍历将二叉搜索树转变成一个数组,代码如下:
@@ -211,7 +211,7 @@ public:
最后这份代码看上去整洁一些,思路也清晰。
## 迭代法
### 迭代法
可以用迭代法模拟二叉树中序遍历,对前中后序迭代法生疏的同学可以看这两篇[二叉树:听说递归能做的,栈也能做!](https://programmercarl.com/二叉树的迭代遍历.html)[二叉树:前中后序迭代方式统一写法](https://programmercarl.com/二叉树的统一迭代法.html)
@@ -245,7 +245,7 @@ public:
在[二叉树:二叉搜索树登场!](https://programmercarl.com/0700.二叉搜索树中的搜索.html)中我们分明写出了痛哭流涕的简洁迭代法,怎么在这里不行了呢,因为本题是要验证二叉搜索树啊。
# 总结
## 总结
这道题目是一个简单题,但对于没接触过的同学还是有难度的。
@@ -254,10 +254,10 @@ public:
只要把基本类型的题目都做过,总结过之后,思路自然就开阔了。
# 其他语言版本
## 其他语言版本
## Java
### Java
```Java
//使用統一迭代法
@@ -369,7 +369,7 @@ class Solution {
}
```
## Python
### Python
递归法(版本一)利用中序递增性质,转换成数组
```python
@@ -479,7 +479,7 @@ class Solution:
```
## Go
### Go
```Go
func isValidBST(root *TreeNode) bool {
@@ -526,7 +526,7 @@ func isValidBST(root *TreeNode) bool {
}
```
## JavaScript
### JavaScript
辅助数组解决
@@ -595,7 +595,7 @@ var isValidBST = function (root) {
};
```
## TypeScript
### TypeScript
> 辅助数组解决:
@@ -637,7 +637,7 @@ function isValidBST(root: TreeNode | null): boolean {
};
```
## Scala
### Scala
辅助数组解决:
```scala
@@ -682,7 +682,7 @@ object Solution {
}
```
## rust
### Rust
递归:
@@ -735,3 +735,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -13,9 +13,11 @@
![101. 对称二叉树](https://code-thinking-1253855093.file.myqcloud.com/pics/20210203144607387.png)
# 思路
## 算法公开课
《代码随想录》算法视频公开课:[同时操作两个二叉树 | LeetCode101. 对称二叉树](https://www.bilibili.com/video/BV1ue4y1Y7Mf),相信结合视频看本篇题解,更有助于大家对本题的理解。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[同时操作两个二叉树 | LeetCode101. 对称二叉树](https://www.bilibili.com/video/BV1ue4y1Y7Mf) 相信结合视频看本篇题解,更有助于大家对本题的理解**
## 思路
**首先想清楚,判断对称二叉树要比较的是哪两个节点,要比较的可不是左右节点!**
@@ -41,7 +43,7 @@
那么我们先来看看递归法的代码应该怎么写。
## 递归法
### 递归法
递归三部曲
@@ -159,13 +161,13 @@ public:
**所以建议大家做题的时候,一定要想清楚逻辑,每一步做什么。把题目所有情况想到位,相应的代码写出来之后,再去追求简洁代码的效果。**
## 迭代法
### 迭代法
这道题目我们也可以使用迭代法,但要注意,这里的迭代法可不是前中后序的迭代写法,因为本题的本质是判断两个树是否是相互翻转的,其实已经不是所谓二叉树遍历的前中后序的关系了。
这里我们可以使用队列来比较两个树(根节点的左右子树)是否相互翻转,(**注意这不是层序遍历**
### 使用队列
#### 使用队列
通过队列来判断根节点的左子树和右子树的内侧和外侧是否相等,如动画所示:
@@ -207,7 +209,7 @@ public:
};
```
### 使用栈
#### 使用栈
细心的话,其实可以发现,这个迭代法,其实是把左右两个子树要比较的元素顺序放进一个容器,然后成对成对的取出来进行比较,那么其实使用栈也是可以的。
@@ -254,12 +256,12 @@ public:
这两道题目基本和本题是一样的只要稍加修改就可以AC。
* 100.相同的树
* 572.另一个树的子树
* [100.相同的树](https://leetcode.cn/problems/same-tree/)
* [572.另一个树的子树](https://leetcode.cn/problems/subtree-of-another-tree/)
# 其他语言版本
## 其他语言版本
Java
### Java:
```Java
/**
@@ -364,7 +366,7 @@ Java
```
Python
### Python:
递归法:
```python
@@ -470,7 +472,8 @@ class Solution:
return True
```
Go
### Go:
```go
/**
* Definition for a binary tree node.
@@ -521,8 +524,7 @@ func isSymmetric(root *TreeNode) bool {
}
```
JavaScript
### JavaScript:
递归判断是否为对称二叉树:
```javascript
@@ -610,7 +612,7 @@ var isSymmetric = function(root) {
};
```
TypeScript
### TypeScript
> 递归法
@@ -679,7 +681,7 @@ function isSymmetric(root: TreeNode | null): boolean {
};
```
Swift:
### Swift:
> 递归
```swift
@@ -761,7 +763,7 @@ func isSymmetric3(_ root: TreeNode?) -> Bool {
}
```
Scala
### Scala:
> 递归:
```scala
@@ -835,7 +837,7 @@ object Solution {
}
```
## Rust
### Rust:
递归:
```rust
@@ -900,3 +902,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -8,21 +8,23 @@
# 二叉树层序遍历登场!
《代码随想录》算法视频公开课:[讲透二叉树的层序遍历 | 广度优先搜索 | LeetCode102.二叉树的层序遍历](https://www.bilibili.com/video/BV1GY4y1u7b2),相信结合视频在看本篇题解,更有助于大家对本题的理解。
## 算法公开课
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[讲透二叉树的层序遍历 | 广度优先搜索 | LeetCode102.二叉树的层序遍历](https://www.bilibili.com/video/BV1GY4y1u7b2),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
学会二叉树的层序遍历,可以一口气打完以下十题:
* 102.二叉树的层序遍历
* 107.二叉树的层次遍历II
* 199.二叉树的右视图
* 637.二叉树的层平均值
* 429.N叉树的层序遍历
* 515.在每个树行中找最大值
* 116.填充每个节点的下一个右侧节点指针
* 117.填充每个节点的下一个右侧节点指针II
* 104.二叉树的最大深度
* 111.二叉树的最小深度
* [102.二叉树的层序遍历](https://leetcode.cn/problems/binary-tree-level-order-traversal/)
* [107.二叉树的层次遍历II](https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/)
* [199.二叉树的右视图](https://leetcode.cn/problems/binary-tree-right-side-view/)
* [637.二叉树的层平均值](https://leetcode.cn/problems/binary-tree-right-side-view/)
* [429.N叉树的层序遍历](https://leetcode.cn/problems/n-ary-tree-level-order-traversal/)
* [515.在每个树行中找最大值](https://leetcode.cn/problems/find-largest-value-in-each-tree-row/)
* [116.填充每个节点的下一个右侧节点指针](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/)
* [117.填充每个节点的下一个右侧节点指针II](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node-ii/)
* [104.二叉树的最大深度](https://leetcode.cn/problems/maximum-depth-of-binary-tree/)
* [111.二叉树的最小深度](https://leetcode.cn/problems/minimum-depth-of-binary-tree/)
@@ -31,7 +33,7 @@
# 102.二叉树的层序遍历
## 102.二叉树的层序遍历
[力扣题目链接](https://leetcode.cn/problems/binary-tree-level-order-traversal/)
@@ -39,7 +41,7 @@
![102.二叉树的层序遍历](https://code-thinking-1253855093.file.myqcloud.com/pics/20210203144842988.png)
思路
### 思路
我们之前讲过了三篇关于二叉树的深度优先遍历的文章:
@@ -63,7 +65,7 @@
代码如下:**这份代码也可以作为二叉树层序遍历的模板,打十个就靠它了**。
C++代码:
c++代码如下
```CPP
class Solution {
@@ -111,7 +113,9 @@ public:
};
```
java:
### 其他语言版本
#### Java:
```Java
// 102.二叉树的层序遍历
@@ -167,7 +171,7 @@ class Solution {
}
```
python3代码
#### Python:
```python
@@ -219,12 +223,9 @@ class Solution:
self.helper(node.left, level + 1, levels)
self.helper(node.right, level + 1, levels)
```
go:
#### Go:
```go
/**
@@ -320,7 +321,7 @@ func levelOrder(root *TreeNode) (res [][]int) {
}
```
javascript代码
#### Javascript
```javascript
var levelOrder = function(root) {
@@ -350,7 +351,7 @@ var levelOrder = function(root) {
```
TypeScript
#### TypeScript
```typescript
function levelOrder(root: TreeNode | null): number[][] {
@@ -377,7 +378,7 @@ function levelOrder(root: TreeNode | null): number[][] {
};
```
Swift
#### Swift
```swift
func levelOrder(_ root: TreeNode?) -> [[Int]] {
@@ -403,7 +404,7 @@ func levelOrder(_ root: TreeNode?) -> [[Int]] {
}
```
Scala:
#### Scala:
```scala
// 102.二叉树的层序遍历
@@ -430,7 +431,7 @@ object Solution {
}
```
Rust:
#### Rust:
```rust
use std::cell::RefCell;
@@ -466,7 +467,7 @@ impl Solution {
**此时我们就掌握了二叉树的层序遍历了,那么如下九道力扣上的题目,只需要修改模板的两三行代码(不能再多了),便可打倒!**
# 107.二叉树的层次遍历 II
## 107.二叉树的层次遍历 II
[力扣题目链接](https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/)
@@ -474,7 +475,7 @@ impl Solution {
![107.二叉树的层次遍历II](https://code-thinking-1253855093.file.myqcloud.com/pics/20210203151058308.png)
思路
### 思路
相对于102.二叉树的层序遍历就是最后把result数组反转一下就可以了。
@@ -506,7 +507,9 @@ public:
};
```
python代码
### 其他语言版本
#### Python
```python
class Solution:
@@ -537,7 +540,7 @@ class Solution:
return result[::-1]
```
Java
#### Java
```java
// 107. 二叉树的层序遍历 II
@@ -618,12 +621,10 @@ class Solution {
return ans;
}
}
```
go:
#### Go:
```GO
/**
@@ -662,7 +663,7 @@ func levelOrderBottom(root *TreeNode) [][]int {
}
```
javascript代码
#### Javascript:
```javascript
var levelOrderBottom = function(root) {
@@ -688,7 +689,7 @@ var levelOrderBottom = function(root) {
};
```
TypeScript:
#### TypeScript:
```typescript
function levelOrderBottom(root: TreeNode | null): number[][] {
@@ -711,7 +712,7 @@ function levelOrderBottom(root: TreeNode | null): number[][] {
};
```
Swift
#### Swift
```swift
func levelOrderBottom(_ root: TreeNode?) -> [[Int]] {
@@ -737,8 +738,7 @@ func levelOrderBottom(_ root: TreeNode?) -> [[Int]] {
}
```
Scala:
#### Scala:
```scala
// 107.二叉树的层次遍历II
@@ -764,7 +764,10 @@ object Solution {
res.reverse.toList
}
Rust:
```
#### Rust:
```rust
use std::cell::RefCell;
@@ -796,7 +799,7 @@ impl Solution {
}
```
# 199.二叉树的右视图
## 199.二叉树的右视图
[力扣题目链接](https://leetcode.cn/problems/binary-tree-right-side-view/)
@@ -804,7 +807,7 @@ impl Solution {
![199.二叉树的右视图](https://code-thinking-1253855093.file.myqcloud.com/pics/20210203151307377.png)
思路
### 思路
层序遍历的时候判断是否遍历到单层的最后面的元素如果是就放进result数组中随后返回result就可以了。
@@ -832,7 +835,9 @@ public:
};
```
python代码
### 其他语言版本
#### Python
```python
# Definition for a binary tree node.
@@ -866,8 +871,7 @@ class Solution:
return right_view
```
Java:
#### Java:
```java
// 199.二叉树的右视图
@@ -911,7 +915,7 @@ public class N0199 {
}
```
go:
#### Go:
```GO
/**
@@ -945,8 +949,7 @@ func rightSideView(root *TreeNode) []int {
}
```
javascript代码:
#### Javascript:
```javascript
var rightSideView = function(root) {
@@ -972,7 +975,7 @@ var rightSideView = function(root) {
};
```
TypeScript
#### TypeScript
```typescript
function rightSideView(root: TreeNode | null): number[] {
@@ -992,7 +995,7 @@ function rightSideView(root: TreeNode | null): number[] {
};
```
Swift
#### Swift
```swift
func rightSideView(_ root: TreeNode?) -> [Int] {
@@ -1017,7 +1020,7 @@ func rightSideView(_ root: TreeNode?) -> [Int] {
}
```
Scala:
#### Scala:
```scala
// 199.二叉树的右视图
@@ -1043,7 +1046,7 @@ object Solution {
}
```
rust:
#### Rust:
```rust
use std::cell::RefCell;
@@ -1076,7 +1079,7 @@ impl Solution {
}
```
# 637.二叉树的层平均值
## 637.二叉树的层平均值
[力扣题目链接](https://leetcode.cn/problems/average-of-levels-in-binary-tree/)
@@ -1084,7 +1087,7 @@ impl Solution {
![637.二叉树的层平均值](https://code-thinking-1253855093.file.myqcloud.com/pics/20210203151350500.png)
思路:
### 思路
本题就是层序遍历的时候把一层求个总和在取一个均值。
@@ -1115,7 +1118,9 @@ public:
```
python代码
### 其他语言版本
#### Python
```python
class Solution:
@@ -1155,7 +1160,7 @@ class Solution:
return averages
```
java:
#### Java:
```java
// 637. 二叉树的层平均值
@@ -1197,7 +1202,7 @@ public class N0637 {
}
```
go:
#### Go:
```GO
/**
@@ -1235,7 +1240,7 @@ func averageOfLevels(root *TreeNode) []float64 {
}
```
javascript代码
#### Javascript
```javascript
var averageOfLevels = function(root) {
@@ -1262,7 +1267,7 @@ var averageOfLevels = function(root) {
};
```
TypeScript
#### TypeScript
```typescript
function averageOfLevels(root: TreeNode | null): number[] {
@@ -1286,7 +1291,7 @@ function averageOfLevels(root: TreeNode | null): number[] {
};
```
Swift
#### Swift
```swift
func averageOfLevels(_ root: TreeNode?) -> [Double] {
@@ -1313,7 +1318,7 @@ func averageOfLevels(_ root: TreeNode?) -> [Double] {
}
```
Scala:
#### Scala:
```scala
// 637.二叉树的层平均值
@@ -1339,7 +1344,7 @@ object Solution {
}
```
rust:
#### Rust:
```rust
use std::cell::RefCell;
@@ -1372,7 +1377,7 @@ impl Solution {
}
```
# 429.N叉树的层序遍历
## 429.N叉树的层序遍历
[力扣题目链接](https://leetcode.cn/problems/n-ary-tree-level-order-traversal/)
@@ -1390,8 +1395,7 @@ impl Solution {
[5,6]
]
思路:
### 思路
这道题依旧是模板题,只不过一个节点有多个孩子了
@@ -1423,7 +1427,9 @@ public:
};
```
python代码
### 其他语言版本
#### Python
```python
"""
@@ -1475,7 +1481,7 @@ class Solution:
return result
```
java:
#### Java:
```java
// 429. N 叉树的层序遍历
@@ -1535,8 +1541,7 @@ public class N0429 {
}
```
go:
#### Go:
```GO
/**
@@ -1567,7 +1572,7 @@ func levelOrder(root *Node) [][]int {
}
```
JavaScript代码
#### JavaScript
```JavaScript
var levelOrder = function(root) {
@@ -1596,7 +1601,7 @@ var levelOrder = function(root) {
};
```
TypeScript:
#### TypeScript:
```typescript
function levelOrder(root: Node | null): number[][] {
@@ -1618,7 +1623,7 @@ function levelOrder(root: Node | null): number[][] {
};
```
Swift
#### Swift
```swift
func levelOrder(_ root: Node?) -> [[Int]] {
@@ -1643,7 +1648,7 @@ func levelOrder(_ root: Node?) -> [[Int]] {
}
```
Scala:
#### Scala:
```scala
// 429.N叉树的层序遍历
@@ -1672,7 +1677,7 @@ object Solution {
}
```
rust:
#### Rust:
```rust
pub struct Solution;
@@ -1720,7 +1725,7 @@ impl Solution {
}
```
# 515.在每个树行中找最大值
## 515.在每个树行中找最大值
[力扣题目链接](https://leetcode.cn/problems/find-largest-value-in-each-tree-row/)
@@ -1728,7 +1733,7 @@ impl Solution {
![515.在每个树行中找最大值](https://code-thinking-1253855093.file.myqcloud.com/pics/20210203151532153.png)
思路
### 思路
层序遍历,取每一层的最大值
@@ -1758,7 +1763,9 @@ public:
};
```
python代码
### 其他语言版本
#### Python
```python
# Definition for a binary tree node.
@@ -1794,7 +1801,7 @@ class Solution:
return result
```
java代码
#### Java
```java
class Solution {
@@ -1820,7 +1827,7 @@ class Solution {
}
```
go:
#### Go:
```GO
/**
@@ -1864,7 +1871,7 @@ func max(x, y int) int {
}
```
javascript代码
#### Javascript
```javascript
var largestValues = function(root) {
@@ -1890,7 +1897,7 @@ var largestValues = function(root) {
};
```
TypeScript:
#### TypeScript:
```typescript
function largestValues(root: TreeNode | null): number[] {
@@ -1916,7 +1923,7 @@ function largestValues(root: TreeNode | null): number[] {
};
```
Swift
#### Swift
```swift
func largestValues(_ root: TreeNode?) -> [Int] {
@@ -1943,7 +1950,7 @@ func largestValues(_ root: TreeNode?) -> [Int] {
}
```
Scala:
#### Scala:
```scala
// 515.在每个树行中找最大值
@@ -1970,7 +1977,7 @@ object Solution {
}
```
rust:
#### Rust:
```rust
use std::cell::RefCell;
@@ -2002,7 +2009,7 @@ impl Solution {
}
```
# 116.填充每个节点的下一个右侧节点指针
## 116.填充每个节点的下一个右侧节点指针
[力扣题目链接](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/)
@@ -2024,7 +2031,7 @@ struct Node {
![116.填充每个节点的下一个右侧节点指针](https://code-thinking-1253855093.file.myqcloud.com/pics/20210203152044855.jpg)
思路:
### 思路
本题依然是层序遍历,只不过在单层遍历的时候记录一下本层的头部节点,然后在遍历的时候让前一个节点指向本节点就可以了
@@ -2063,7 +2070,9 @@ public:
};
```
java代码
### 其他语言版本
#### Java
```java
class Solution {
@@ -2093,7 +2102,7 @@ class Solution {
}
```
python代码
#### Python
```python
"""
@@ -2133,7 +2142,7 @@ class Solution:
return root
```
go:
#### Go:
```GO
/**
@@ -2173,7 +2182,7 @@ func connect(root *Node) *Node {
```
JavaScript:
#### JavaScript:
```javascript
/**
@@ -2209,7 +2218,7 @@ var connect = function(root) {
```
TypeScript:
#### TypeScript:
```typescript
function connect(root: Node | null): Node | null {
@@ -2234,7 +2243,7 @@ function connect(root: Node | null): Node | null {
};
```
Swift
#### Swift
```swift
func connect(_ root: Node?) -> Node? {
@@ -2266,7 +2275,7 @@ func connect(_ root: Node?) -> Node? {
}
```
Scala:
#### Scala:
```scala
// 116.填充每个节点的下一个右侧节点指针
@@ -2297,11 +2306,11 @@ object Solution {
}
```
# 117.填充每个节点的下一个右侧节点指针II
## 117.填充每个节点的下一个右侧节点指针II
[力扣题目链接](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node-ii/)
思路
### 思路
这道题目说是二叉树但116题目说是完整二叉树其实没有任何差别一样的代码一样的逻辑一样的味道
@@ -2339,7 +2348,9 @@ public:
};
```
Java 代码:
### 其他语言版本
#### Java
```java
// 二叉树之层次遍历
@@ -2377,7 +2388,7 @@ class Solution {
}
```
python代码
#### Python
```python
# 层序遍历解法
@@ -2420,7 +2431,7 @@ class Solution:
```
go:
#### Go:
```GO
/**
@@ -2459,7 +2470,7 @@ func connect(root *Node) *Node {
}
```
JavaScript:
#### JavaScript:
```javascript
/**
@@ -2494,7 +2505,7 @@ var connect = function(root) {
};
```
TypeScript:
#### TypeScript:
```typescript
function connect(root: Node | null): Node | null {
@@ -2519,7 +2530,7 @@ function connect(root: Node | null): Node | null {
};
```
Swift
#### Swift
```swift
func connect(_ root: Node?) -> Node? {
@@ -2551,7 +2562,7 @@ func connect(_ root: Node?) -> Node? {
}
```
Scala:
#### Scala:
```scala
// 117.填充每个节点的下一个右侧节点指针II
@@ -2582,7 +2593,7 @@ object Solution {
}
```
# 104.二叉树的最大深度
## 104.二叉树的最大深度
[力扣题目链接](https://leetcode.cn/problems/maximum-depth-of-binary-tree/)
@@ -2600,7 +2611,7 @@ object Solution {
返回它的最大深度 3 。
思路
### 思路
使用迭代法的话,使用层序遍历是最为合适的,因为最大的深度就是二叉树的层数,和层序遍历的方式极其吻合。
@@ -2635,7 +2646,9 @@ public:
};
```
Java
### 其他语言版本
#### Java
```Java
class Solution {
@@ -2661,7 +2674,7 @@ class Solution {
}
```
Python
#### Python
```python 3
# Definition for a binary tree node.
@@ -2691,7 +2704,7 @@ class Solution:
```
Go
#### Go
```go
/**
@@ -2726,7 +2739,7 @@ func maxDepth(root *TreeNode) int {
}
```
JavaScript
#### JavaScript
```javascript
/**
@@ -2759,7 +2772,7 @@ var maxDepth = function(root) {
};
```
TypeScript:
#### TypeScript:
```typescript
function maxDepth(root: TreeNode | null): number {
@@ -2779,7 +2792,7 @@ function maxDepth(root: TreeNode | null): number {
};
```
Swift
#### Swift
```swift
func maxDepth(_ root: TreeNode?) -> Int {
@@ -2804,7 +2817,7 @@ func maxDepth(_ root: TreeNode?) -> Int {
}
```
Scala:
#### Scala:
```scala
// 104.二叉树的最大深度
@@ -2829,7 +2842,7 @@ object Solution {
}
```
rust:
#### Rust:
```rust
use std::cell::RefCell;
@@ -2859,10 +2872,12 @@ impl Solution {
}
```
# 111.二叉树的最小深度
## 111.二叉树的最小深度
[力扣题目链接](https://leetcode.cn/problems/minimum-depth-of-binary-tree/)
### 思路
相对于 104.二叉树的最大深度 ,本题还也可以使用层序遍历的方式来解决,思路是一样的。
**需要注意的是,只有当左右孩子都为空的时候,才说明遍历的最低点了。如果其中一个孩子为空则不是最低点**
@@ -2895,7 +2910,9 @@ public:
};
```
Java
### 其他语言版本
#### Java
```java
class Solution {
@@ -2925,9 +2942,7 @@ class Solution {
}
```
Python 3
#### Python
```python 3
# Definition for a binary tree node.
@@ -2960,7 +2975,7 @@ class Solution:
return depth
```
Go
#### Go
```go
/**
@@ -2999,7 +3014,7 @@ func minDepth(root *TreeNode) int {
}
```
JavaScript
#### JavaScript
```javascript
/**
@@ -3035,7 +3050,7 @@ var minDepth = function(root) {
};
```
TypeScript:
#### TypeScript:
```typescript
function minDepth(root: TreeNode | null): number {
@@ -3056,7 +3071,7 @@ function minDepth(root: TreeNode | null): number {
};
```
Swift
#### Swift
```swift
func minDepth(_ root: TreeNode?) -> Int {
@@ -3082,7 +3097,7 @@ func minDepth(_ root: TreeNode?) -> Int {
}
```
Scala:
#### Scala:
```scala
// 111.二叉树的最小深度
@@ -3108,7 +3123,7 @@ object Solution {
}
```
rust:
#### Rust:
```rust
use std::cell::RefCell;
@@ -3141,28 +3156,27 @@ impl Solution {
}
```
# 总结
## 总结
二叉树的层序遍历,**就是图论中的广度优先搜索在二叉树中的应用**,需要借助队列来实现(此时又发现队列的一个应用了)。
来吧,一口气打十个:
* 102.二叉树的层序遍历
* 107.二叉树的层次遍历II
* 199.二叉树的右视图
* 637.二叉树的层平均值
* 429.N叉树的层序遍历
* 515.在每个树行中找最大值
* 116.填充每个节点的下一个右侧节点指针
* 117.填充每个节点的下一个右侧节点指针II
* 104.二叉树的最大深度
* 111.二叉树的最小深度
* [102.二叉树的层序遍历](https://leetcode.cn/problems/binary-tree-level-order-traversal/)
* [107.二叉树的层次遍历II](https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/)
* [199.二叉树的右视图](https://leetcode.cn/problems/binary-tree-right-side-view/)
* [637.二叉树的层平均值](https://leetcode.cn/problems/binary-tree-right-side-view/)
* [429.N叉树的层序遍历](https://leetcode.cn/problems/n-ary-tree-level-order-traversal/)
* [515.在每个树行中找最大值](https://leetcode.cn/problems/find-largest-value-in-each-tree-row/)
* [116.填充每个节点的下一个右侧节点指针](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/)
* [117.填充每个节点的下一个右侧节点指针II](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node-ii/)
* [104.二叉树的最大深度](https://leetcode.cn/problems/maximum-depth-of-binary-tree/)
* [111.二叉树的最小深度](https://leetcode.cn/problems/minimum-depth-of-binary-tree/)
**致敬叶师傅!**
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -5,6 +5,7 @@
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
# 104.二叉树的最大深度
[力扣题目链接](https://leetcode.cn/problems/maximum-depth-of-binary-tree/)
@@ -23,17 +24,19 @@
返回它的最大深度 3 。
# 思路
## 算法公开课
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[二叉树的高度和深度有啥区别?究竟用什么遍历顺序?很多录友搞不懂 | 104.二叉树的最大深度](https://www.bilibili.com/video/BV1Gd4y1V75u),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
看完本篇可以一起做了如下两道题目:
* 104.二叉树的最大深度
* 559.n叉树的最大深度
《代码随想录》算法视频公开课:[二叉树的高度和深度有啥区别?究竟用什么遍历顺序?很多录友搞不懂 | 104.二叉树的最大深度](https://www.bilibili.com/video/BV1Gd4y1V75u),相信结合视频在看本篇题解,更有助于大家对本题的理解。
* [104.二叉树的最大深度](https://leetcode.cn/problems/maximum-depth-of-binary-tree/)
* [559.n叉树的最大深度](https://leetcode.cn/problems/maximum-depth-of-n-ary-tree/)
## 递归法
### 递归法
本题可以使用前序(中左右),也可以使用后序遍历(左右中),使用前序求的就是深度,使用后序求的是高度。
@@ -164,7 +167,7 @@ public:
};
```
## 迭代法
### 迭代法
使用迭代法的话,使用层序遍历是最为合适的,因为最大的深度就是二叉树的层数,和层序遍历的方式极其吻合。
@@ -202,10 +205,11 @@ public:
};
```
那么我们可以顺便解决一下n叉树的最大深度问题
# 559.n叉树的最大深度
## 相关题目推荐
### 559.n叉树的最大深度
[力扣题目链接](https://leetcode.cn/problems/maximum-depth-of-n-ary-tree/)
@@ -219,11 +223,11 @@ public:
我们应返回其最大深度3。
思路
### 思路
依然可以提供递归法和迭代法,来解决这个问题,思路是和二叉树思路一样的,直接给出代码如下:
## 递归法
#### 递归法
c++代码:
@@ -240,7 +244,7 @@ public:
}
};
```
## 迭代法
#### 迭代法
依然是层序遍历,代码如下:
@@ -267,11 +271,11 @@ public:
};
```
# 其他语言版本
## 其他语言版本
## java
### Java:
### 104.二叉树的最大深度
104.二叉树的最大深度
```java
class solution {
@@ -344,7 +348,8 @@ class solution {
}
```
### 559.n叉树的最大深度
559.n叉树的最大深度
```java
class Solution {
/*递归法后序遍历求root节点的高度*/
@@ -391,9 +396,9 @@ class solution {
}
```
## python
### Python :
### 104.二叉树的最大深度
104.二叉树的最大深度
递归法:
```python
@@ -448,7 +453,7 @@ class Solution:
```
### 559.n叉树的最大深度
559.n叉树的最大深度
递归法:
```python
@@ -522,9 +527,10 @@ class Solution:
return max_depth
```
### Go:
104.二叉树的最大深度
## go
### 104.二叉树的最大深度
```go
/**
* definition for a binary tree node.
@@ -574,7 +580,7 @@ func maxdepth(root *treenode) int {
```
### 559. n叉树的最大深度
559. n叉树的最大深度
```go
func maxDepth(root *Node) int {
@@ -598,9 +604,9 @@ func maxDepth(root *Node) int {
}
```
## javascript
### Javascript :
### 104.二叉树的最大深度
104.二叉树的最大深度
```javascript
var maxdepth = function(root) {
@@ -649,7 +655,7 @@ var maxDepth = function(root) {
};
```
### 559.n叉树的最大深度
559.n叉树的最大深度
N叉树的最大深度 递归写法
```js
@@ -683,9 +689,9 @@ var maxDepth = function(root) {
};
```
## TypeScript
### TypeScript:
### 104.二叉树的最大深度
104.二叉树的最大深度
```typescript
// 后续遍历(自下而上)
@@ -728,7 +734,7 @@ function maxDepth(root: TreeNode | null): number {
};
```
### 559.n叉树的最大深度
559.n叉树的最大深度
```typescript
// 后续遍历(自下而上)
@@ -756,9 +762,9 @@ function maxDepth(root: TreeNode | null): number {
```
## C
### C:
### 104.二叉树的最大深度
104.二叉树的最大深度
二叉树最大深度递归
```c
@@ -814,9 +820,9 @@ int maxDepth(struct TreeNode* root){
}
```
## Swift
### Swift:
### 104.二叉树的最大深度
104.二叉树的最大深度
```swift
// 递归 - 后序
@@ -856,7 +862,7 @@ func maxDepth(_ root: TreeNode?) -> Int {
}
```
### 559.n叉树的最大深度
559.n叉树的最大深度
```swift
// 递归
@@ -893,9 +899,10 @@ func maxDepth1(_ root: Node?) -> Int {
}
```
## Scala
### Scala:
104.二叉树的最大深度
### 104.二叉树的最大深度
递归法:
```scala
object Solution {
@@ -934,7 +941,7 @@ object Solution {
}
```
### 559.n叉树的最大深度
559.n叉树的最大深度
递归法:
```scala
@@ -972,8 +979,8 @@ object Solution {
}
```
## rust
### 0104.二叉树的最大深度
### Rust:
0104.二叉树的最大深度
递归:
```rust

View File

@@ -29,9 +29,9 @@
![106. 从中序与后序遍历序列构造二叉树1](https://code-thinking-1253855093.file.myqcloud.com/pics/20210203154316774.png)
# 视频讲解
## 算法公开课
**《代码随想录》算法视频公开课:[坑很多!来看看你掉过几次坑 | LeetCode106.从中序与后序遍历序列构造二叉树](https://www.bilibili.com/video/BV1vW4y1i7dn),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[坑很多!来看看你掉过几次坑 | LeetCode106.从中序与后序遍历序列构造二叉树](https://www.bilibili.com/video/BV1vW4y1i7dn),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -158,8 +158,6 @@ root->right = traversal(rightInorder, rightPostorder);
完整代码如下:
### C++完整代码
```CPP
class Solution {
private:
@@ -281,8 +279,6 @@ public:
下面给出用下标索引写出的代码版本思路是一样的只不过不用重复定义vector了每次用下标索引来分割
### C++优化版本
```CPP
class Solution {
private:
@@ -400,8 +396,9 @@ public:
};
```
## 相关题目推荐
# 105.从前序与中序遍历序列构造二叉树
### 105.从前序与中序遍历序列构造二叉树
[力扣题目链接](https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/)
@@ -418,7 +415,7 @@ public:
![105. 从前序与中序遍历序列构造二叉树](https://code-thinking-1253855093.file.myqcloud.com/pics/20210203154626672.png)
## 思路
### 思路
本题和106是一样的道理。
@@ -547,7 +544,7 @@ public:
};
```
# 思考题
## 思考题
前序和中序可以唯一确定一棵二叉树。
@@ -569,7 +566,7 @@ tree2 的前序遍历是[1 2 3] 后序遍历是[3 2 1]。
所以前序和后序不能唯一确定一棵二叉树!
# 总结
## 总结
之前我们讲的二叉树题目都是各种遍历二叉树,这次开始构造二叉树了,思路其实比较简单,但是真正代码实现出来并不容易。
@@ -585,9 +582,9 @@ tree2 的前序遍历是[1 2 3] 后序遍历是[3 2 1]。
# 其他语言版本
## 其他语言版本
## Java
### Java
106.从中序与后序遍历序列构造二叉树
@@ -688,7 +685,7 @@ class Solution {
}
```
## Python
### Python
105.从前序与中序遍历序列构造二叉树
@@ -754,7 +751,7 @@ class Solution:
return root
```
## Go
### Go
106 从中序与后序遍历序列构造二叉树
@@ -833,9 +830,7 @@ func build(pre []int, in []int, root int, l, r int) *TreeNode {
```
## JavaScript
### JavaScript
```javascript
var buildTree = function(inorder, postorder) {
@@ -863,7 +858,7 @@ var buildTree = function(preorder, inorder) {
};
```
## TypeScript
### TypeScript
> 106.从中序与后序遍历序列构造二叉树
@@ -969,7 +964,7 @@ function buildTree(preorder: number[], inorder: number[]): TreeNode | null {
};
```
## C
### C
106 从中序与后序遍历序列构造二叉树
@@ -1047,7 +1042,7 @@ struct TreeNode* buildTree(int* preorder, int preorderSize, int* inorder, int in
}
```
## Swift
### Swift
105 从前序与中序遍历序列构造二叉树
@@ -1140,7 +1135,7 @@ class Solution_0106 {
}
```
## Scala
### Scala
106 从中序与后序遍历序列构造二叉树
@@ -1188,7 +1183,7 @@ object Solution {
}
```
## rust
### Rust
106 从中序与后序遍历序列构造二叉树
@@ -1238,3 +1233,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -20,11 +20,11 @@
![108.将有序数组转换为二叉搜索树](https://code-thinking-1253855093.file.myqcloud.com/pics/20201022164420763.png)
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[构造平衡二叉搜索树!| LeetCode108.将有序数组转换为二叉搜索树](https://www.bilibili.com/video/BV1uR4y1X7qL?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[构造平衡二叉搜索树!| LeetCode108.将有序数组转换为二叉搜索树](https://www.bilibili.com/video/BV1uR4y1X7qL?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
做这道题目之前大家可以了解一下这几道:
@@ -71,7 +71,7 @@
**这也是题目中强调答案不是唯一的原因。 理解这一点,这道题目算是理解到位了**
## 递归
### 递归
递归三部曲:
@@ -155,7 +155,7 @@ public:
**注意在调用traversal的时候传入的left和right为什么是0和nums.size() - 1因为定义的区间为左闭右闭**
## 迭代法
### 迭代法
迭代法可以通过三个队列来模拟,一个队列放遍历的节点,一个队列放左区间下标,一个队列放右区间下标。
@@ -203,7 +203,7 @@ public:
};
```
# 总结
## 总结
**在[二叉树:构造二叉树登场!](https://programmercarl.com/0106.从中序与后序遍历序列构造二叉树.html) 和 [二叉树:构造一棵最大的二叉树](https://programmercarl.com/0654.最大二叉树.html)之后,我们顺理成章的应该构造一下二叉搜索树了,一不小心还是一棵平衡二叉搜索树**
@@ -216,10 +216,10 @@ public:
最后依然给出迭代的方法,其实就是模拟取中间元素,然后不断分割去构造二叉树的过程。
# 其他语言版本
## 其他语言版本
## Java
### Java
递归: 左闭右开 [left,right)
```Java
@@ -315,7 +315,7 @@ class Solution {
}
```
## Python
### Python
递归法
```python
class Solution:
@@ -377,7 +377,7 @@ class Solution:
```
## Go
### Go
递归(隐含回溯)
@@ -396,7 +396,7 @@ func sortedArrayToBST(nums []int) *TreeNode {
}
```
## JavaScript
### JavaScript
递归
```javascript
@@ -453,7 +453,7 @@ var sortedArrayToBST = function(nums) {
return root;
};
```
## TypeScript
### TypeScript
```typescript
function sortedArrayToBST(nums: number[]): TreeNode | null {
@@ -469,7 +469,7 @@ function sortedArrayToBST(nums: number[]): TreeNode | null {
};
```
## C
### C
递归
```c
@@ -490,7 +490,7 @@ struct TreeNode* sortedArrayToBST(int* nums, int numsSize) {
}
```
## Scala
### Scala
递归:
@@ -511,7 +511,7 @@ object Solution {
}
```
## rust
### Rust
递归:
@@ -536,3 +536,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -33,8 +33,9 @@
返回 false 。
## 算法公开课
**《代码随想录》算法视频公开课:[后序遍历求高度,高度判断是否平衡 | LeetCode110.平衡二叉树](https://www.bilibili.com/video/BV1Ug411S7my),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[后序遍历求高度,高度判断是否平衡 | LeetCode110.平衡二叉树](https://www.bilibili.com/video/BV1Ug411S7my),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
## 题外话
@@ -357,7 +358,7 @@ public:
## 其他语言版本
### Java
### Java:
```Java
class Solution {
@@ -498,7 +499,7 @@ class Solution {
}
```
### Python
### Python:
递归法:
@@ -620,7 +621,7 @@ class Solution:
height_map[real_node] = 1 + max(left, right)
return True
```
### Go
### Go:
```Go
func isBalanced(root *TreeNode) bool {
@@ -652,7 +653,7 @@ func max(a, b int) int {
}
```
### JavaScript
### JavaScript:
递归法:
@@ -723,7 +724,7 @@ var isBalanced = function (root) {
};
```
### TypeScript
### TypeScript:
```typescript
// 递归法
@@ -741,7 +742,7 @@ function isBalanced(root: TreeNode | null): boolean {
};
```
### C
### C:
递归法:
@@ -876,7 +877,7 @@ func getHeight(_ root: TreeNode?) -> Int {
}
```
### rust
### Rust:
递归
@@ -912,3 +913,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -26,9 +26,11 @@
返回它的最小深度 2.
# 思路
## 算法公开课
《代码随想录》算法视频公开课:[看起来好像做过,一写就错! | LeetCode111.二叉树的最小深度](https://www.bilibili.com/video/BV1QD4y1B7e2),相信结合视频看本篇题解,更有助于大家对本题的理解。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[看起来好像做过,一写就错! | LeetCode111.二叉树的最小深度](https://www.bilibili.com/video/BV1QD4y1B7e2),相信结合视频看本篇题解,更有助于大家对本题的理解**
## 思路
看完了这篇[104.二叉树的最大深度](https://programmercarl.com/0104.二叉树的最大深度.html),再来看看如何求最小深度。
@@ -52,7 +54,7 @@
什么是叶子节点,左右孩子都为空的节点才是叶子节点!
## 递归法
### 递归法
来来来,一起递归三部曲:
@@ -199,7 +201,7 @@ public:
};
```
## 迭代法
### 迭代法
相对于[104.二叉树的最大深度](https://programmercarl.com/0104.二叉树的最大深度.html),本题还可以使用层序遍历的方式来解决,思路是一样的。
@@ -237,10 +239,10 @@ public:
```
# 其他语言版本
## 其他语言版本
## Java
### Java:
```Java
class Solution {
@@ -300,7 +302,7 @@ class Solution {
}
```
## Python
### Python :
递归法(版本一)
@@ -400,9 +402,7 @@ class Solution:
return depth
```
## Go
### Go:
```go
/**
@@ -463,7 +463,7 @@ func minDepth(root *TreeNode) int {
```
## JavaScript
### JavaScript:
递归法:
@@ -509,7 +509,7 @@ var minDepth = function(root) {
};
```
## TypeScript
### TypeScript:
> 递归法
@@ -547,7 +547,7 @@ function minDepth(root: TreeNode | null): number {
};
```
## Swift
### Swift:
> 递归
```Swift
@@ -594,7 +594,7 @@ func minDepth(_ root: TreeNode?) -> Int {
```
## Scala
### Scala:
递归法:
```scala
@@ -633,7 +633,8 @@ object Solution {
}
```
rust:
### Rust:
```rust
impl Solution {
// 递归

View File

@@ -21,9 +21,9 @@
返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。
## 视频讲解
## 算法公开课
**《代码随想录》算法视频公开课:[拿不准的遍历顺序,搞不清的回溯过程,我太难了! | LeetCode112. 路径总和](https://www.bilibili.com/video/BV19t4y1L7CR),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[拿不准的遍历顺序,搞不清的回溯过程,我太难了! | LeetCode112. 路径总和](https://www.bilibili.com/video/BV19t4y1L7CR),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -32,8 +32,8 @@
那么接下来我通过详细讲解如下两道题,来回答这个问题:
* 112.路径总和
* 113.路径总和ii
* [112.路径总和](https://leetcode.cn/problems/path-sum/)
* [113.路径总和ii](https://leetcode.cn/problems/path-sum-ii/)
这道题我们要遍历从根节点到叶子节点的路径看看总和是不是目标和。
@@ -218,7 +218,9 @@ public:
如果大家完全理解了本题的递归方法之后就可以顺便把leetcode上113. 路径总和ii做了。
# 113. 路径总和ii
## 相关题目推荐
### 113. 路径总和ii
[力扣题目链接](https://leetcode.cn/problems/path-sum-ii/)
@@ -232,7 +234,7 @@ public:
![113.路径总和ii1.png](https://code-thinking-1253855093.file.myqcloud.com/pics/20210203160854654.png)
## 思路
### 思路
113.路径总和ii要遍历整个树找到所有路径**所以递归函数不要返回值!**
@@ -289,7 +291,7 @@ public:
至于113. 路径总和ii 的迭代法我并没有写,用迭代方式记录所有路径比较麻烦,也没有必要,如果大家感兴趣的话,可以再深入研究研究。
## 总结
### 总结
本篇通过leetcode上112. 路径总和 和 113. 路径总和ii 详细的讲解了 递归函数什么时候需要返回值,什么不需要返回值。
@@ -300,11 +302,11 @@ public:
# 其他语言版本
## 其他语言版本
## java
### Java
### 0112.路径总和
0112.路径总和
```java
class solution {
@@ -422,7 +424,7 @@ class solution {
}
```
### 0113.路径总和-ii
0113.路径总和-ii
```java
class solution {
@@ -529,9 +531,9 @@ class Solution {
}
```
## python
### Python
### 0112.路径总和
0112.路径总和
(版本一) 递归
```python
@@ -618,7 +620,7 @@ class Solution:
### 0113.路径总和-ii
0113.路径总和-ii
(版本一) 递归
```python
@@ -719,9 +721,9 @@ class Solution:
```
## go
### Go
### 112. 路径总和
112. 路径总和
```go
//递归法
@@ -746,7 +748,7 @@ func hasPathSum(root *TreeNode, targetSum int) bool {
}
```
### 113. 路径总和 II
113. 路径总和 II
```go
/**
@@ -786,9 +788,9 @@ func traverse(node *TreeNode, result *[][]int, currPath *[]int, targetSum int) {
}
```
## javascript
### Javascript
### 0112.路径总和
0112.路径总和
**递归**
@@ -852,7 +854,7 @@ let hasPathSum = function(root, targetSum) {
};
```
### 0113.路径总和-ii
0113.路径总和-ii
**递归**
@@ -950,9 +952,9 @@ let pathSum = function(root, targetSum) {
};
```
## TypeScript
### TypeScript
### 0112.路径总和
0112.路径总和
**递归法:**
@@ -1034,7 +1036,7 @@ function hasPathSum(root: TreeNode | null, targetSum: number): boolean {
};
```
### 0112.路径总和 ii
0112.路径总和 ii
**递归法:**
@@ -1070,9 +1072,9 @@ function pathSum(root: TreeNode | null, targetSum: number): number[][] {
};
```
## Swift
### Swift
### 0112.路径总和
0112.路径总和
**递归**
@@ -1141,7 +1143,7 @@ func hasPathSum(_ root: TreeNode?, _ targetSum: Int) -> Bool {
}
```
### 0113.路径总和 II
0113.路径总和 II
**递归**
@@ -1192,10 +1194,11 @@ func traversal(_ cur: TreeNode?, count: Int) {
}
```
## C
### C
> 0112.路径总和
> 递归法:
0112.路径总和
递归法:
```c
bool hasPathSum(struct TreeNode* root, int targetSum){
@@ -1252,7 +1255,7 @@ bool hasPathSum(struct TreeNode* root, int targetSum){
}
```
> 0113.路径总和 II
0113.路径总和 II
```c
int** ret;
@@ -1317,9 +1320,9 @@ int** pathSum(struct TreeNode* root, int targetSum, int* returnSize, int** retur
}
```
## Scala
### Scala
### 0112.路径总和
0112.路径总和
**递归:**
@@ -1369,7 +1372,7 @@ object Solution {
}
```
### 0113.路径总和 II
0113.路径总和 II
**递归:**
@@ -1405,9 +1408,9 @@ object Solution {
}
```
## rust
### Rust
### 112.路径总和.md
0112.路径总和
递归:
@@ -1461,7 +1464,7 @@ impl Solution {
}
```
### 113.路径总和-ii
0113.路径总和-ii
```rust
impl Solution {

View File

@@ -413,7 +413,52 @@ function maxProfit(prices: number[]): number {
};
```
Rust
> 版本一
```rust
impl Solution {
pub fn max_profit(prices: Vec<i32>) -> i32 {
/*
* 定义 5 种状态:
* 0: 没有操作, 1: 第一次买入, 2: 第一次卖出, 3: 第二次买入, 4: 第二次卖出
*/
let mut dp = vec![vec![0; 5]; prices.len()];
dp[0][1] = -prices[0];
dp[0][3] = -prices[0];
for (i, &p) in prices.iter().enumerate().skip(1) {
// 不操作
// dp[i][0] = dp[i - 1][0];
dp[i][1] = dp[i - 1][1].max(-p);
dp[i][2] = dp[i - 1][2].max(dp[i - 1][1] + p);
dp[i][3] = dp[i - 1][3].max(dp[i - 1][2] - p);
dp[i][4] = dp[i - 1][4].max(dp[i - 1][3] + p);
}
dp[prices.len() - 1][4]
}
}
```
> 版本二(绕)
```rust
impl Solution {
pub fn max_profit(prices: Vec<i32>) -> i32 {
let (mut one_buy, mut one_sale, mut two_buy, mut two_sale) = (-prices[0], 0, -prices[0], 0);
for p in prices {
one_buy = one_buy.max(-p);
one_sale = one_sale.max(p + one_buy);
two_buy = two_buy.max(one_sale - p);
two_sale = two_sale.max(two_buy + p);
}
two_sale
}
}
```
<p align="center">

View File

@@ -188,6 +188,54 @@ class Solution {
}
}
```
```Java
//BFS使用helper function
class Solution {
int[][] dir ={{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
public void solve(char[][] board) {
for(int i = 0; i < board.length; i++){
if(board[i][0] == 'O') bfs(board, i, 0);
if(board[i][board[0].length - 1] == 'O') bfs(board, i, board[0].length - 1);
}
for(int j = 1 ; j < board[0].length - 1; j++){
if(board[0][j] == 'O') bfs(board, 0, j);
if(board[board.length - 1][j] == 'O') bfs(board, board.length - 1, j);
}
for(int i = 0; i < board.length; i++){
for(int j = 0; j < board[0].length; j++){
if(board[i][j] == 'O') board[i][j] = 'X';
if(board[i][j] == 'A') board[i][j] = 'O';
}
}
}
private void bfs(char[][] board, int x, int y){
Queue<Integer> que = new LinkedList<>();
board[x][y] = 'A';
que.offer(x);
que.offer(y);
while(!que.isEmpty()){
int currX = que.poll();
int currY = que.poll();
for(int i = 0; i < 4; i++){
int nextX = currX + dir[i][0];
int nextY = currY + dir[i][1];
if(nextX < 0 || nextY < 0 || nextX >= board.length || nextY >= board[0].length)
continue;
if(board[nextX][nextY] == 'X'|| board[nextX][nextY] == 'A')
continue;
bfs(board, nextX, nextY);
}
}
}
}
```
```Java
// 深度优先遍历
// 使用 visited 数组进行标记
@@ -296,6 +344,47 @@ class Solution {
}
}
```
```java
//DFS(有終止條件)
class Solution {
int[][] dir ={{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
public void solve(char[][] board) {
for(int i = 0; i < board.length; i++){
if(board[i][0] == 'O') dfs(board, i, 0);
if(board[i][board[0].length - 1] == 'O') dfs(board, i, board[0].length - 1);
}
for(int j = 1 ; j < board[0].length - 1; j++){
if(board[0][j] == 'O') dfs(board, 0, j);
if(board[board.length - 1][j] == 'O') dfs(board, board.length - 1, j);
}
for(int i = 0; i < board.length; i++){
for(int j = 0; j < board[0].length; j++){
if(board[i][j] == 'O') board[i][j] = 'X';
if(board[i][j] == 'A') board[i][j] = 'O';
}
}
}
private void dfs(char[][] board, int x, int y){
if(board[x][y] == 'X'|| board[x][y] == 'A')
return;
board[x][y] = 'A';
for(int i = 0; i < 4; i++){
int nextX = x + dir[i][0];
int nextY = y + dir[i][1];
if(nextX < 0 || nextY < 0 || nextX >= board.length || nextY >= board[0].length)
continue;
// if(board[nextX][nextY] == 'X'|| board[nextX][nextY] == 'A')
// continue;
dfs(board, nextX, nextY);
}
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">

View File

@@ -23,12 +23,12 @@
["a","a","b"]
]
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[131.分割回文串](https://www.bilibili.com/video/BV1c54y1e7k6),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[131.分割回文串](https://www.bilibili.com/video/BV1c54y1e7k6),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
本题这涉及到两个关键问题:
@@ -58,7 +58,7 @@
此时可以发现,切割问题的回溯搜索的过程和组合问题的回溯搜索的过程是差不多的。
## 回溯三部曲
### 回溯三部曲
* 递归函数参数
@@ -124,7 +124,7 @@ for (int i = startIndex; i < s.size(); i++) {
**注意切割过的位置不能重复切割所以backtracking(s, i + 1); 传入下一层的起始位置为i + 1**
## 判断回文子串
### 判断回文子串
最后我们看一下回文子串要如何判断了,判断一个字符串是否是回文。
@@ -147,8 +147,6 @@ for (int i = startIndex; i < s.size(); i++) {
此时关键代码已经讲解完毕,整体代码如下(详细注释了)
## C++整体代码
根据Carl给出的回溯算法模板
```CPP
@@ -212,7 +210,7 @@ public:
* 时间复杂度: O(n * 2^n)
* 空间复杂度: O(n^2)
# 优化
## 优化
上面的代码还存在一定的优化空间, 在于如何更高效的计算一个子字符串是否是回文字串。上述代码```isPalindrome```函数运用双指针的方法来判定对于一个字符串```s```, 给定起始下标和终止下标, 截取出的子字符串是否是回文字串。但是其中有一定的重复计算存在:
@@ -272,7 +270,7 @@ public:
```
# 总结
## 总结
这道题目在leetcode上是中等但可以说是hard的题目了但是代码其实就是按照模板的样子来的。
@@ -306,10 +304,10 @@ public:
# 其他语言版本
## 其他语言版本
## Java
### Java
```Java
class Solution {
List<List<String>> lists = new ArrayList<>();
@@ -351,7 +349,7 @@ class Solution {
}
```
## Python
### Python
回溯 基本版
```python
class Solution:
@@ -473,7 +471,7 @@ class Solution:
return all(s[i] == s[len(s) - 1 - i] for i in range(len(s) // 2))
```
## Go
### Go
```go
var (
path []string // 放已经回文的子串
@@ -512,7 +510,7 @@ func isPalindrome(s string) bool {
}
```
## javaScript
### JavaScript
```js
/**
@@ -545,7 +543,7 @@ var partition = function(s) {
};
```
## TypeScript
### TypeScript
```typescript
function partition(s: string): string[][] {
@@ -582,7 +580,7 @@ function partition(s: string): string[][] {
};
```
## C
### C
```c
char** path;
@@ -679,7 +677,7 @@ char*** partition(char* s, int* returnSize, int** returnColumnSizes){
}
```
## Swift
### Swift
```swift
func partition(_ s: String) -> [[String]] {
@@ -719,7 +717,7 @@ func partition(_ s: String) -> [[String]] {
}
```
## Rust
### Rust
**回溯+函数判断回文串**
```Rust
@@ -808,7 +806,7 @@ impl Solution {
```
## Scala
### Scala
```scala
object Solution {
@@ -855,3 +853,4 @@ object Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -70,7 +70,7 @@ public:
## 其他语言版本
### Java
### Java:
```java
public class Solution {
@@ -90,7 +90,7 @@ public class Solution {
}
```
### Python
### Python:
```python
class Solution:
@@ -105,7 +105,7 @@ class Solution:
return False
```
### Go
### Go:
```go
func hasCycle(head *ListNode) bool {
@@ -125,7 +125,7 @@ func hasCycle(head *ListNode) bool {
}
```
### JavaScript
### JavaScript:
```js
var hasCycle = function(head) {
@@ -141,7 +141,7 @@ var hasCycle = function(head) {
};
```
### TypeScript
### TypeScript:
```typescript
function hasCycle(head: ListNode | null): boolean {
@@ -163,3 +163,4 @@ function hasCycle(head: ListNode | null): boolean {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -11,7 +11,7 @@
> 找到有没有环已经很不容易了,还要让我找到环的入口?
## 142.环形链表II
# 142.环形链表II
[力扣题目链接](https://leetcode.cn/problems/linked-list-cycle-ii/)
@@ -24,9 +24,11 @@
![循环链表](https://code-thinking-1253855093.file.myqcloud.com/pics/20200816110112704.png)
## 思路
## 算法公开课
《代码随想录》算法公开课:[把环形链表讲清楚!| LeetCode:142.环形链表II](https://www.bilibili.com/video/BV1if4y1d7ob),相信结合视频在看本篇题解,更有助于大家对链表的理解。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[把环形链表讲清楚!| LeetCode:142.环形链表II](https://www.bilibili.com/video/BV1if4y1d7ob),相信结合视频在看本篇题解,更有助于大家对链表的理解。**
## 思路
这道题目,不仅考察对链表的操作,而且还需要一些数学运算。
@@ -148,7 +150,7 @@ public:
* 时间复杂度: O(n)快慢指针相遇前指针走的次数小于链表长度快慢指针相遇后两个index指针走的次数也小于链表长度总体为走的次数小于 2n
* 空间复杂度: O(1)
## 补充
### 补充
在推理过程中,大家可能有一个疑问就是:**为什么第一次在环中相遇slow的 步数 是 x+y 而不是 x + 若干环的长度 + y 呢?**
@@ -190,8 +192,7 @@ public:
## 其他语言版本
Java
### Java
```java
public class Solution {
@@ -217,8 +218,7 @@ public class Solution {
}
```
Python
### Python
```python
版本一快慢指针法
@@ -270,7 +270,7 @@ class Solution:
return None
```
Go
### Go
```go
func detectCycle(head *ListNode) *ListNode {
@@ -290,7 +290,7 @@ func detectCycle(head *ListNode) *ListNode {
}
```
javaScript
### JavaScript
```js
// 两种循环实现方式
@@ -334,7 +334,7 @@ var detectCycle = function(head) {
};
```
TypeScript
### TypeScript
```typescript
function detectCycle(head: ListNode | null): ListNode | null {
@@ -356,7 +356,7 @@ function detectCycle(head: ListNode | null): ListNode | null {
};
```
Swift:
### Swift:
```swift
class Solution {
@@ -391,7 +391,7 @@ extension ListNode: Equatable {
}
```
C
### C
```c
ListNode *detectCycle(ListNode *head) {
@@ -410,7 +410,7 @@ ListNode *detectCycle(ListNode *head) {
}
```
Scala:
### Scala:
```scala
object Solution {
@@ -437,7 +437,7 @@ object Solution {
}
```
C#:
### C#:
```CSharp
public class Solution
{

View File

@@ -5,8 +5,6 @@
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
> 这不仅仅是一道好题,也展现出计算机的思考方式
# 150. 逆波兰表达式求值
@@ -63,9 +61,13 @@
* 适合用栈操作运算:遇到数字则入栈;遇到运算符则取出栈顶两个数字进行计算,并将结果压入栈中。
# 思路
## 算法公开课
《代码随想录》算法视频公开课:[栈的最后表演! | LeetCode150. 逆波兰表达式求值](https://www.bilibili.com/video/BV1kd4y1o7on),相信结合视频再看本篇题解,更有助于大家对本题的理解。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[栈的最后表演! | LeetCode150. 逆波兰表达式求值](https://www.bilibili.com/video/BV1kd4y1o7on),相信结合视频再看本篇题解,更有助于大家对本题的理解**
## 思路
### 正题
在上一篇文章中[1047.删除字符串中的所有相邻重复项](https://programmercarl.com/1047.删除字符串中的所有相邻重复项.html)提到了 递归就是用栈来实现的。
@@ -117,7 +119,7 @@ public:
* 空间复杂度: O(n)
## 题外话
### 题外话
我们习惯看到的表达式都是中缀表达式,因为符合我们的习惯,但是中缀表达式对于计算机来说就不是很友好了。
@@ -134,11 +136,9 @@ public:
> During the 1970s and 1980s, Hewlett-Packard used RPN in all of their desktop and hand-held calculators, and continued to use it in some models into the 2020s.
## 其他语言版本
java:
### Java:
```Java
class Solution {
@@ -164,7 +164,7 @@ class Solution {
}
```
python3
### Python3
```python
from operator import add, sub, mul
@@ -201,7 +201,8 @@ class Solution:
```
Go:
### Go:
```Go
func evalRPN(tokens []string) int {
stack := []int{}
@@ -228,7 +229,7 @@ func evalRPN(tokens []string) int {
}
```
javaScript:
### JavaScript:
```js
var evalRPN = function (tokens) {
@@ -259,7 +260,7 @@ var evalRPN = function (tokens) {
};
```
TypeScript
### TypeScript
普通版:
@@ -324,7 +325,8 @@ function evalRPN(tokens: string[]): number {
};
```
Swift
### Swift
```Swift
func evalRPN(_ tokens: [String]) -> Int {
var stack = [Int]()
@@ -357,7 +359,8 @@ func evalRPN(_ tokens: [String]) -> Int {
}
```
C#:
### C#:
```csharp
public int EvalRPN(string[] tokens) {
int num;
@@ -391,8 +394,8 @@ public int EvalRPN(string[] tokens) {
}
```
### PHP
PHP
```php
class Solution {
function evalRPN($tokens) {
@@ -417,7 +420,8 @@ class Solution {
}
```
Scala:
### Scala:
```scala
object Solution {
import scala.collection.mutable
@@ -447,7 +451,7 @@ object Solution {
}
```
rust:
### Rust:
```rust
impl Solution {

View File

@@ -28,10 +28,11 @@
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
## 算法公开课
# 思路
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[字符串复杂操作拿捏了! | LeetCode:151.翻转字符串里的单词](https://www.bilibili.com/video/BV1uT41177fX),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
针对本题,我录制了视频讲解:[字符串复杂操作拿捏了! | LeetCode:151.翻转字符串里的单词](https://www.bilibili.com/video/BV1uT41177fX),结合本题解一起看,事半功倍!
## 思路
**这道题目可以说是综合考察了字符串的多种操作。**
@@ -204,8 +205,7 @@ public:
## 其他语言版本
Java
### Java
```Java
class Solution {
@@ -433,9 +433,10 @@ class Solution {
}
```
python:
### python:
(版本一)先删除空白,然后整个反转,最后单词反转。
**因为字符串是不可变类型所以反转单词的时候需要将其转换成列表然后通过join函数再将其转换成列表所以空间复杂度不是O(1)**
```Python
class Solution:
def reverseWords(self, s: str) -> str:
@@ -467,7 +468,7 @@ class Solution:
return " ".join(words)
```
Go
### Go
版本一:
@@ -571,7 +572,8 @@ func reverse(b *[]byte, left, right int) {
javaScript:
### JavaScript:
```js
/**
* @param {string} s
@@ -630,7 +632,7 @@ function reverse(strArr, start, end) {
}
```
TypeScript
### TypeScript
```typescript
function reverseWords(s: string): string {
@@ -689,7 +691,7 @@ function reverseWords(s: string): string {
};
```
Swift:
### Swift:
```swift
func reverseWords(_ s: String) -> String {
@@ -766,7 +768,7 @@ func reverseWord(_ s: inout [Character]) {
}
```
Scala:
### Scala:
```scala
object Solution {
@@ -824,8 +826,8 @@ object Solution {
}
```
### PHP:
PHP:
```php
function reverseWords($s) {
$this->removeExtraSpaces($s);
@@ -872,7 +874,7 @@ function reverseString(&$s, $start, $end) {
return ;
}
```
Rust:
### Rust:
```Rust
// 根据C++版本二思路进行实现
@@ -924,7 +926,7 @@ pub fn remove_extra_spaces(s: &mut Vec<char>) {
}
}
```
C:
### C:
```C
// 翻转字符串中指定范围的字符
@@ -972,3 +974,4 @@ char * reverseWords(char * s){
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -474,6 +474,55 @@ function maxProfit(k: number, prices: number[]): number {
};
```
Rust
```rust
impl Solution {
pub fn max_profit(k: i32, prices: Vec<i32>) -> i32 {
let mut dp = vec![vec![0; 2 * k as usize + 1]; prices.len()];
for v in dp[0].iter_mut().skip(1).step_by(2) {
*v = -prices[0];
}
for (i, &p) in prices.iter().enumerate().skip(1) {
for j in (0..2 * k as usize - 1).step_by(2) {
dp[i][j + 1] = dp[i - 1][j + 1].max(dp[i - 1][j] - p);
dp[i][j + 2] = dp[i - 1][j + 2].max(dp[i - 1][j + 1] + p);
}
}
dp[prices.len() - 1][2 * k as usize]
}
}
```
空间优化:
```rust
impl Solution {
pub fn max_profit(k: i32, prices: Vec<i32>) -> i32 {
let mut dp = vec![0; 2 * k as usize + 1];
for v in dp.iter_mut().skip(1).step_by(2) {
*v = -prices[0];
}
for p in prices {
for i in 1..=2 * k as usize {
if i % 2 == 1 {
// 买入
dp[i] = dp[i].max(dp[i - 1] - p);
continue;
}
// 卖出
dp[i] = dp[i].max(dp[i - 1] + p);
}
}
dp[2 * k as usize]
}
}
```
<p align="center">

View File

@@ -196,7 +196,51 @@ class Solution {
}
}
```
## 其他语言版本
### Python
BFS solution
```python
class Solution:
def __init__(self):
self.dirs = [[0, 1], [1, 0], [-1, 0], [0, -1]]
def numIslands(self, grid: List[List[str]]) -> int:
m = len(grid)
n = len(grid[0])
visited = [[False]*n for _ in range(m)]
res = 0
for i in range(m):
for j in range(n):
if visited[i][j] == False and grid[i][j] == '1':
res += 1
self.bfs(grid, i, j, visited) # Call bfs within this condition
return res
def bfs(self, grid, i, j, visited):
q = deque()
q.append((i,j))
visited[i][j] = True
while q:
x, y = q.popleft()
for k in range(4):
next_i = x + self.dirs[k][0]
next_j = y + self.dirs[k][1]
if next_i < 0 or next_i >= len(grid):
continue
if next_j < 0 or next_j >= len(grid[0]):
continue
if visited[next_i][next_j]:
continue
if grid[next_i][next_j] == '0':
continue
q.append((next_i, next_j))
visited[next_i][next_j] = True
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>
```

View File

@@ -176,6 +176,48 @@ public void dfs(char[][] grid, int i, int j){
dfs(grid,i,j + 1);
dfs(grid,i,j - 1);
}
```
```java
//graph - dfs (和卡哥的代碼邏輯一致)
class Solution {
boolean[][] visited;
int dir[][] = {
{0, 1}, //right
{1, 0}, //down
{-1, 0}, //up
{0, -1} //left
};
public int numIslands(char[][] grid) {
int count = 0;
visited = new boolean[grid.length][grid[0].length];
for(int i = 0; i < grid.length; i++){
for(int j = 0; j < grid[0].length; j++){
if(visited[i][j] == false && grid[i][j] == '1'){
count++;
dfs(grid, i, j);
}
}
}
return count;
}
private void dfs(char[][]grid, int x, int y){
if(visited[x][y] == true || grid[x][y] == '0')
return;
visited[x][y] = true;
for(int i = 0; i < 4; i++){
int nextX = x + dir[i][0];
int nextY = y + dir[i][1];
if(nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length)
continue;
dfs(grid, nextX, nextY);
}
}
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>

View File

@@ -28,7 +28,7 @@
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1
# 思路
## 思路
这道题目看上去貌似一道数学问题,其实并不是!
@@ -80,10 +80,10 @@ public:
# 其他语言版本
## 其他语言版本
### Java
Java
```java
class Solution {
public boolean isHappy(int n) {
@@ -107,8 +107,9 @@ class Solution {
}
```
Python
### Python
(版本一)使用集合
```python
class Solution:
def isHappy(self, n: int) -> bool:
@@ -131,7 +132,7 @@ class Solution:
n, r = divmod(n, 10)
new_num += r ** 2
return new_num
```
```
(版本二)使用集合
```python
class Solution:
@@ -146,7 +147,7 @@ class Solution:
if new_num==1: return True
else: n = new_num
return False
```
```
(版本三)使用数组
```python
class Solution:
@@ -161,7 +162,7 @@ class Solution:
if new_num==1: return True
else: n = new_num
return False
```
```
(版本四)使用快慢指针
```python
class Solution:
@@ -180,7 +181,7 @@ class Solution:
n, r = divmod(n, 10)
new_num += r ** 2
return new_num
```
```
(版本五)使用集合+精简
```python
class Solution:
@@ -192,7 +193,7 @@ class Solution:
return False
seen.add(n)
return True
```
```
(版本六)使用数组+精简
```python
class Solution:
@@ -204,8 +205,9 @@ class Solution:
return False
seen.append(n)
return True
```
Go
```
### Go
```go
func isHappy(n int) bool {
m := make(map[int]bool)
@@ -225,7 +227,7 @@ func getSum(n int) int {
}
```
javaScript:
### JavaScript:
```js
var isHappy = function (n) {
@@ -303,7 +305,7 @@ var isHappy = function(n) {
};
```
TypeScript:
### TypeScript:
```typescript
function isHappy(n: number): boolean {
@@ -322,7 +324,7 @@ function isHappy(n: number): boolean {
};
```
Swift
### Swift
```swift
// number 每个位置上的数字的平方和
@@ -355,7 +357,8 @@ func isHappy(_ n: Int) -> Bool {
}
```
PHP:
### PHP:
```php
class Solution {
/**
@@ -386,7 +389,8 @@ class Solution {
}
```
Rust:
### Rust:
```Rust
use std::collections::HashSet;
impl Solution {
@@ -416,7 +420,8 @@ impl Solution {
}
```
C:
### C:
```C
typedef struct HashNodeTag {
int key; /* num */
@@ -473,8 +478,8 @@ object Solution {
}
```
### C#
C#
```csharp
public class Solution {
private int getSum(int n) {
@@ -500,3 +505,4 @@ public class Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -27,10 +27,12 @@
输入head = [7,7,7,7], val = 7
输出:[]
## 算法公开课
# 思路
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[链表基础操作| LeetCode203.移除链表元素](https://www.bilibili.com/video/BV18B4y1s7R9),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
为了方便大家理解,我特意录制了视频:[链表基础操作| LeetCode203.移除链表元素](https://www.bilibili.com/video/BV18B4y1s7R9),结合视频在看本题解,事半功倍。
## 思路
这里以链表 1 4 2 4 来举例移除元素4。
@@ -86,9 +88,6 @@
最后呢在题目中return 头结点的时候,别忘了 `return dummyNode->next;` 这才是新的头结点
# C++代码
**直接使用原来的链表来进行移除节点操作:**
```CPP
@@ -155,7 +154,7 @@ public:
## 其他语言版本
C:
### C:
用原来的链表操作:
```c
@@ -223,7 +222,7 @@ struct ListNode* removeElements(struct ListNode* head, int val){
}
```
Java
### Java
```java
/**
@@ -304,7 +303,7 @@ public ListNode removeElements(ListNode head, int val) {
}
```
Python
### Python
```python
版本一虚拟头节点法
@@ -330,7 +329,7 @@ class Solution:
```
Go
### Go
```go
/**
@@ -355,7 +354,7 @@ func removeElements(head *ListNode, val int) *ListNode {
}
```
javaScript:
### JavaScript:
```js
/**
@@ -377,7 +376,7 @@ var removeElements = function(head, val) {
};
```
TypeScript:
### TypeScript:
版本一(在原链表上直接删除):
@@ -433,7 +432,7 @@ function removeElements(head: ListNode | null, val: number): ListNode | null {
};
```
Swift
### Swift
```swift
/**
@@ -461,7 +460,7 @@ func removeElements(_ head: ListNode?, _ val: Int) -> ListNode? {
}
```
PHP:
### PHP:
```php
/**
@@ -489,7 +488,7 @@ func removeElements(head *ListNode, val int) *ListNode {
}
```
RUST:
### Rust:
```rust
// Definition for singly-linked list.
@@ -527,7 +526,7 @@ impl Solution {
}
```
Scala:
### Scala:
```scala
/**
@@ -560,7 +559,7 @@ object Solution {
}
```
Kotlin:
### Kotlin:
```kotlin
/**
@@ -596,7 +595,8 @@ class Solution {
}
```
C#
### C#
```CSharp
/**
* Definition for singly-linked list.
@@ -635,3 +635,4 @@ public class Solution
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -17,9 +17,12 @@
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
# 思路
## 算法公开课
本题我录制了B站视频[帮你拿下反转链表 | LeetCode206.反转链表](https://www.bilibili.com/video/BV1nB4y1i7eL),相信结合视频看本篇题解,更有助于大家对链表的理解。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[帮你拿下反转链表 | LeetCode206.反转链表](https://www.bilibili.com/video/BV1nB4y1i7eL),相信结合视频看本篇题解,更有助于大家对本题的理解**
## 思路
如果再定义一个新的链表,实现链表元素的反转,其实这是对内存空间的浪费。
@@ -46,9 +49,7 @@
最后cur 指针已经指向了null循环结束链表也反转完毕了。 此时我们return pre指针就可以了pre指针就指向了新的头结点。
# C++代码
## 双指针法
### 双指针法
```CPP
class Solution {
public:
@@ -71,7 +72,7 @@ public:
* 时间复杂度: O(n)
* 空间复杂度: O(1)
## 递归法
### 递归法
递归法相对抽象一些但是其实和双指针法是一样的逻辑同样是当cur为空的时候循环结束不断将cur指向pre的过程。
@@ -132,8 +133,8 @@ public:
## 其他语言版本
### Java
Java
```java
// 双指针
class Solution {
@@ -193,7 +194,8 @@ class Solution {
}
```
Python
### Python
```python
版本一双指针法
# Definition for singly-linked list.
@@ -214,8 +216,6 @@ class Solution:
return pre
```
Python递归法
```python
版本二递归法
# Definition for singly-linked list.
@@ -237,7 +237,7 @@ class Solution:
Go
### Go
```go
//双指针
@@ -268,7 +268,7 @@ func help(pre, head *ListNode)*ListNode{
}
```
javaScript:
### JavaScript:
```js
/**
@@ -323,7 +323,7 @@ var reverseList = function(head) {
};
```
TypeScript:
### TypeScript:
```typescript
// 双指针法
@@ -371,7 +371,7 @@ function reverseList(head: ListNode | null): ListNode | null {
};
```
Ruby:
### Ruby:
```ruby
# 双指针
@@ -416,7 +416,8 @@ def reverse(pre, cur)
end
```
Kotlin:
### Kotlin:
```Kotlin
fun reverseList(head: ListNode?): ListNode? {
var pre: ListNode? = null
@@ -466,7 +467,8 @@ class Solution {
}
```
Swift
### Swift
```swift
/// 双指针法 (迭代)
/// - Parameter head: 头结点
@@ -503,8 +505,9 @@ func reverse(pre: ListNode?, cur: ListNode?) -> ListNode? {
}
```
C:
### C:
双指针法:
```c
struct ListNode* reverseList(struct ListNode* head){
//保存cur的下一个结点
@@ -544,7 +547,8 @@ struct ListNode* reverseList(struct ListNode* head){
PHP:
### PHP:
```php
// 双指针法:
function reverseList($head) {
@@ -560,8 +564,9 @@ function reverseList($head) {
}
```
Scala:
### Scala:
双指针法:
```scala
object Solution {
def reverseList(head: ListNode): ListNode = {
@@ -596,7 +601,7 @@ object Solution {
}
```
Rust:
### Rust:
双指针法:
```rust
@@ -635,7 +640,7 @@ impl Solution {
}
}
```
C#:
### C#:
三指针法, 感觉会更直观:
```cs
@@ -672,11 +677,11 @@ public class LinkNumbers
}
```
## 其他解法
### 使用虚拟头结点解决链表反转
## 使用虚拟头结点解决链表翻转
> 使用虚拟头结点,通过头插法实现链表的翻转(不需要栈)
> 使用虚拟头结点,通过头插法实现链表的反转(不需要栈)
```java
// 迭代方法:增加虚头结点,使用头插法实现链表翻转
@@ -699,7 +704,7 @@ public static ListNode reverseList1(ListNode head) {
## 使用栈解决反转链表的问题
### 使用栈解决反转链表的问题
* 首先将所有的结点入栈
* 然后创建一个虚拟虚拟头结点让cur指向虚拟头结点。然后开始循环出栈每出来一个元素就把它加入到以虚拟头结点为头结点的链表当中最后返回即可。
@@ -738,4 +743,3 @@ public ListNode reverseList(ListNode head) {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -13,9 +13,9 @@
示例:
输入s = 7, nums = [2,3,1,2,4,3]
输出2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
* 输入s = 7, nums = [2,3,1,2,4,3]
* 输出2
* 解释:子数组 [4,3] 是该条件下的长度最小的子数组。
提示:
@@ -23,11 +23,14 @@
* 1 <= nums.length <= 10^5
* 1 <= nums[i] <= 10^5
# 思路
## 算法公开课
为了易于大家理解我特意录制了B站视频[拿下滑动窗口! | LeetCode 209 长度最小的子数组](https://www.bilibili.com/video/BV1tZ4y1q7XE),结合视频看本题解,事半功倍!
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[拿下滑动窗口! | LeetCode 209 长度最小的子数组](https://www.bilibili.com/video/BV1tZ4y1q7XE)相信结合视频看本题解,更有助于大家对本题的理解**。
## 暴力解法
## 思路
### 暴力解法
这道题目暴力解法当然是 两个for循环然后不断的寻找符合条件的子序列时间复杂度很明显是O(n^2)。
@@ -61,7 +64,7 @@ public:
后面力扣更新了数据,暴力解法已经超时了。
## 滑动窗口
### 滑动窗口
接下来就开始介绍数组操作中另一个重要的方法:**滑动窗口**。
@@ -148,8 +151,8 @@ public:
## 其他语言版本
### Java
Java
```java
class Solution {
@@ -170,7 +173,7 @@ class Solution {
}
```
Python
### Python
```python
版本一滑动窗口法
@@ -213,7 +216,8 @@ class Solution:
return min_len if min_len != float('inf') else 0
```
Go
### Go
```go
func minSubArrayLen(target int, nums []int) int {
i := 0
@@ -239,8 +243,7 @@ func minSubArrayLen(target int, nums []int) int {
}
```
JavaScript:
### JavaScript:
```js
var minSubArrayLen = function(target, nums) {
@@ -263,7 +266,7 @@ var minSubArrayLen = function(target, nums) {
};
```
Typescript
### Typescript
```typescript
function minSubArrayLen(target: number, nums: number[]): number {
@@ -285,7 +288,7 @@ function minSubArrayLen(target: number, nums: number[]): number {
};
```
Swift:
### Swift:
```swift
func minSubArrayLen(_ target: Int, _ nums: [Int]) -> Int {
@@ -306,7 +309,7 @@ func minSubArrayLen(_ target: Int, _ nums: [Int]) -> Int {
}
```
Rust:
### Rust:
```rust
impl Solution {
@@ -333,7 +336,8 @@ impl Solution {
}
```
PHP:
### PHP:
```php
// 双指针 - 滑动窗口
class Solution {
@@ -362,7 +366,7 @@ class Solution {
}
```
Ruby:
### Ruby:
```ruby
def min_sub_array_len(target, nums)
@@ -380,8 +384,9 @@ def min_sub_array_len(target, nums)
end
```
C:
### C:
暴力解法:
```c
int minSubArrayLen(int target, int* nums, int numsSize){
//初始化最小长度为INT_MAX
@@ -430,7 +435,8 @@ int minSubArrayLen(int target, int* nums, int numsSize){
}
```
Kotlin:
### Kotlin:
```kotlin
class Solution {
fun minSubArrayLen(target: Int, nums: IntArray): Int {
@@ -482,7 +488,7 @@ class Solution {
}
}
```
Scala:
### Scala:
滑动窗口:
```scala
@@ -530,7 +536,8 @@ object Solution {
}
}
```
C#:
### C#:
```csharp
public class Solution {
public int MinSubArrayLen(int s, int[] nums) {
@@ -556,3 +563,4 @@ public class Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -7,8 +7,6 @@
> 别看本篇选的是组合总和III而不是组合总和本题和上一篇77.组合相比难度刚刚好!
# 216.组合总和III
@@ -30,12 +28,12 @@
输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[和组合问题有啥区别?回溯算法如何剪枝?| LeetCode216.组合总和III](https://www.bilibili.com/video/BV1wg411873x),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[和组合问题有啥区别?回溯算法如何剪枝?| LeetCode216.组合总和III](https://www.bilibili.com/video/BV1wg411873x),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
本题就是在[1,2,3,4,5,6,7,8,9]这个集合中找到和为n的k个数的组合。
@@ -54,7 +52,7 @@
图中可以看出只有最后取到集合13和为4 符合条件。
## 回溯三部曲
### 回溯三部曲
* **确定递归函数参数**
@@ -165,7 +163,7 @@ public:
};
```
## 剪枝
### 剪枝
这道题目,剪枝操作其实是很容易想到了,想必大家看上面的树形图的时候已经想到了。
@@ -238,7 +236,7 @@ public:
* 时间复杂度: O(n * 2^n)
* 空间复杂度: O(n)
# 总结
## 总结
开篇就介绍了本题与[77.组合](https://programmercarl.com/0077.组合.html)的区别,相对来说加了元素总和的限制,如果做完[77.组合](https://programmercarl.com/0077.组合.html)再做本题在合适不过。
@@ -249,10 +247,10 @@ public:
# 其他语言版本
## 其他语言版本
## Java
### Java
模板方法
@@ -358,7 +356,7 @@ class Solution {
}
```
## Python
### Python
```py
class Solution:
@@ -383,7 +381,7 @@ class Solution:
```
## Go
### Go
回溯+减枝
@@ -418,7 +416,7 @@ func dfs(k, n int, start int, sum int) {
}
```
## javaScript
### JavaScript
```js
/**
@@ -455,7 +453,7 @@ var combinationSum3 = function(k, n) {
};
```
## TypeScript
### TypeScript
```typescript
function combinationSum3(k: number, n: number): number[][] {
@@ -479,7 +477,7 @@ function combinationSum3(k: number, n: number): number[][] {
};
```
## Rust
### Rust
```Rust
impl Solution {
@@ -516,7 +514,7 @@ impl Solution {
}
```
## C
### C
```c
int* path;
@@ -575,7 +573,7 @@ int** combinationSum3(int k, int n, int* returnSize, int** returnColumnSizes){
}
```
## Swift
### Swift
```swift
func combinationSum3(_ count: Int, _ targetSum: Int) -> [[Int]] {
@@ -607,7 +605,7 @@ func combinationSum3(_ count: Int, _ targetSum: Int) -> [[Int]] {
}
```
## Scala
### Scala
```scala
object Solution {

View File

@@ -29,14 +29,17 @@
* 0 <= Node.val <= 5 * 10^4
* 题目数据保证输入的树是 完全二叉树
## 算法公开课
# 思路
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[要理解普通二叉树和完全二叉树的区别! | LeetCode222.完全二叉树节点的数量](https://www.bilibili.com/video/BV1eW4y1B7pD),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
《代码随想录》算法视频公开课:[要理解普通二叉树和完全二叉树的区别! | LeetCode222.完全二叉树节点的数量](https://www.bilibili.com/video/BV1eW4y1B7pD),相信结合视频在看本篇题解,更有助于大家对本题的理解。
本篇给出按照普通二叉树的求法以及利用完全二叉树性质的求法。
## 普通二叉树
### 普通二叉树
首先按照普通二叉树的逻辑来求。
@@ -44,7 +47,7 @@
递归遍历的顺序依然是后序(左右中)。
### 递归
#### 递归
如果对求二叉树深度还不熟悉的话,看这篇:[二叉树:看看这些树的最大深度](https://programmercarl.com/0104.二叉树的最大深度.html)。
@@ -112,7 +115,7 @@ public:
**网上基本都是这个精简的代码版本,其实不建议大家照着这个来写,代码确实精简,但隐藏了一些内容,连遍历的顺序都看不出来,所以初学者建议学习版本一的代码,稳稳的打基础**
### 迭代
#### 迭代
如果对求二叉树层序遍历还不熟悉的话,看这篇:[二叉树:层序遍历登场!](https://programmercarl.com/0102.二叉树的层序遍历.html)。
@@ -142,7 +145,7 @@ public:
* 时间复杂度O(n)
* 空间复杂度O(n)
## 完全二叉树
### 完全二叉树
以上方法都是按照普通二叉树来做的,对于完全二叉树特性不了解的同学可以看这篇 [关于二叉树,你该了解这些!](https://programmercarl.com/二叉树理论基础.html),这篇详细介绍了各种二叉树的特性。
@@ -249,9 +252,9 @@ public:
* 时间复杂度O(log n × log n)
* 空间复杂度O(log n)
# 其他语言版本
## 其他语言版本
## Java
### Java:
```java
class Solution {
// 通用递归解法
@@ -312,7 +315,7 @@ class Solution {
}
```
## Python
### Python:
递归法:
```python
@@ -408,7 +411,7 @@ class Solution: # 利用完全二叉树特性
return 1+self.countNodes(root.left)+self.countNodes(root.right)
```
## Go
### Go:
递归版本
@@ -488,9 +491,7 @@ func countNodes(root *TreeNode) int {
}
```
## JavaScript:
### JavaScript:
递归版本
```javascript
@@ -559,7 +560,7 @@ var countNodes = function(root) {
};
```
## TypeScrpt:
### TypeScrpt:
> 递归法
@@ -614,7 +615,7 @@ function countNodes(root: TreeNode | null): number {
};
```
## C:
### C:
递归法
```c
@@ -690,7 +691,7 @@ int countNodes(struct TreeNode* root){
}
```
## Swift:
### Swift:
> 递归
```swift
@@ -758,7 +759,7 @@ func countNodes(_ root: TreeNode?) -> Int {
}
```
## Scala
### Scala:
递归:
```scala
@@ -821,9 +822,9 @@ object Solution {
}
```
rust:
### Rust:
// 递归
递归
```rust
use std::cell::RefCell;
use std::rc::Rc;
@@ -838,7 +839,7 @@ impl Solution {
}
```
// 迭代
迭代
```rust
use std::rc::Rc;
use std::cell::RefCell;

View File

@@ -25,11 +25,11 @@
* 你所使用的语言也许不支持队列。 你可以使用 list 或者 deque双端队列来模拟一个队列 , 只要是标准的队列操作即可。
* 你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)。
## 算法公开课
# 思路
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[队列的基本操作! | LeetCode225. 用队列实现栈](https://www.bilibili.com/video/BV1Fd4y1K7sm),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
《代码随想录》算法公开课:[队列的基本操作! | LeetCode225. 用队列实现栈](https://www.bilibili.com/video/BV1Fd4y1K7sm),相信结合视频再看本篇题解,更有助于大家对链表的理解。
## 思路
(这里要强调是单向队列)
@@ -114,7 +114,7 @@ public:
* 时间复杂度: push为O(n)其他为O(1)
* 空间复杂度: O(n)
# 优化
## 优化
其实这道题目就是用一个队列就够了。
@@ -162,9 +162,9 @@ public:
* 空间复杂度: O(n)
# 其他语言版本
## 其他语言版本
Java
### Java
使用两个 Queue 实现方法1
```java
@@ -404,7 +404,7 @@ class MyStack {
}
```
Python
### Python
```python
from collections import deque
@@ -496,8 +496,7 @@ class MyStack:
return not self.que
```
Go
### Go
使用两个队列实现
```go
@@ -628,9 +627,7 @@ func (this *MyStack) Empty() bool {
*/
```
javaScript:
### JavaScript:
使用数组push, shift模拟队列
@@ -740,7 +737,7 @@ MyStack.prototype.empty = function() {
```
TypeScript:
### TypeScript:
版本一:使用两个队列模拟栈
@@ -812,7 +809,7 @@ class MyStack {
}
```
Swift
### Swift:
```Swift
// 定义一个队列数据结构
@@ -931,8 +928,9 @@ class MyStack {
}
}
```
Scala:
### Scala:
使用两个队列模拟栈:
```scala
import scala.collection.mutable
@@ -1015,8 +1013,8 @@ class MyStack() {
}
```
### C#:
C#:
```csharp
public class MyStack {
Queue<int> queue1;
@@ -1051,8 +1049,9 @@ public class MyStack {
}
```
PHP
> 双对列
### PHP:
> 双队列
```php
// SplQueue 类通过使用一个双向链表来提供队列的主要功能。(PHP 5 >= 5.3.0, PHP 7, PHP 8)
// https://www.php.net/manual/zh/class.splqueue.php
@@ -1130,6 +1129,8 @@ class MyStack {
}
```
### Rust:
> rust单队列
```rust

View File

@@ -16,7 +16,11 @@
这道题目背后有一个让程序员心酸的故事,听说 Homebrew的作者Max Howell就是因为没在白板上写出翻转二叉树最后被Google拒绝了。真假不做判断权当一个乐子哈
# 题外话
## 算法公开课
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[听说一位巨佬面Google被拒了因为没写出翻转二叉树 | LeetCode226.翻转二叉树](https://www.bilibili.com/video/BV1sP4y1f7q7),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 题外话
这道题目是非常经典的题目,也是比较简单的题目(至少一看就会)。
@@ -24,9 +28,7 @@
如果做过这道题的同学也建议认真看完,相信一定有所收获!
# 思路
《代码随想录》算法视频公开课:[听说一位巨佬面Google被拒了因为没写出翻转二叉树 | LeetCode226.翻转二叉树](https://www.bilibili.com/video/BV1sP4y1f7q7),相信结合视频在看本篇题解,更有助于大家对本题的理解。
## 思路
我们之前介绍的都是各种方式遍历二叉树,这次要翻转了,感觉还是有点懵逼。
@@ -49,7 +51,7 @@
那么层序遍历可以不可以呢?**依然可以的!只要把每一个节点的左右孩子翻转一下的遍历方式都是可以的!**
## 递归法
### 递归法
对于二叉树的递归法的前中后序遍历,已经在[二叉树:前中后序递归遍历](https://programmercarl.com/二叉树的递归遍历.html)详细讲解了。
@@ -102,9 +104,9 @@ public:
};
```
## 迭代法
### 迭代法
### 深度优先遍历
#### 深度优先遍历
[二叉树:听说递归能做的,栈也能做!](https://programmercarl.com/二叉树的迭代遍历.html)中给出了前中后序迭代方式的写法,所以本题可以很轻松的写出如下迭代法的代码:
@@ -163,7 +165,7 @@ public:
如果上面这个代码看不懂,回顾一下文章[二叉树:前中后序迭代方式的统一写法](https://programmercarl.com/二叉树的统一迭代法.html)。
### 广度优先遍历
#### 广度优先遍历
也就是层序遍历,层数遍历也是可以翻转这棵树的,因为层序遍历也可以把每个节点的左右孩子都翻转一遍,代码如下:
@@ -259,7 +261,7 @@ public:
## 其他语言版本
### Java
### Java:
```Java
//DFS递归
class Solution {
@@ -310,7 +312,7 @@ class Solution {
}
```
### Python
### Python:
递归法:前序遍历:
```python
@@ -466,7 +468,7 @@ class Solution:
```
### Go
### Go:
递归版本的前序遍历
```Go
@@ -575,7 +577,7 @@ func invertTree(root *TreeNode) *TreeNode {
}
```
### JavaScript
### JavaScript:
使用递归版本的前序遍历
```javascript
@@ -783,7 +785,7 @@ function invertTree(root: TreeNode | null): TreeNode | null {
};
```
### C
### C:
递归法
```c
@@ -961,7 +963,7 @@ object Solution {
}
```
### rust
### Rust:
```rust
impl Solution {
@@ -991,7 +993,7 @@ impl Solution {
}
```
### C#
### C#:
```csharp
//递归
@@ -1042,3 +1044,4 @@ public class Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -36,11 +36,12 @@ queue.empty(); // 返回 false
* 你所使用的语言也许不支持栈。你可以使用 list 或者 deque双端队列来模拟一个栈只要是标准的栈操作即可。
* 假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。
## 算法公开课
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[栈的基本操作! | LeetCode232.用栈实现队列](https://www.bilibili.com/video/BV1nY4y1w7VC),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
《代码随想录》算法公开课:[栈的基本操作! | LeetCode232.用栈实现队列](https://www.bilibili.com/video/BV1nY4y1w7VC),相信结合视频再看本篇题解,更有助于大家对栈和队列的理解。
这是一道模拟题,不涉及到具体算法,考察的就是对栈和队列的掌握程度。
使用栈来模式队列的行为,如果仅仅用一个栈,是一定不行的,所以需要两个栈**一个输入栈,一个输出栈**,这里要注意输入栈和输出栈的关系。
@@ -132,7 +133,7 @@ public:
## 其他语言版本
Java
### Java
```java
class MyQueue {
@@ -179,8 +180,8 @@ class MyQueue {
```
### Python
Python
```python
class MyQueue:
@@ -231,8 +232,8 @@ class MyQueue:
```
### Go
Go
```Go
type MyQueue struct {
stackIn []int //输入栈
@@ -283,7 +284,7 @@ func (this *MyQueue) Empty() bool {
}
```
javaScript:
### JavaScript:
```js
// 使用两个数组的栈方法push, pop 实现队列
@@ -338,7 +339,7 @@ MyQueue.prototype.empty = function() {
};
```
TypeScript:
### TypeScript:
```typescript
class MyQueue {
@@ -374,7 +375,7 @@ class MyQueue {
}
```
Swift
### Swift
```swift
class MyQueue {
@@ -413,7 +414,8 @@ class MyQueue {
}
```
C:
### C:
```C
/*
1.两个type为int的数组大小为100
@@ -490,8 +492,8 @@ void myQueueFree(MyQueue* obj) {
}
```
### C#:
C#:
```csharp
public class MyQueue {
Stack<int> inStack;
@@ -534,7 +536,8 @@ public class MyQueue {
PHP:
### PHP:
```php
// SplStack 类通过使用一个双向链表来提供栈的主要功能。[PHP 5 >= 5.3.0, PHP 7, PHP 8]
// https://www.php.net/manual/zh/class.splstack.php
@@ -579,7 +582,8 @@ class MyQueue {
}
```
Scala:
### Scala:
```scala
class MyQueue() {
import scala.collection.mutable
@@ -621,7 +625,7 @@ class MyQueue() {
}
```
rust:
### Rust:
```rust
struct MyQueue {
@@ -666,4 +670,3 @@ impl MyQueue {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -36,11 +36,11 @@
* 所有节点的值都是唯一的。
* p、q 为不同节点且均存在于给定的二叉搜索树中。
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[二叉搜索树找祖先就有点不一样了!| 235. 二叉搜索树的最近公共祖先](https://www.bilibili.com/video/BV1Zt4y1F7ww?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[二叉搜索树找祖先就有点不一样了!| 235. 二叉搜索树的最近公共祖先](https://www.bilibili.com/video/BV1Zt4y1F7ww?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
做过[二叉树:公共祖先问题](https://programmercarl.com/0236.二叉树的最近公共祖先.html)题目的同学应该知道利用回溯从底向上搜索遇到一个节点的左子树里有p右子树里有q那么当前节点就是最近公共祖先。
@@ -71,7 +71,7 @@
可以看出直接按照指定的方向就可以找到节点8为最近公共祖先而且不需要遍历整棵树找到结果直接返回
## 递归法
### 递归法
递归三部曲如下
@@ -203,7 +203,7 @@ public:
};
```
## 迭代法
### 迭代法
对于二叉搜索树的迭代法,大家应该在[二叉树:二叉搜索树登场!](https://programmercarl.com/0700.二叉搜索树中的搜索.html)就了解了。
@@ -229,7 +229,7 @@ public:
灵魂拷问:是不是又被简单的迭代法感动到痛哭流涕?
# 总结
## 总结
对于二叉搜索树的最近祖先问题,其实要比[普通二叉树公共祖先问题](https://programmercarl.com/0236.二叉树的最近公共祖先.html)简单的多。
@@ -238,10 +238,10 @@ public:
最后给出了对应的迭代法,二叉搜索树的迭代法甚至比递归更容易理解,也是因为其有序性(自带方向性),按照目标区间找就行了。
# 其他语言版本
## 其他语言版本
## Java
### Java
递归法:
```java
@@ -273,7 +273,7 @@ class Solution {
```
## Python
### Python
递归法(版本一)
```python
@@ -326,7 +326,7 @@ class Solution:
```
## Go
### Go
递归法:
```go
@@ -350,7 +350,7 @@ func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
```
## JavaScript
### JavaScript
递归法:
```javascript
@@ -391,7 +391,7 @@ var lowestCommonAncestor = function(root, p, q) {
};
```
## TypeScript
### TypeScript
> 递归法:
@@ -422,7 +422,7 @@ function lowestCommonAncestor(root: TreeNode | null, p: TreeNode | null, q: Tree
};
```
## Scala
### Scala
递归:
@@ -453,7 +453,7 @@ object Solution {
}
```
## rust
### Rust
递归:
@@ -519,3 +519,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -34,12 +34,12 @@
* 所有节点的值都是唯一的。
* p、q 为不同节点且均存在于给定的二叉树中。
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[自底向上查找,有点难度! | LeetCode236. 二叉树的最近公共祖先](https://www.bilibili.com/video/BV1jd4y1B7E2),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[自底向上查找,有点难度! | LeetCode236. 二叉树的最近公共祖先](https://www.bilibili.com/video/BV1jd4y1B7E2),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
遇到这个题目首先想的是要是能自底向上查找就好了,这样就可以找到公共祖先了。
@@ -226,7 +226,7 @@ public:
};
```
# 总结
## 总结
这道题目刷过的同学未必真正了解这里面回溯的过程,以及结果是如何一层一层传上去的。
@@ -243,10 +243,10 @@ public:
本题没有给出迭代法,因为迭代法不适合模拟回溯的过程。理解递归的解法就够了。
# 其他语言版本
## 其他语言版本
## Java
### Java
```Java
class Solution {
@@ -273,7 +273,7 @@ class Solution {
```
## Python
### Python
递归法(版本一)
```python
class Solution:
@@ -312,7 +312,7 @@ class Solution:
return left
```
## Go
### Go
```Go
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
@@ -343,7 +343,7 @@ func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
}
```
## JavaScript
### JavaScript
```javascript
var lowestCommonAncestor = function(root, p, q) {
@@ -370,7 +370,7 @@ var lowestCommonAncestor = function(root, p, q) {
};
```
## TypeScript
### TypeScript
```typescript
function lowestCommonAncestor(root: TreeNode | null, p: TreeNode | null, q: TreeNode | null): TreeNode | null {
@@ -384,7 +384,7 @@ function lowestCommonAncestor(root: TreeNode | null, p: TreeNode | null, q: Tree
};
```
## Scala
### Scala
```scala
object Solution {
@@ -404,7 +404,7 @@ object Solution {
}
```
## rust
### Rust
```rust
impl Solution {
@@ -436,3 +436,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -28,11 +28,11 @@
* -10^4 <= nums[i] <= 10^4
* 1 <= k <= nums.length
## 算法公开课
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[单调队列正式登场!| LeetCode239. 滑动窗口最大值](https://www.bilibili.com/video/BV1XS4y1p7qj),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
# 思路
《代码随想录》算法视频公开课:[单调队列正式登场!| LeetCode239. 滑动窗口最大值](https://www.bilibili.com/video/BV1XS4y1p7qj),相信结合视频在看本篇题解,更有助于大家对本题的理解。
## 思路
这是使用单调队列的经典题目。
@@ -196,7 +196,7 @@ public:
空间复杂度因为我们定义一个辅助队列所以是O(k)。
# 扩展
## 扩展
大家貌似对单调队列 都有一些疑惑首先要明确的是题解中单调队列里的pop和push接口仅适用于本题哈。单调队列不是一成不变的而是不同场景不同写法总之要保证队列里单调递减或递增的原则所以叫做单调队列。 不要以为本题中的单调队列实现就是固定的写法哈。
@@ -204,10 +204,10 @@ public:
# 其他语言版本
## 其他语言版本
### Java
Java
```Java
//解法一
//自定义数组
@@ -298,7 +298,8 @@ class Solution {
}
```
Python
### Python
```python
from collections import deque
@@ -338,8 +339,7 @@ class Solution:
return result
```
Go
### Go
```go
// 封装单调队列的方式解题
@@ -401,7 +401,8 @@ func maxSlidingWindow(nums []int, k int) []int {
}
```
Javascript:
### Javascript:
```javascript
/**
* @param {number[]} nums
@@ -449,7 +450,7 @@ var maxSlidingWindow = function (nums, k) {
};
```
TypeScript
### TypeScript
```typescript
function maxSlidingWindow(nums: number[], k: number): number[] {
@@ -497,7 +498,9 @@ function maxSlidingWindow(nums: number[], k: number): number[] {
};
```
Swift:
### Swift:
解法一:
```Swift
/// 双向链表
@@ -638,7 +641,8 @@ func maxSlidingWindow(_ nums: [Int], _ k: Int) -> [Int] {
return result
}
```
Scala:
### Scala:
```scala
import scala.collection.mutable.ArrayBuffer
object Solution {
@@ -686,8 +690,8 @@ class MyQueue {
}
```
### PHP:
PHP:
```php
class Solution {
/**
@@ -764,7 +768,8 @@ class MyQueue{
}
```
C#:
### C#:
```csharp
class myDequeue{
private LinkedList<int> linkedList = new LinkedList<int>();
@@ -805,7 +810,7 @@ class myDequeue{
}
```
rust:
### Rust:
```rust
impl Solution {

View File

@@ -7,7 +7,7 @@
> 数组就是简单的哈希表,但是数组的大小可不是无限开辟的
## 242.有效的字母异位词
# 242.有效的字母异位词
[力扣题目链接](https://leetcode.cn/problems/valid-anagram/)
@@ -21,13 +21,14 @@
输入: s = "rat", t = "car"
输出: false
**说明:**
你可以假设字符串只包含小写字母。
## 思路
## 算法公开课
本题B站视频讲解版[学透哈希表数组使用有技巧Leetcode242.有效的字母异位词](https://www.bilibili.com/video/BV1YG411p7BA)
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[学透哈希表数组使用有技巧Leetcode242.有效的字母异位词](https://www.bilibili.com/video/BV1YG411p7BA),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
先看暴力的解法两层for循环同时还要记录字符是否重复出现很明显时间复杂度是 O(n^2)。
@@ -88,12 +89,10 @@ public:
* 时间复杂度: O(n)
* 空间复杂度: O(1)
## 其他语言版本
### Java
Java
```java
/**
* 242. 有效的字母异位词 字典解法
@@ -121,7 +120,7 @@ class Solution {
}
```
Python
### Python
```python
class Solution:
@@ -163,8 +162,9 @@ class Solution(object):
a_count = Counter(s)
b_count = Counter(t)
return a_count == b_count
```
Go
### Go
```go
func isAnagram(s string, t string) bool {
@@ -181,7 +181,7 @@ func isAnagram(s string, t string) bool {
}
```
javaScript:
### JavaScript:
```js
/**
@@ -217,7 +217,7 @@ var isAnagram = function(s, t) {
};
```
TypeScript
### TypeScript
```typescript
function isAnagram(s: string, t: string): boolean {
@@ -232,7 +232,7 @@ function isAnagram(s: string, t: string): boolean {
};
```
Swift
### Swift
```Swift
func isAnagram(_ s: String, _ t: String) -> Bool {
@@ -256,7 +256,8 @@ func isAnagram(_ s: String, _ t: String) -> Bool {
}
```
PHP
### PHP
```php
class Solution {
/**
@@ -291,7 +292,8 @@ class Solution {
}
```
Rust
### Rust
```rust
impl Solution {
pub fn is_anagram(s: String, t: String) -> bool {
@@ -311,8 +313,8 @@ impl Solution {
}
```
### Scala:
Scala:
```scala
object Solution {
def isAnagram(s: String, t: String): Boolean = {
@@ -336,8 +338,8 @@ object Solution {
}
```
### C#
C#
```csharp
public bool IsAnagram(string s, string t) {
int sl=s.Length,tl=t.Length;
@@ -359,11 +361,12 @@ C#
## 相关题目
* [383.赎金信](https://programmercarl.com/0383.%E8%B5%8E%E9%87%91%E4%BF%A1.html)
* 49.字母异位词分组
* 438.找到字符串中所有字母异位词
* [49.字母异位词分组](https://leetcode.cn/problems/group-anagrams/)
* [438.找到字符串中所有字母异位词](https://leetcode.cn/problems/find-all-anagrams-in-a-string/)
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -18,9 +18,11 @@
示例:
![257.二叉树的所有路径1](https://code-thinking-1253855093.file.myqcloud.com/pics/2021020415161576.png)
# 思路
## 算法公开课
**《代码随想录》算法视频公开课:[递归中带着回溯,你感受到了没?| LeetCode257. 二叉树的所有路径](https://www.bilibili.com/video/BV1ZG411G7Dh),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[递归中带着回溯,你感受到了没?| LeetCode257. 二叉树的所有路径](https://www.bilibili.com/video/BV1ZG411G7Dh),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
## 思路
这道题目要求从根节点到叶子的路径,所以需要前序遍历,这样才方便让父节点指向孩子节点,找到对应的路径。
@@ -32,7 +34,7 @@
我们先使用递归的方式,来做前序遍历。**要知道递归和回溯就是一家的,本题也需要回溯。**
## 递归
### 递归
1. 递归函数参数以及返回值
@@ -305,7 +307,7 @@ public:
**综合以上,第二种递归的代码虽然精简但把很多重要的点隐藏在了代码细节里,第一种递归写法虽然代码多一些,但是把每一个逻辑处理都完整的展现出来了。**
## 拓展
### 拓展
这里讲解本题解的写法逻辑以及一些更具体的细节下面的讲解中涉及到C++语法特性如果不是C++的录友,就可以不看了,避免越看越晕。
@@ -328,7 +330,7 @@ public:
所以,第一个代码版本中,我才使用 vector 类型的path这样方便给大家演示代码中回溯的操作。 vector类型的path不管 每次 路径收集的数字是几位数总之一定是int所以就一次 pop_back就可以。
## 迭代法
### 迭代法
至于非递归的方式,我们可以依然可以使用前序遍历的迭代方式来模拟遍历路径的过程,对该迭代方式不了解的同学,可以看文章[二叉树:听说递归能做的,栈也能做!](https://programmercarl.com/二叉树的迭代遍历.html)和[二叉树:前中后序迭代方式统一写法](https://programmercarl.com/二叉树的统一迭代法.html)。
@@ -368,7 +370,7 @@ public:
```
当然使用java的同学可以直接定义一个成员变量为object的栈`Stack<Object> stack = new Stack<>();`,这样就不用定义两个栈了,都放到一个栈里就可以了。
# 总结
## 总结
**本文我们开始初步涉及到了回溯,很多同学过了这道题目,可能都不知道自己其实使用了回溯,回溯和递归都是相伴相生的。**
@@ -380,13 +382,9 @@ public:
对于本题充分了解递归与回溯的过程之后,有精力的同学可以再去实现迭代法。
## 其他语言版本
# 其他语言版本
## Java
### Java
```Java
//解法一
@@ -492,9 +490,9 @@ class Solution {
}
```
---
## Python:
### Python:
递归法+回溯
```Python
# Definition for a binary tree node.
@@ -552,7 +550,7 @@ class Solution:
self.traversal(cur.right, path[:], result)
```
递归法+隐形回溯(版本二)
```Python
# Definition for a binary tree node.
@@ -610,7 +608,7 @@ class Solution:
---
## Go
### Go
递归法:
@@ -672,7 +670,7 @@ func binaryTreePaths(root *TreeNode) []string {
```
---
## JavaScript:
### JavaScript:
递归法:
@@ -725,7 +723,7 @@ var binaryTreePaths = function(root) {
};
```
## TypeScript
### TypeScript
> 递归法
@@ -779,7 +777,7 @@ function binaryTreePaths(root: TreeNode | null): string[] {
};
```
## Swift:
### Swift:
> 递归/回溯
```swift
@@ -846,7 +844,7 @@ func binaryTreePaths(_ root: TreeNode?) -> [String] {
}
```
## Scala:
### Scala:
递归:
```scala
@@ -876,7 +874,7 @@ object Solution {
}
```
rust:
### Rust:
```rust
// 递归
@@ -907,4 +905,3 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -455,7 +455,29 @@ function maxProfit(prices: number[]): number {
};
```
Rust
```rust
impl Solution {
pub fn max_profit(prices: Vec<i32>) -> i32 {
/*
* dp[i][0]: 持股状态;
* dp[i][1]: 无股状态,当天为非冷冻期;
* dp[i][2]: 无股状态,当天卖出;
* dp[i][3]: 无股状态,当天为冷冻期;
*/
let mut dp = vec![vec![0; 4]; prices.len()];
dp[0][0] = -prices[0];
for (i, &p) in prices.iter().enumerate().skip(1) {
dp[i][0] = dp[i - 1][0].max((dp[i - 1][3] - p).max(dp[i - 1][1] - p));
dp[i][1] = dp[i - 1][1].max(dp[i - 1][3]);
dp[i][2] = dp[i - 1][0] + p;
dp[i][3] = dp[i - 1][2];
}
*dp[prices.len() - 1].iter().skip(1).max().unwrap()
}
}
```
<p align="center">

View File

@@ -29,9 +29,11 @@
* 输出:["JFK","ATL","JFK","SFO","ATL","SFO"]
* 解释:另一种有效的行程是 ["JFK","SFO","ATL","JFK","ATL","SFO"]。但是它自然排序更大更靠后。
## 思路
## 算法公开课
**如果对回溯算法基础还不了解的话,我还特意录制了一期视频:[带你学透回溯算法(理论篇)](https://www.bilibili.com/video/BV1cy4y167mM/)** 可以结合题解和视频一起看,希望对大家理解回溯算法有所帮助。
**如果对回溯算法基础还不了解的话,我还特意录制了一期视频[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[带你学透回溯算法(理论篇)](https://www.bilibili.com/video/BV1cy4y167mM/)** 可以结合题解和视频一起看,希望对大家理解回溯算法有所帮助。
## 思路
这道题目还是很难的,之前我们用回溯法解决了如下问题:[组合问题](https://programmercarl.com/0077.组合.html)[分割问题](https://programmercarl.com/0093.复原IP地址.html)[子集问题](https://programmercarl.com/0078.子集.html)[排列问题](https://programmercarl.com/0046.全排列.html)。
@@ -53,7 +55,7 @@
针对以上问题我来逐一解答!
## 如何理解死循环
### 如何理解死循环
对于死循环,我来举一个有重复机场的例子:
@@ -61,7 +63,7 @@
为什么要举这个例子呢,就是告诉大家,出发机场和到达机场也会重复的,**如果在解题的过程中没有对集合元素处理好,就会死循环。**
## 该记录映射关系
### 该记录映射关系
有多种解法,字母序靠前排在前面,让很多同学望而退步,如何该记录映射关系呢
@@ -90,7 +92,7 @@ unordered_map<string, map<string, int>> targetsunordered_map<出发机场, ma
**相当于说我不删,我就做一个标记!**
## 回溯法
### 回溯法
这道题目我使用回溯法,那么下面按照我总结的回溯模板来:
@@ -260,8 +262,8 @@ for (pair<string, int>target : targets[result[result.size() - 1]])
## 其他语言版本
### java
### Java
```java
class Solution {
private LinkedList<String> res;
@@ -346,7 +348,7 @@ class Solution {
}
```
### python
### Python
回溯 使用used数组
```python
@@ -406,7 +408,7 @@ class Solution:
path.pop() # 移除目的地
return False # 没有找到有效行程
```
```
回溯 使用字典 逆序
```python
from collections import defaultdict
@@ -430,8 +432,8 @@ class Solution:
self.backtracking(next_airport, targets, result) # 递归调用回溯函数进行深度优先搜索
result.append(airport) # 将当前机场添加到行程路径中
```
### GO
### Go
```go
type pair struct {
target string
@@ -577,7 +579,7 @@ function findItinerary(tickets: string[][]): string[] {
};
```
### C语言
### C
```C
char **result;
@@ -638,7 +640,7 @@ char ** findItinerary(char *** tickets, int ticketsSize, int* ticketsColSize, in
return result;
}
```
### Swift
直接迭代tickets数组
@@ -791,3 +793,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -26,10 +26,12 @@
输入:["H","a","n","n","a","h"]
输出:["h","a","n","n","a","H"]
## 算法公开课
# 思路
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[字符串基础操作! | LeetCode344.反转字符串](https://www.bilibili.com/video/BV1fV4y17748),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
针对本题,我录制了视频讲解:[字符串基础操作! | LeetCode344.反转字符串](https://www.bilibili.com/video/BV1fV4y17748),结合本题解一起看,事半功倍!
## 思路
先说一说题外话:
@@ -138,8 +140,8 @@ public:
## 其他语言版本
### Java
Java
```Java
class Solution {
public void reverseString(char[] s) {
@@ -173,8 +175,9 @@ class Solution {
```
Python
### Python
(版本一) 双指针
```python
class Solution:
def reverseString(self, s: List[str]) -> None:
@@ -247,7 +250,8 @@ class Solution:
s[:] = [s[i] for i in range(len(s) - 1, -1, -1)]
```
Go
### Go
```Go
func reverseString(s []byte) {
left := 0
@@ -260,7 +264,7 @@ func reverseString(s []byte) {
}
```
javaScript:
### JavaScript:
```js
/**
@@ -278,7 +282,7 @@ var reverse = function(s) {
};
```
TypeScript
### TypeScript
```typescript
/**
@@ -299,7 +303,7 @@ function reverseString(s: string[]): void {
};
```
Swift:
### Swift:
```swift
// 双指针 - 元组
@@ -316,7 +320,8 @@ func reverseString(_ s: inout [Character]) {
```
Rust:
### Rust:
```Rust
impl Solution {
pub fn reverse_string(s: &mut Vec<char>) {
@@ -332,7 +337,8 @@ impl Solution {
}
```
C:
### C:
```c
void reverseString(char* s, int sSize){
int left = 0;
@@ -347,7 +353,8 @@ void reverseString(char* s, int sSize){
}
```
C#
### C#
```csharp
public class Solution
{
@@ -361,8 +368,8 @@ public class Solution
}
```
### PHP
PHP
```php
// 双指针
// 一:
@@ -392,7 +399,8 @@ function reverse(&$s, $start, $end) {
}
```
Scala:
### Scala:
```scala
object Solution {
def reverseString(s: Array[Char]): Unit = {
@@ -411,4 +419,3 @@ object Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -5,8 +5,6 @@
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
> 前K个大数问题老生常谈不得不谈
# 347.前 K 个高频元素
@@ -29,9 +27,11 @@
* 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
* 你可以按任意顺序返回答案。
# 思路
## 算法公开课
《代码随想录》算法视频公开课:[优先级队列正式登场!大顶堆、小顶堆该怎么用?| LeetCode347.前 K 个高频元素](https://www.bilibili.com/video/BV1Xg41167Lz),相信结合视频看本篇题解,更有助于大家对本题的理解。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[优先级队列正式登场!大顶堆、小顶堆该怎么用?| LeetCode347.前 K 个高频元素](https://www.bilibili.com/video/BV1Xg41167Lz),相信结合视频看本篇题解,更有助于大家对本题的理解**
## 思路
这道题目主要涉及到如下三块内容:
1. 要统计元素出现频率
@@ -122,7 +122,7 @@ public:
* 时间复杂度: O(nlogk)
* 空间复杂度: O(n)
# 拓展
## 拓展
大家对这个比较运算在建堆时是如何应用的,为什么左大于右就会建立小顶堆,反而建立大顶堆比较困惑。
确实 例如我们在写快排的cmp函数的时候`return left>right` 就是从大到小,`return left<right` 就是从小到大。
@@ -130,10 +130,10 @@ public:
优先级队列的定义正好反过来了,可能和优先级队列的源码实现有关(我没有仔细研究),我估计是底层实现上优先队列队首指向后面,队尾指向最前面的缘故!
# 其他语言版本
## 其他语言版本
### Java
Java
```java
/*Comparator接口说明:
@@ -216,7 +216,8 @@ class Solution {
}
```
Python
### Python
```python
#时间复杂度O(nlogk)
#空间复杂度O(n)
@@ -245,7 +246,7 @@ class Solution:
return result
```
Go
### Go
```go
//方法一:小顶堆
@@ -320,8 +321,8 @@ func topKFrequent(nums []int, k int) []int {
### JavaScript:
JavaScript:
```js
// js 没有堆 需要自己构造
class Heap {
@@ -419,7 +420,7 @@ const topKFrequent = function (nums, k) {
};
```
TypeScript
### TypeScript
```typescript
function topKFrequent(nums: number[], k: number): number[] {
@@ -435,7 +436,8 @@ function topKFrequent(nums: number[], k: number): number[] {
};
```
C#:
### C#:
```csharp
public int[] TopKFrequent(int[] nums, int k) {
//哈希表-标权重
@@ -473,7 +475,7 @@ C#:
```
Scala:
### Scala:
解法一: 优先级队列
```scala
@@ -517,7 +519,9 @@ object Solution {
}
```
rust: 小根堆
### Rust
小根堆
```rust
use std::cmp::Reverse;
@@ -549,3 +553,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -10,7 +10,7 @@
> 如果哈希值比较少、特别分散、跨度非常大,使用数组就造成空间的极大浪费!
## 349. 两个数组的交集
# 349. 两个数组的交集
[力扣题目链接](https://leetcode.cn/problems/intersection-of-two-arrays/)
@@ -22,9 +22,11 @@
输出结果中的每个元素一定是唯一的。
我们可以不考虑输出结果的顺序。
## 思路
## 算法公开课
关于本题,我录制了讲解视频[学透哈希表set使用有技巧Leetcode349. 两个数组的交集](https://www.bilibili.com/video/BV1ba411S7wu)看视频配合题解,事半功倍
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[学透哈希表set使用有技巧Leetcode349. 两个数组的交集](https://www.bilibili.com/video/BV1ba411S7wu)相信结合视频再看本篇题解,更有助于大家对本题的理解**
## 思路
这道题目主要要学会使用一种哈希数据结构unordered_set这个数据结构可以解决很多类似的问题。
@@ -118,8 +120,7 @@ public:
## 其他语言版本
Java
### Java
```Java
import java.util.HashSet;
@@ -159,8 +160,9 @@ class Solution {
}
```
Python3
### Python3
(版本一) 使用字典和集合
```python
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
@@ -206,7 +208,8 @@ class Solution:
```
Go
### Go
```go
func intersection(nums1 []int, nums2 []int) []int {
set:=make(map[int]struct{},0) // 用map模拟set
@@ -227,7 +230,7 @@ func intersection(nums1 []int, nums2 []int) []int {
}
```
javaScript:
### JavaScript:
```js
/**
@@ -255,7 +258,7 @@ var intersection = function(nums1, nums2) {
};
```
TypeScript:
### TypeScript:
版本一(正常解法):
@@ -280,7 +283,7 @@ function intersection(nums1: number[], nums2: number[]): number[] {
};
```
Swift
### Swift
```swift
func intersection(_ nums1: [Int], _ nums2: [Int]) -> [Int] {
@@ -298,7 +301,8 @@ func intersection(_ nums1: [Int], _ nums2: [Int]) -> [Int] {
}
```
PHP:
### PHP:
```php
class Solution {
/**
@@ -327,7 +331,8 @@ class Solution {
}
```
Rust:
### Rust:
```rust
use std::collections::HashSet;
impl Solution {
@@ -363,7 +368,8 @@ impl Solution {
}
```
C:
### C:
```C
int* intersection1(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
@@ -394,7 +400,7 @@ int* intersection1(int* nums1, int nums1Size, int* nums2, int nums2Size, int* re
}
```
Scala:
### Scala:
正常解法:
```scala
@@ -439,8 +445,8 @@ object Solution {
```
### C#:
C#:
```csharp
public int[] Intersection(int[] nums1, int[] nums2) {
if(nums1==null||nums1.Length==0||nums2==null||nums1.Length==0)
@@ -461,11 +467,10 @@ C#:
```
## 相关题目
* 350.两个数组的交集 II
* [350.两个数组的交集 II](https://leetcode.cn/problems/intersection-of-two-arrays-ii/)
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -34,7 +34,7 @@ canConstruct("aa", "aab") -> true
* 第二点 “你可以假设两个字符串均只含有小写字母。” *说明只有小写字母*,这一点很重要
## 暴力解法
### 暴力解法
那么第一个思路其实就是暴力枚举了两层for循环不断去寻找代码如下
@@ -66,7 +66,7 @@ public:
这里时间复杂度是比较高的而且里面还有一个字符串删除也就是erase的操作也是费时的当然这段代码也可以过这道题。
## 哈希解法
### 哈希解法
因为题目所只有小写字母,那可以采用空间换取时间的哈希策略, 用一个长度为26的数组还记录magazine里字母出现的次数。
@@ -88,7 +88,7 @@ public:
return false;
}
for (int i = 0; i < magazine.length(); i++) {
// 通过recode数据记录 magazine里各个字符出现次数
// 通过record数据记录 magazine里各个字符出现次数
record[magazine[i]-'a'] ++;
}
for (int j = 0; j < ransomNote.length(); j++) {
@@ -112,8 +112,8 @@ public:
## 其他语言版本
### Java
Java
```Java
class Solution {
public boolean canConstruct(String ransomNote, String magazine) {
@@ -146,8 +146,9 @@ class Solution {
```
Python
### Python
(版本一)使用数组
```python
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
@@ -213,12 +214,12 @@ class Solution:
return all(ransomNote.count(c) <= magazine.count(c) for c in set(ransomNote))
```
Go
### Go
```go
func canConstruct(ransomNote string, magazine string) bool {
record := make([]int, 26)
for _, v := range magazine { // 通过recode数据记录 magazine里各个字符出现次数
for _, v := range magazine { // 通过record数据记录 magazine里各个字符出现次数
record[v-'a']++
}
for _, v := range ransomNote { // 遍历ransomNote在record里对应的字符个数做--操作
@@ -231,7 +232,7 @@ func canConstruct(ransomNote string, magazine string) bool {
}
```
javaScript:
### JavaScript:
```js
/**
@@ -254,7 +255,7 @@ var canConstruct = function(ransomNote, magazine) {
};
```
TypeScript:
### TypeScript:
```typescript
function canConstruct(ransomNote: string, magazine: string): boolean {
@@ -275,8 +276,8 @@ function canConstruct(ransomNote: string, magazine: string): boolean {
};
```
### PHP:
PHP:
```php
class Solution {
/**
@@ -301,7 +302,8 @@ class Solution {
}
```
Swift
### Swift
```swift
func canConstruct(_ ransomNote: String, _ magazine: String) -> Bool {
var record = Array(repeating: 0, count: 26);
@@ -324,7 +326,8 @@ func canConstruct(_ ransomNote: String, _ magazine: String) -> Bool {
}
```
Rust:
### Rust:
```rust
impl Solution {
pub fn can_construct(ransom_note: String, magazine: String) -> bool {
@@ -347,7 +350,7 @@ impl Solution {
}
```
Scala:
### Scala:
版本一: 使用数组作为哈希表
```scala
@@ -411,8 +414,8 @@ object Solution {
}
```
### C#
C#
```csharp
public bool CanConstruct(string ransomNote, string magazine) {
if(ransomNote.Length > magazine.Length) return false;
@@ -434,3 +437,4 @@ public bool CanConstruct(string ransomNote, string magazine) {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -16,9 +16,9 @@
![404.左叶子之和1](https://code-thinking-1253855093.file.myqcloud.com/pics/20210204151927654.png)
## 视频讲解
## 算法公开课
**《代码随想录》算法视频公开课:[二叉树的题目中,总有一些规则让你找不到北 | LeetCode404.左叶子之和](https://www.bilibili.com/video/BV1GY4y1K7z8),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[二叉树的题目中,总有一些规则让你找不到北 | LeetCode404.左叶子之和](https://www.bilibili.com/video/BV1GY4y1K7z8),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -48,7 +48,7 @@ if (node->left != NULL && node->left->left == NULL && node->left->right == NULL)
}
```
## 递归法
### 递归法
递归的遍历顺序为后序遍历(左右中),是因为要通过递归函数的返回值来累加求取左叶子数值之和。
@@ -131,11 +131,11 @@ public:
return leftValue + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
}
};
```
```
精简之后的代码其实看不出来用的是什么遍历方式了,对于算法初学者以上根据第一个版本来学习。
## 迭代法
### 迭代法
本题迭代法使用前中后序都是可以的,只要把左叶子节点统计出来,就可以了,那么参考文章 [二叉树:听说递归能做的,栈也能做!](https://programmercarl.com/二叉树的迭代遍历.html)和[二叉树:迭代法统一写法](https://programmercarl.com/二叉树的统一迭代法.html)中的写法,可以写出一个前序遍历的迭代法。
@@ -177,7 +177,7 @@ public:
## 其他语言版本
### Java
### Java
**递归**
@@ -246,7 +246,7 @@ class Solution {
```
### Python
### Python:
递归
```python
# Definition for a binary tree node.
@@ -316,7 +316,7 @@ class Solution:
```
### Go
### Go:
**递归法**
@@ -368,7 +368,7 @@ func sumOfLeftLeaves(root *TreeNode) int {
```
### JavaScript
### JavaScript:
**递归法**
@@ -417,7 +417,7 @@ var sumOfLeftLeaves = function(root) {
};
```
### TypeScript
### TypeScript:
> 递归法
@@ -462,7 +462,7 @@ function sumOfLeftLeaves(root: TreeNode | null): number {
};
```
### Swift
### Swift:
**递归法**
```swift
@@ -511,7 +511,7 @@ func sumOfLeftLeaves(_ root: TreeNode?) -> Int {
}
```
### C
### C:
递归法:
```c
int sumOfLeftLeaves(struct TreeNode* root){
@@ -561,7 +561,7 @@ int sumOfLeftLeaves(struct TreeNode* root){
}
```
### Scala
### Scala:
**递归:**
```scala
@@ -600,7 +600,7 @@ object Solution {
}
```
### Rust
### Rust:
**递归**
@@ -656,3 +656,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -24,15 +24,15 @@
![450.删除二叉搜索树中的节点](https://code-thinking-1253855093.file.myqcloud.com/pics/20201020171048265.png)
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[调整二叉树的结构最难!| LeetCode450.删除二叉搜索树中的节点](https://www.bilibili.com/video/BV1tP41177us?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[调整二叉树的结构最难!| LeetCode450.删除二叉搜索树中的节点](https://www.bilibili.com/video/BV1tP41177us?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
搜索树的节点删除要比节点增加复杂的多,有很多情况需要考虑,做好心理准备。
## 递归
### 递归
递归三部曲:
@@ -161,7 +161,7 @@ public:
};
```
## 普通二叉树的删除方式
### 普通二叉树的删除方式
这里我在介绍一种通用的删除,普通二叉树的删除方式(没有使用搜索树的特性,遍历整棵树),用交换值的操作来删除目标节点。
@@ -198,7 +198,7 @@ public:
这个代码是简短一些,思路也巧妙,但是不太好想,实操性不强,推荐第一种写法!
## 迭代法
### 迭代法
删除节点的迭代法还是复杂一些的,但其本质我在递归法里都介绍了,最关键就是删除节点的操作(动画模拟的过程)
@@ -246,7 +246,7 @@ public:
};
```
# 总结
## 总结
读完本篇,大家会发现二叉搜索树删除节点比增加节点复杂的多。
@@ -264,10 +264,10 @@ public:
迭代法其实不太容易写出来,所以如果是初学者的话,彻底掌握第一种递归写法就够了。
# 其他语言版本
## 其他语言版本
## Java
### Java
```java
// 解法1(最好理解的版本)
class Solution {
@@ -375,7 +375,8 @@ class Solution {
```
## Python
### Python
递归法(版本一)
```python
class Solution:
@@ -463,7 +464,7 @@ class Solution:
return root
```
## Go
### Go
```Go
// 递归版本
func deleteNode(root *TreeNode, key int) *TreeNode {
@@ -549,7 +550,7 @@ func deleteNode(root *TreeNode, key int) *TreeNode {
}
```
## JavaScript
### JavaScript
递归
@@ -640,7 +641,7 @@ var deleteNode = function (root, key) {
}
```
## TypeScript
### TypeScript
> 递归法:
@@ -704,7 +705,7 @@ function deleteNode(root: TreeNode | null, key: number): TreeNode | null {
};
```
## Scala
### Scala
```scala
object Solution {
@@ -734,7 +735,7 @@ object Solution {
}
```
## rust
### Rust
```rust
impl Solution {
@@ -772,3 +773,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -34,10 +34,12 @@
1. (0, 0, 0, 1) -> A[0] + B[0] + C[0] + D[1] = 1 + (-2) + (-1) + 2 = 0
2. (1, 1, 0, 0) -> A[1] + B[1] + C[0] + D[0] = 2 + (-1) + (-1) + 0 = 0
## 算法公开课
# 思路
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[学透哈希表map使用有技巧LeetCode454.四数相加II](https://www.bilibili.com/video/BV1Md4y1Q7Yh),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
本题视频讲解:[学透哈希表map使用有技巧LeetCode454.四数相加II](https://www.bilibili.com/video/BV1Md4y1Q7Yh),结合视频在看本题解,事半功倍。
## 思路
本题咋眼一看好像和[0015.三数之和](https://programmercarl.com/0015.三数之和.html)[0018.四数之和](https://programmercarl.com/0018.四数之和.html)差不多,其实差很多。
@@ -92,8 +94,8 @@ public:
## 其他语言版本
### Java
Java
```Java
class Solution {
public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
@@ -117,8 +119,9 @@ class Solution {
}
```
Python
### Python
(版本一) 使用字典
```python
class Solution(object):
def fourSumCount(self, nums1, nums2, nums3, nums4):
@@ -179,7 +182,7 @@ class Solution:
return cnt
```
Go
### Go
```go
func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int {
@@ -201,7 +204,7 @@ func fourSumCount(nums1 []int, nums2 []int, nums3 []int, nums4 []int) int {
}
```
javaScript:
### JavaScript:
```js
/**
@@ -233,7 +236,7 @@ var fourSumCount = function(nums1, nums2, nums3, nums4) {
};
```
TypeScript
### TypeScript
```typescript
function fourSumCount(nums1: number[], nums2: number[], nums3: number[], nums4: number[]): number {
@@ -258,7 +261,7 @@ function fourSumCount(nums1: number[], nums2: number[], nums3: number[], nums4:
};
```
PHP:
### PHP:
```php
class Solution {
@@ -291,8 +294,8 @@ class Solution {
}
```
### Swift
Swift
```swift
func fourSumCount(_ nums1: [Int], _ nums2: [Int], _ nums3: [Int], _ nums4: [Int]) -> Int {
// ab和: ab和出现次数
@@ -316,7 +319,8 @@ func fourSumCount(_ nums1: [Int], _ nums2: [Int], _ nums3: [Int], _ nums4: [Int]
}
```
Rust
### Rust
```rust
use std::collections::HashMap;
impl Solution {
@@ -342,8 +346,8 @@ impl Solution {
}
```
### Scala:
Scala:
```scala
object Solution {
// 导包
@@ -380,7 +384,8 @@ object Solution {
}
```
C#
### C#
```csharp
public int FourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
Dictionary<int, int> dic = new Dictionary<int, int>();
@@ -411,3 +416,4 @@ public int FourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -5,8 +5,6 @@
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
> KMP算法还能干这个
# 459.重复的子字符串
@@ -16,22 +14,24 @@
给定一个非空的字符串判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母并且长度不超过10000。
示例 1:
输入: "abab"
输出: True
解释: 可由子字符串 "ab" 重复两次构成。
* 输入: "abab"
* 输出: True
* 解释: 可由子字符串 "ab" 重复两次构成。
示例 2:
输入: "aba"
输出: False
* 输入: "aba"
* 输出: False
示例 3:
输入: "abcabcabcabc"
输出: True
解释: 可由子字符串 "abc" 重复四次构成。 (或者子字符串 "abcabc" 重复两次构成。)
* 输入: "abcabcabcabc"
* 输出: True
* 解释: 可由子字符串 "abc" 重复四次构成。 (或者子字符串 "abcabc" 重复两次构成。)
# 思路
## 算法公开课
针对本题,我录制了视频讲解[字符串这么玩,可有点难度! | LeetCode459.重复的子字符串](https://www.bilibili.com/video/BV1cg41127fw)结合本题解一起看,事半功倍!
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[字符串这么玩,可有点难度! | LeetCode459.重复的子字符串](https://www.bilibili.com/video/BV1cg41127fw)相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
暴力的解法, 就是一个for循环获取 子串的终止位置, 然后判断子串是否能重复构成字符串又嵌套一个for循环所以是O(n^2)的时间复杂度。
@@ -44,7 +44,7 @@
主要讲一讲移动匹配 和 KMP两种方法。
## 移动匹配
### 移动匹配
当一个字符串sabcabc内部由重复的子串组成那么这个字符串的结构一定是这样的
@@ -80,9 +80,9 @@ public:
如果我们做过 [28.实现strStr](https://programmercarl.com/0028.实现strStr.html) 题目的话,其实就知道,**实现一个 高效的算法来判断 一个字符串中是否出现另一个字符串是很复杂的**这里就涉及到了KMP算法。
## KMP
### KMP
### 为什么会使用KMP
#### 为什么会使用KMP
以下使用KMP方式讲解强烈建议大家先把以下两个视频看了理解KMP算法再来看下面讲解否则会很懵。
* [视频讲解版帮你把KMP算法学个通透理论篇](https://www.bilibili.com/video/BV1PD4y1o7nd/)
@@ -105,7 +105,7 @@ KMP算法中next数组为什么遇到字符不匹配的时候可以找到上一
![图三](https://code-thinking-1253855093.file.myqcloud.com/pics/20220728205249.png)
### 如何找到最小重复子串
#### 如何找到最小重复子串
这里有同学就问了为啥一定是开头的ab呢。 其实最关键还是要理解 最长相等前后缀,如图:
@@ -123,7 +123,7 @@ KMP算法中next数组为什么遇到字符不匹配的时候可以找到上一
正是因为 最长相等前后缀的规则,当一个字符串由重复子串组成的,最长相等前后缀不包含的子串就是最小重复子串。
### 简单推理
#### 简单推理
这里再给出一个数学推导,就容易理解很多。
@@ -229,7 +229,7 @@ public:
## 其他语言版本
Java
### Java
```java
class Solution {
@@ -261,8 +261,7 @@ class Solution {
}
```
Python
### Python
(版本一) 前缀表 减一
```python
@@ -346,8 +345,7 @@ class Solution:
return False
```
Go
### Go
这里使用了前缀表统一减一的实现方式
@@ -405,7 +403,7 @@ func repeatedSubstringPattern(s string) bool {
}
```
JavaScript版本
### JavaScript:
> 前缀表统一减一
@@ -479,7 +477,7 @@ var repeatedSubstringPattern = function (s) {
};
```
TypeScript:
### TypeScript:
> 前缀表统一减一
@@ -539,8 +537,7 @@ function repeatedSubstringPattern(s: string): boolean {
};
```
Swift:
### Swift:
> 前缀表统一减一
```swift
@@ -623,7 +620,7 @@ Swift:
}
```
Rust:
### Rust:
>前缀表统一不减一
```Rust

View File

@@ -142,6 +142,53 @@ class Solution {
return landSum * 4 - cover * 2;
}
}
// 延伸 - 傳統DFS解法(使用visited數組)(遇到邊界 或是 海水 就edge ++
class Solution {
int dir[][] ={
{0, 1},
{0, -1},
{1, 0},
{-1, 0}
};
boolean visited[][];
int res = 0;
public int islandPerimeter(int[][] grid) {
int row = grid.length;
int col = grid[0].length;
visited = new boolean[row][col];
int result = 0;
for(int i = 0; i < row; i++){
for(int j = 0; j < col; j++){
if(visited[i][j] == false && grid[i][j] == 1)
result += dfs(grid, i, j);
}
}
return result;
}
private int dfs(int[][] grid, int x, int y){
//如果遇到 邊界x < 0 || y < 0 || x >= grid.length || y >= grid[0].length或是 遇到海水(grid[x][y] == 0)就return 1edge + 1
if(x < 0 || y < 0 || x >= grid.length || y >= grid[0].length || grid[x][y] == 0)
return 1;
//如果該地已經拜訪過就return 0 避免重複計算
if(visited[x][y])
return 0;
int temp = 0;
visited[x][y] = true;
for(int i = 0; i < 4; i++){
int nextX = x + dir[i][0];
int nextY = y + dir[i][1];
//用temp 把edge存起來
temp +=dfs(grid, nextX, nextY);
}
return temp;
}
}
```
Python

View File

@@ -23,9 +23,9 @@
* 数组中的整数范围是 [-100,100]。
* 给定数组中可能包含重复数字,相等的数字应该被视为递增的一种情况。
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[回溯算法精讲,树层去重与树枝去重 | LeetCode491.递增子序列](https://www.bilibili.com/video/BV1EG4y1h78v/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[回溯算法精讲,树层去重与树枝去重 | LeetCode491.递增子序列](https://www.bilibili.com/video/BV1EG4y1h78v/),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -619,4 +619,3 @@ object Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -292,6 +292,85 @@ class Solution {
}
```
易于理解的二维数组版本:
```java
class Solution {
public int findTargetSumWays(int[] nums, int target) {
// 01背包应用之“有多少种不同的填满背包最大容量的方法“
// 易于理解的二维数组解法及详细注释
int sum = 0;
for(int i = 0; i < nums.length; i++) {
sum += nums[i];
}
// 注意nums[i] >= 0的题目条件意味着sum也是所有nums[i]的绝对值之和
// 这里保证了sum + target一定是大于等于零的也就是left大于等于零毕竟我们定义left大于right
if(sum < Math.abs(target)){
return 0;
}
// 利用二元一次方程组将left用target和sum表示出来替换掉right组合详见代码随想录对此题的分析
// 如果所求的left数组和为小数则作为整数数组的nums里的任何元素自然是没有办法凑出这个小数的
if((sum + target) % 2 != 0) {
return 0;
}
int left = (sum + target) / 2;
// dp[i][j]遍历到数组第i个数时 left为j时的能装满背包的方法总数
int[][] dp = new int[nums.length][left + 1];
// 初始化最上行dp[0][j])当nums[0] == j时注意nums[0]和j都一定是大于等于零的因此不需要判断等于-j时的情况有唯一一种取法可取到jdp[0][j]此时等于1
// 其他情况dp[0][j] = 0
// java整数数组默认初始值为0
for(int j = 0; j <= left; j++) {
if(nums[0] == j) {
dp[0][j] = 1;
}
}
// 初始化最左列dp[i][0])
// 当从nums数组的索引0到i的部分有n个0时n > 0)每个0可以取+/-因此有2的n次方中可以取到j = 0的方案
// n = 0说明当前遍历到的数组部分没有0全为正数因此只有一种方案可以取到j = 0就是所有数都不取
int numZeros = 0;
for(int i = 0; i < nums.length; i++) {
if(nums[i] == 0) {
numZeros++;
}
dp[i][0] = (int) Math.pow(2, numZeros);
}
// 递推公式分析:
// 当nums[i] > j时这时候nums[i]一定不能取所以是dp[i - 1][j]种方案数
// nums[i] <= j时num[i]可取可不取因此方案数是dp[i - 1][j] + dp[i - 1][j - nums[i]]
// 由递推公式可知先遍历i或j都可
for(int i = 1; i < nums.length; i++) {
for(int j = 1; j <= left; j++) {
if(nums[i] > j) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = dp[i - 1][j] + dp[i - 1][j - nums[i]];
}
}
}
// 打印dp数组
// for(int i = 0; i < nums.length; i++) {
// for(int j = 0; j <= left; j++) {
// System.out.print(dp[i][j] + " ");
// }
// System.out.println("");
// }
return dp[nums.length - 1][left];
}
}
```
### Python
回溯版
```python

View File

@@ -33,20 +33,20 @@
进阶:你可以不使用额外的空间吗?(假设由递归产生的隐式调用栈的开销不被计算在内)
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[不仅双指针,还有代码技巧可以惊艳到你! | LeetCode501.二叉搜索树中的众数](https://www.bilibili.com/video/BV1fD4y117gp),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[不仅双指针,还有代码技巧可以惊艳到你! | LeetCode501.二叉搜索树中的众数](https://www.bilibili.com/video/BV1fD4y117gp),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
这道题目呢,递归法我从两个维度来讲。
首先如果不是二叉搜索树的话,应该怎么解题,是二叉搜索树,又应该如何解题,两种方式做一个比较,可以加深大家对二叉树的理解。
## 递归法
### 递归法
### 如果不是二叉搜索树
#### 如果不是二叉搜索树
如果不是二叉搜索树最直观的方法一定是把这个树都遍历了用map统计频率把频率排个序最后取前面高频的元素的集合。
@@ -140,7 +140,7 @@ public:
**所以如果本题没有说是二叉搜索树的话,那么就按照上面的思路写!**
### 是二叉搜索树
#### 是二叉搜索树
**既然是搜索树,它中序遍历就是有序的**
@@ -271,7 +271,7 @@ public:
```
## 迭代法
### 迭代法
只要把中序遍历转成迭代,中间节点的处理逻辑完全一样。
@@ -326,7 +326,7 @@ public:
};
```
# 总结
## 总结
本题在递归法中,我给出了如果是普通二叉树,应该怎么求众数。
@@ -345,10 +345,10 @@ public:
> **需要强调的是 leetcode上的耗时统计是非常不准确的看个大概就行一样的代码耗时可以差百分之50以上**所以leetcode的耗时统计别太当回事知道理论上的效率优劣就行了。
# 其他语言版本
## 其他语言版本
## Java
### Java
暴力法
@@ -472,7 +472,7 @@ class Solution {
}
}
```
一迭代法
一迭代法
```Java
class Solution {
public int[] findMode(TreeNode root) {
@@ -526,7 +526,7 @@ class Solution {
```
## Python
### Python
递归法(版本一)利用字典
@@ -640,7 +640,7 @@ class Solution:
return result
```
## Go
### Go
计数法,不使用额外空间,利用二叉树性质,中序遍历
```go
@@ -676,7 +676,7 @@ func findMode(root *TreeNode) []int {
}
```
## JavaScript
### JavaScript
使用额外空间map的方法
```javascript
@@ -753,7 +753,7 @@ var findMode = function(root) {
};
```
## TypeScript
### TypeScript
> 辅助Map法
@@ -852,7 +852,7 @@ function findMode(root: TreeNode | null): number[] {
};
```
## Scala
### Scala
暴力:
```scala
@@ -923,7 +923,7 @@ object Solution {
}
```
## rust
### Rust
递归:
@@ -1015,3 +1015,4 @@ pub fn find_mode(root: Option<Rc<RefCell<TreeNode>>>) -> Vec<i32> {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -20,9 +20,9 @@
![513.找树左下角的值1](https://code-thinking-1253855093.file.myqcloud.com/pics/20210204153017586.png)
## 视频讲解
## 算法公开课
**《代码随想录》算法视频公开课:[怎么找二叉树的左下角? 递归中又带回溯了,怎么办?| LeetCode513.找二叉树左下角的值](https://www.bilibili.com/video/BV1424y1Z7pn),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[怎么找二叉树的左下角? 递归中又带回溯了,怎么办?| LeetCode513.找二叉树左下角的值](https://www.bilibili.com/video/BV1424y1Z7pn),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -614,7 +614,7 @@ object Solution {
}
```
### rust
### Rust
**层序遍历**
@@ -689,3 +689,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -19,12 +19,12 @@
提示:树中至少有 2 个节点。
# 视频讲解
## 算法公开课
**《代码随想录》算法视频公开课:[二叉搜索树中,需要掌握如何双指针遍历!| LeetCode530.二叉搜索树的最小绝对差](https://www.bilibili.com/video/BV1DD4y11779),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[二叉搜索树中,需要掌握如何双指针遍历!| LeetCode530.二叉搜索树的最小绝对差](https://www.bilibili.com/video/BV1DD4y11779),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
题目中要求在二叉搜索树上任意两节点的差的绝对值的最小值。
@@ -32,7 +32,7 @@
遇到在二叉搜索树上求什么最值啊,差值之类的,就把它想成在一个有序数组上求最值,求差值,这样就简单多了。
## 递归
### 递归
那么二叉搜索树采用中序遍历,其实就是一个有序数组。
@@ -102,7 +102,7 @@ public:
是不是看上去也并不复杂!
## 迭代
### 迭代
看过这两篇[二叉树:听说递归能做的,栈也能做!](https://programmercarl.com/二叉树的迭代遍历.html)[二叉树:前中后序迭代方式的写法就不能统一一下么?](https://programmercarl.com/二叉树的统一迭代法.html)文章之后,不难写出两种中序遍历的迭代法。
@@ -135,7 +135,7 @@ public:
};
```
# 总结
## 总结
**遇到在二叉搜索树上求什么最值,求差值之类的,都要思考一下二叉搜索树可是有序的,要利用好这一特点。**
@@ -145,10 +145,10 @@ public:
# 其他语言版本
## 其他语言版本
## Java
### Java
递归
```java
@@ -235,7 +235,7 @@ class Solution {
}
}
```
## Python
### Python
递归法(版本一)利用中序递增,结合数组
```python
@@ -313,7 +313,7 @@ class Solution:
```
## Go
### Go
中序遍历,然后计算最小差值
```go
@@ -340,7 +340,7 @@ func getMinimumDifference(root *TreeNode) int {
}
```
## JavaScript
### JavaScript
递归 先转换为有序数组
```javascript
/**
@@ -415,7 +415,7 @@ var getMinimumDifference = function(root) {
}
```
## TypeScript
### TypeScript
> 辅助数组解决
@@ -482,7 +482,7 @@ function getMinimumDifference(root: TreeNode | null): number {
};
```
## Scala
### Scala
构建二叉树的有序数组:
@@ -561,7 +561,7 @@ object Solution {
}
```
## rust
### Rust
构建二叉树的有序数组:
@@ -652,3 +652,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -44,11 +44,11 @@
* 树中的所有值 互不相同 。
* 给定的树为二叉搜索树。
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[普大喜奔!二叉树章节已全部更完啦!| LeetCode538.把二叉搜索树转换为累加树](https://www.bilibili.com/video/BV1d44y1f7wP?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[普大喜奔!二叉树章节已全部更完啦!| LeetCode538.把二叉搜索树转换为累加树](https://www.bilibili.com/video/BV1d44y1f7wP?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
一看到累加树,相信很多小伙伴都会疑惑:如何累加?遇到一个节点,然后再遍历其他节点累加?怎么一想这么麻烦呢。
@@ -64,7 +64,7 @@
那么知道如何遍历这个二叉树,也就迎刃而解了,**从树中可以看出累加的顺序是右中左,所以我们需要反中序遍历这个二叉树,然后顺序累加就可以了**。
## 递归
### 递归
遍历顺序如图所示:
@@ -131,7 +131,7 @@ public:
};
```
## 迭代法
### 迭代法
迭代法其实就是中序模板题了,在[二叉树:前中后序迭代法](https://programmercarl.com/二叉树的迭代遍历.html)和[二叉树:前中后序统一方式迭代法](https://programmercarl.com/二叉树的统一迭代法.html)可以选一种自己习惯的写法。
@@ -166,17 +166,17 @@ public:
};
```
# 总结
## 总结
经历了前面各种二叉树增删改查的洗礼之后,这道题目应该比较简单了。
**好了,二叉树已经接近尾声了,接下来就是要对二叉树来一个大总结了**
# 其他语言版本
## 其他语言版本
## Java
### Java
**递归**
```Java
@@ -237,7 +237,7 @@ class Solution {
}
```
## Python
### Python
递归法(版本一)
```python
# Definition for a binary tree node.
@@ -318,7 +318,7 @@ class Solution:
self.traversal(root)
return root
```
```
迭代法(版本二)
```python
class Solution:
@@ -338,9 +338,9 @@ class Solution:
pre = cur.val
cur =cur.left
return root
```
```
## Go
### Go
弄一个sum暂存其和值
```go
@@ -362,7 +362,7 @@ func traversal(cur *TreeNode) {
}
```
## JavaScript
### JavaScript
递归
```javascript
@@ -401,7 +401,7 @@ var convertBST = function (root) {
};
```
##C
### C
递归
```c
@@ -422,7 +422,7 @@ struct TreeNode* convertBST(struct TreeNode* root){
}
```
## TypeScript
### TypeScript
> 递归法
@@ -462,7 +462,7 @@ function convertBST(root: TreeNode | null): TreeNode | null {
};
```
## Scala
### Scala
```scala
object Solution {
@@ -481,7 +481,7 @@ object Solution {
}
```
## rust
### Rust
递归:
@@ -535,3 +535,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -23,9 +23,11 @@
输入: s = "abcdefg", k = 2
输出: "bacdfeg"
# 思路
## 算法公开课
针对本题,我录制了视频讲解[字符串操作进阶! | LeetCode541. 反转字符串II](https://www.bilibili.com/video/BV1dT411j7NN)结合本题解一起看,事半功倍!
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[字符串操作进阶! | LeetCode541. 反转字符串II](https://www.bilibili.com/video/BV1dT411j7NN)相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
这道题目其实也是模拟,实现题目中规定的反转规则就可以了。
@@ -42,8 +44,6 @@
那么这里具体反转的逻辑我们要不要使用库函数呢其实用不用都可以使用reverse来实现反转也没毛病毕竟不是解题关键部分。
# C++代码
使用C++库函数reverse的版本如下
```CPP
@@ -129,7 +129,7 @@ public:
## 其他语言版本
C
### C
```c
char * reverseStr(char * s, int k){
@@ -152,7 +152,7 @@ char * reverseStr(char * s, int k){
}
```
Java
### Java
```Java
//解法一
@@ -256,7 +256,8 @@ class Solution {
}
}
```
Python
### Python
```python
class Solution:
def reverseStr(self, s: str, k: int) -> str:
@@ -281,7 +282,7 @@ class Solution:
return ''.join(res)
```
Python3 (v2):
### Python3 (v2):
```python
class Solution:
@@ -296,7 +297,7 @@ class Solution:
return s
```
Go
### Go
```go
func reverseStr(s string, k int) string {
@@ -325,7 +326,7 @@ func reverse(b []byte) {
}
```
javaScript:
### JavaScript:
```js
@@ -346,7 +347,7 @@ var reverseStr = function(s, k) {
```
TypeScript
### TypeScript
```typescript
function reverseStr(s: string, k: number): string {
@@ -368,7 +369,7 @@ function reverseStr(s: string, k: number): string {
};
```
Swift:
### Swift:
```swift
func reverseStr(_ s: String, _ k: Int) -> String {
@@ -388,7 +389,8 @@ func reverseStr(_ s: String, _ k: Int) -> String {
}
```
C#
### C#
```csharp
public class Solution
{
@@ -403,7 +405,7 @@ public class Solution
}
}
```
Scala:
### Scala:
版本一: (正常解法)
```scala
@@ -469,7 +471,7 @@ object Solution {
}
```
Rust:
### Rust:
```Rust
impl Solution {
@@ -503,4 +505,3 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -19,9 +19,9 @@
注意: 合并必须从两个树的根节点开始。
# 视频讲解
# 算法公开课
**《代码随想录》算法视频公开课:[一起操作两个二叉树?有点懵!| LeetCode617.合并二叉树](https://www.bilibili.com/video/BV1m14y1Y7JK),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[一起操作两个二叉树?有点懵!| LeetCode617.合并二叉树](https://www.bilibili.com/video/BV1m14y1Y7JK),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -164,7 +164,7 @@ public:
};
```
## 迭代法
### 迭代法
使用迭代法,如何同时处理两棵树呢?
@@ -716,7 +716,7 @@ object Solution {
}
```
### rust
### Rust
递归:
@@ -793,4 +793,3 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -304,7 +304,38 @@ class Solution {
}
}
```
LeetCode 5. Longest Palindromic Substring(LeetCode 647. 同一題的思路改一下、加一點就能通過LeetCode 5)
```java
class Solution {
public String longestPalindrome(String s) {
//題目要求要return 最長的回文連續子串,故需要記錄當前最長的連續回文子串長度、最終起點、最終終點。
int finalStart = 0;
int finalEnd = 0;
int finalLen = 0;
char[] chars = s.toCharArray();
int len = chars.length;
boolean[][] dp = new boolean[len][len];
for (int i = len - 1; i >= 0; i--) {
for (int j = i; j < len; j++) {
if (chars[i] == chars[j] && (j - i <= 1 || dp[i + 1][j - 1]))
dp[i][j] = true;
//和LeetCode 647差別就在這個if statement。
//如果當前[i, j]範圍內的substring是回文子串(dp[i][j]) 且(&&) 長度大於當前要記錄的最終長度(j - i + 1 > finalLen)
//我們就更新 當前最長的連續回文子串長度、最終起點、最終終點
if (dp[i][j] && j - i + 1 > finalLen) {
finalLen = j - i + 1;
finalStart = i;
finalEnd = j;
}
}
}
//String.substring這個method的用法是[起點, 終點),包含起點,不包含終點(左閉右開區間),故終點 + 1。
return s.substring(finalStart, finalEnd + 1);
}
}
```
Python

View File

@@ -25,9 +25,9 @@
给定的数组的大小在 [1, 1000] 之间。
## 视频讲解
## 算法公开课
**《代码随想录》算法视频公开课:[又是构造二叉树,又有很多坑!| LeetCode654.最大二叉树](https://www.bilibili.com/video/BV1MG411G7ox),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[又是构造二叉树,又有很多坑!| LeetCode654.最大二叉树](https://www.bilibili.com/video/BV1MG411G7ox),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -310,7 +310,7 @@ class Solution:
def constructMaximumBinaryTree(self, nums: List[int]) -> TreeNode:
return self.traversal(nums, 0, len(nums))
```
```
(版本三) 使用切片
@@ -587,3 +587,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -20,17 +20,17 @@
![669.修剪二叉搜索树1](https://code-thinking-1253855093.file.myqcloud.com/pics/20201014173219142.png)
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[你修剪的方式不对,我来给你纠正一下!| LeetCode669. 修剪二叉搜索树](https://www.bilibili.com/video/BV17P41177ud?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[你修剪的方式不对,我来给你纠正一下!| LeetCode669. 修剪二叉搜索树](https://www.bilibili.com/video/BV17P41177ud?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
相信看到这道题目大家都感觉是一道简单题事实上leetcode上也标明是简单
但还真的不简单!
## 递归法
### 递归法
直接想法就是:递归处理,然后遇到 `root->val < low || root->val > high` 的时候直接return NULL一波修改赶紧利落。
@@ -188,7 +188,7 @@ public:
只看代码,其实不太好理解节点是如何移除的,这一块大家可以自己再模拟模拟!
## 迭代法
### 迭代法
因为二叉搜索树的有序性,不需要使用栈模拟递归的过程。
@@ -233,7 +233,7 @@ public:
};
```
# 总结
## 总结
修剪二叉搜索树其实并不难,但在递归法中大家可看出我费了很大的功夫来讲解如何删除节点的,这个思路其实是比较绕的。
@@ -243,10 +243,10 @@ public:
本题我依然给出递归法和迭代法,初学者掌握递归就可以了,如果想进一步学习,就把迭代法也写一写。
# 其他语言版本
## 其他语言版本
## Java
### Java
**递归**
@@ -311,7 +311,7 @@ class Solution {
````
## Python
### Python
递归法版本一
```python
@@ -381,7 +381,7 @@ class Solution:
```
## Go
### Go
```go
// 递归
@@ -436,7 +436,7 @@ func trimBST(root *TreeNode, low int, high int) *TreeNode {
```
## JavaScript版本
### JavaScript
迭代:
@@ -492,7 +492,7 @@ var trimBST = function (root,low,high) {
}
```
## TypeScript
### TypeScript
> 递归法
@@ -540,7 +540,7 @@ function trimBST(root: TreeNode | null, low: number, high: number): TreeNode | n
};
```
## Scala
### Scala
递归法:
@@ -557,7 +557,7 @@ object Solution {
}
```
## rust
### Rust
// 递归
@@ -590,3 +590,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -4,11 +4,8 @@
</a>
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
# 684.冗余连接
[力扣题目链接](https://leetcode.cn/problems/redundant-connection/)
树可以看成是一个连通且 无环 的 无向 图。
@@ -78,7 +75,9 @@ void join(int u, int v) {
2. 将两个节点接入到同一个集合函数join(int u, int v)将两个节点连在同一个根节点上
3. 判断两个节点是否在同一个集合函数isSame(int u, int v)就是判断两个节点是不是同一个根节点
简单介绍并查集之后我们再来看一下这道题目
如果还不了解并查集可以看这里[并查集理论基础](https://programmercarl.com/图论并查集理论基础.html)
我们再来看一下这道题目
题目说是无向图返回一条可以删去的边使得结果图是一个有着N个节点的树只有一个根节点)。
@@ -92,7 +91,6 @@ void join(int u, int v) {
节点A 和节点 B 不在同一个集合那么就可以将两个 节点连在一起
如果题目中说如果有多个答案则返回二维数组中最前出现的边 那我们就要 从后向前遍历每一条边了
如果边的两个节点已经出现在同一个集合里说明着边的两个节点已经连在一起了再加入这条边一定就出现环了
@@ -151,8 +149,6 @@ public:
可以看出主函数的代码很少就判断一下边的两个节点在不在同一个集合就可以了
这里对并查集就不展开过多的讲解了翻到了自己十年前写过了一篇并查集的文章[并查集学习](https://blog.csdn.net/youngyangyang04/article/details/6447435)哈哈那时候还太年轻写不咋地有空我会重写并查集基础篇
# 其他语言版本

View File

@@ -104,7 +104,7 @@ if (vec.size() > 0) {
}
```
在来看情况三明确没有入度为2的情况那么一定有向环,找到构成环的边就是要删除的边。
在来看情况三明确没有入度为2的情况那么一定有向环找到构成环的边就是要删除的边。
可以定义一个函数,代码如下:
@@ -122,7 +122,7 @@ vector<int> getRemoveEdge(const vector<vector<int>>& edges)
**因为如果两个点所在的边在添加图之前如果就可以在并查集里找到了相同的根,那么这条边添加上之后 这个图一定不是树了**
这里对并查集就不展开过多的讲解了,翻到了自己十年前写过了一篇并查集的文章[并查集学习](https://blog.csdn.net/youngyangyang04/article/details/6447435),哈哈,那时候还太年轻,写不咋地,有空我会重写一篇!
如果还不了解并查集,可以看这里:[并查集理论基础](https://programmercarl.com/图论并查集理论基础.html)
本题C++代码如下:(详细注释了)

View File

@@ -189,6 +189,135 @@ public:
```
# 其它语言版本
## Java
### DFS
```java
// DFS
class Solution {
int[][] dir = {
{0, 1}, //right
{1, 0}, //down
{0, -1}, //left
{-1, 0} //up
};
boolean visited[][];
int count;
public int maxAreaOfIsland(int[][] grid) {
int res = 0;
visited = new boolean[grid.length][grid[0].length];
for(int i = 0; i < grid.length; i++){
for(int j = 0; j < grid[0].length; j++){
if(visited[i][j] == false && grid[i][j] == 1){
count = 0;
dfs(grid, i, j);
res = Math.max(res, count);
}
}
}
return res;
}
private void dfs(int[][] grid, int x, int y){
if(visited[x][y] == true || grid[x][y] == 0)
return;
visited[x][y] = true;
count++;
for(int i = 0; i < 4; i++){
int nextX = x + dir[i][0];
int nextY = y + dir[i][1];
if(nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length)
continue;
dfs(grid, nextX, nextY);
}
}
}
```
### BFS
```java
//BFS
class Solution {
int[][] dir = {
{0, 1}, {1, 0}, {0, -1}, {-1, 0}
};
int count;
boolean visited[][];
public int maxAreaOfIsland(int[][] grid) {
int res = 0;
visited = new boolean[grid.length][grid[0].length];
for(int i = 0; i < grid.length; i++){
for(int j = 0; j < grid[0].length; j++){
if(visited[i][j] == false && grid[i][j] == 1){
count = 0;
bfs(grid, i, j);
res = Math.max(res, count);
}
}
}
return res;
}
private void bfs(int[][] grid, int x, int y){
Queue<Integer> que = new LinkedList<>();
que.offer(x);
que.offer(y);
visited[x][y] = true;
count++;
while(!que.isEmpty()){
int currX = que.poll();
int currY = que.poll();
for(int i = 0; i < 4; i++){
int nextX = currX + dir[i][0];
int nextY = currY + dir[i][1];
if(nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length)
continue;
if(visited[nextX][nextY] == false && grid[nextX][nextY] == 1){
que.offer(nextX);
que.offer(nextY);
visited[nextX][nextY] = true;
count++;
}
}
}
}
}
```
### DFS 優化(遇到島嶼後,就把他淹沒)
```java
//这里使用深度优先搜索 DFS 来完成本道题目。我们使用 DFS 计算一个岛屿的面积,同时维护计算过的最大的岛屿面积。同时,为了避免对岛屿重复计算,我们在 DFS 的时候对岛屿进行 “淹没” 操作,即将岛屿所占的地方置为 0。
public int maxAreaOfIsland(int[][] grid) {
int res = 0;
for(int i = 0;i < grid.length;i++){
for(int j = 0;j < grid[0].length;j++){
//每遇到一个岛屿就计算这个岛屿的面积同时”淹没“这个岛屿
if(grid[i][j] == 1){
//每次计算一个岛屿的面积都要与res比较维护最大的岛屿面积作为最后的答案
res = Math.max(res,dfs(grid,i,j));
}
}
}
return res;
}
public int dfs(int[][] grid,int i,int j){
//搜索边界ij超过grid的范围或者当前元素为0即当前所在的地方已经是海洋
if(i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] == 0) return 0;
//淹没土地,防止后续被重复计算
grid[i][j] = 0;
//递归的思路:要求当前土地(i,j)所在的岛屿的面积则等于1加上下左右相邻的土地的总面积
return 1 + dfs(grid,i - 1,j) +
dfs(grid,i + 1,j) +
dfs(grid,i,j + 1) +
dfs(grid,i,j - 1);
}
```
## Python
### BFS
@@ -261,39 +390,6 @@ class Solution:
if 0 <= new_x < len(grid) and 0 <= new_y < len(grid[0]):
self.dfs(grid, visited, new_x, new_y)
```
## Java
这里使用深度优先搜索 DFS 来完成本道题目。我们使用 DFS 计算一个岛屿的面积,同时维护计算过的最大的岛屿面积。同时,为了避免对岛屿重复计算,我们在 DFS 的时候对岛屿进行 “淹没” 操作,即将岛屿所占的地方置为 0。
```java
public int maxAreaOfIsland(int[][] grid) {
int res = 0;
for(int i = 0;i < grid.length;i++){
for(int j = 0;j < grid[0].length;j++){
//每遇到一个岛屿就计算这个岛屿的面积同时”淹没“这个岛屿
if(grid[i][j] == 1){
//每次计算一个岛屿的面积都要与res比较维护最大的岛屿面积作为最后的答案
res = Math.max(res,dfs(grid,i,j));
}
}
}
return res;
}
public int dfs(int[][] grid,int i,int j){
//搜索边界ij超过grid的范围或者当前元素为0即当前所在的地方已经是海洋
if(i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] == 0) return 0;
//淹没土地,防止后续被重复计算
grid[i][j] = 0;
//递归的思路:要求当前土地(i,j)所在的岛屿的面积则等于1加上下左右相邻的土地的总面积
return 1 + dfs(grid,i - 1,j) +
dfs(grid,i + 1,j) +
dfs(grid,i,j + 1) +
dfs(grid,i,j - 1);
}
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>

View File

@@ -18,9 +18,9 @@
在上述示例中,如果要找的值是 5但因为没有节点值为 5我们应该返回 NULL。
# 视频讲解
## 算法公开课
**《代码随想录》算法视频公开课:[不愧是搜索树,这次搜索有方向了!| LeetCode700.二叉搜索树中的搜索](https://www.bilibili.com/video/BV1wG411g7sF),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[不愧是搜索树,这次搜索有方向了!| LeetCode700.二叉搜索树中的搜索](https://www.bilibili.com/video/BV1wG411g7sF),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
## 思路
@@ -415,7 +415,7 @@ object Solution {
}
```
### rust
### Rust
递归:
@@ -469,3 +469,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -23,11 +23,11 @@
* -10^8 <= val <= 10^8
* 新值和原始二叉搜索树中的任意节点值都不同
# 算法公开课
## 算法公开课
**《代码随想录》算法视频公开课:[原来这么简单? | LeetCode701.二叉搜索树中的插入操作](https://www.bilibili.com/video/BV1Et4y1c78Y?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[原来这么简单? | LeetCode701.二叉搜索树中的插入操作](https://www.bilibili.com/video/BV1Et4y1c78Y?share_source=copy_web),相信结合视频在看本篇题解,更有助于大家对本题的理解**。
# 思路
## 思路
这道题目其实是一道简单题目,**但是题目中的提示:有多种有效的插入方式,还可以重构二叉搜索树,一下子吓退了不少人**,瞬间感觉题目复杂了很多。
@@ -43,7 +43,7 @@
接下来就是遍历二叉搜索树的过程了。
## 递归
### 递归
递归三部曲:
@@ -165,7 +165,7 @@ public:
**网上千篇一律的代码,可能会误导大家认为通过递归函数返回节点 这样的写法是天经地义,其实这里是有优化的!**
## 迭代
### 迭代
再来看看迭代法,对二叉搜索树迭代写法不熟悉,可以看这篇:[二叉树:二叉搜索树登场!](https://programmercarl.com/0700.二叉搜索树中的搜索.html)
@@ -198,7 +198,7 @@ public:
};
```
# 总结
## 总结
首先在二叉搜索树中的插入操作,大家不用恐惧其重构搜索树,其实根本不用重构。
@@ -207,9 +207,9 @@ public:
最后依然给出了迭代的方法,迭代的方法就需要记录当前遍历节点的父节点了,这个和没有返回值的递归函数实现的代码逻辑是一样的。
# 其他语言版本
## 其他语言版本
## Java
### Java
```java
class Solution {
@@ -254,7 +254,7 @@ class Solution {
}
```
-----
## Python
### Python
递归法(版本一)
```python
@@ -371,7 +371,7 @@ class Solution:
```
-----
## Go
### Go
递归法
@@ -417,7 +417,7 @@ func insertIntoBST(root *TreeNode, val int) *TreeNode {
}
```
-----
## JavaScript
### JavaScript
有返回值的递归写法
@@ -530,7 +530,7 @@ var insertIntoBST = function (root, val) {
};
```
## TypeScript
### TypeScript
> 递归-有返回值
@@ -595,7 +595,7 @@ function insertIntoBST(root: TreeNode | null, val: number): TreeNode | null {
```
## Scala
### Scala
递归:
@@ -632,7 +632,7 @@ object Solution {
}
```
### rust
### Rust
迭代:
@@ -697,3 +697,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -5,7 +5,7 @@
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
## 704. 二分查找
# 704. 二分查找
[力扣题目链接](https://leetcode.cn/problems/binary-search/)
@@ -33,11 +33,13 @@
* n 将在 [1, 10000]之间。
* nums 的每个元素都将在 [-9999, 9999]之间。
## 算法公开课
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[手把手带你撕出正确的二分法](https://www.bilibili.com/video/BV1fA4y1o715),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
为了易于大家理解,我还录制了视频,可以看这里:[B站手把手带你撕出正确的二分法](https://www.bilibili.com/video/BV1fA4y1o715)
**这道题目的前提是数组为有序数组**,同时题目还强调**数组中无重复元素**,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的,这些都是使用二分法的前提条件,当大家看到题目描述满足如上条件的时候,可要想一想是不是可以用二分法了。
二分查找涉及的很多的边界条件,逻辑比较简单,但就是写不好。例如到底是 `while(left < right)` 还是 `while(left <= right)`,到底是`right = middle`呢,还是要`right = middle - 1`呢?
@@ -158,7 +160,7 @@ public:
## 其他语言版本
**Java**
### **Java**
(版本一)左闭右闭区间
@@ -204,7 +206,7 @@ class Solution {
}
```
**Python**
### **Python**
(版本一)左闭右闭区间
@@ -244,7 +246,7 @@ class Solution:
return -1 # 未找到目标值
```
**Go**
### **Go**
(版本一)左闭右闭区间
@@ -286,7 +288,7 @@ func search(nums []int, target int) int {
}
```
**JavaScript:**
### **JavaScript:**
(版本一)左闭右闭区间 [left, right]
```js
@@ -343,7 +345,7 @@ var search = function(nums, target) {
};
```
**TypeScript**
### **TypeScript**
(版本一)左闭右闭区间
@@ -385,7 +387,7 @@ function search(nums: number[], target: number): number {
};
```
**Ruby:**
### **Ruby:**
```ruby
# (版本一)左闭右闭区间
@@ -423,7 +425,7 @@ def search(nums, target)
end
```
**Swift:**
### **Swift:**
```swift
// (版本一)左闭右闭区间
@@ -477,7 +479,7 @@ func search(nums: [Int], target: Int) -> Int {
```
**Rust:**
### **Rust:**
```rust
# (版本一)左闭右闭区间
@@ -521,7 +523,8 @@ impl Solution {
}
```
**C:**
### **C:**
```c
// (版本一) 左闭右闭区间 [left, right]
int search(int* nums, int numsSize, int target){
@@ -573,7 +576,8 @@ int search(int* nums, int numsSize, int target){
}
```
**PHP:**
### **PHP:**
```php
// 左闭右闭区间
class Solution {
@@ -605,7 +609,8 @@ class Solution {
}
```
**C#:**
### **C#:**
```csharp
//左闭右闭
public class Solution {
@@ -650,7 +655,8 @@ public class Solution{
}
```
**Kotlin:**
### **Kotlin:**
```kotlin
class Solution {
fun search(nums: IntArray, target: Int): Int {
@@ -680,9 +686,8 @@ class Solution {
}
```
### **Kotlin:**
**Kotlin:**
```Kotlin
// (版本一)左闭右开区间
class Solution {
@@ -713,7 +718,7 @@ class Solution {
}
}
```
**Scala:**
### **Scala:**
(版本一)左闭右闭区间
```scala

View File

@@ -24,9 +24,13 @@
![707示例](https://code-thinking-1253855093.file.myqcloud.com/pics/20200814200558953.png)
# 思路
为了方便大家理解,我特意录制了视频:[帮你把链表操作学个通透LeetCode707.设计链表](https://www.bilibili.com/video/BV1FU4y1X7WD),结合视频在看本题解,事半功倍。
## 算法公开课
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[帮你把链表操作学个通透LeetCode707.设计链表](https://www.bilibili.com/video/BV1FU4y1X7WD),相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 思路
如果对链表的基础知识还不太懂,可以看这篇文章:[关于链表,你该了解这些!](https://programmercarl.com/链表理论基础.html)
@@ -54,8 +58,6 @@
下面采用的设置一个虚拟头结点(这样更方便一些,大家看代码就会感受出来)。
## 代码
```CPP
class MyLinkedList {
public:
@@ -163,7 +165,8 @@ private:
## 其他语言版本
C:
### C:
```C
typedef struct MyLinkedList {
int val;
@@ -287,7 +290,8 @@ void myLinkedListFree(MyLinkedList* obj) {
*/
```
Java
### Java
```Java
//单链表
class ListNode {
@@ -483,7 +487,8 @@ class MyLinkedList {
*/
```
Python
### Python
```python
版本一单链表法
class ListNode:
@@ -657,7 +662,7 @@ class MyLinkedList:
# obj.deleteAtIndex(index)
```
Go
### Go
```go
//单链表实现
@@ -911,7 +916,7 @@ func (this *MyLinkedList) DeleteAtIndex(index int) {
}
```
javaScript:
### JavaScript:
```js
@@ -1051,7 +1056,8 @@ MyLinkedList.prototype.deleteAtIndex = function(index) {
*/
```
TypeScript:
### TypeScript:
```TypeScript
class ListNode {
public val: number;
@@ -1169,7 +1175,8 @@ class MyLinkedList {
}
```
Kotlin:
### Kotlin:
```kotlin
class MyLinkedList {
@@ -1237,8 +1244,7 @@ class MyLinkedList {
}
```
Swift:
### Swift:
```swift
class MyLinkedList {
@@ -1319,7 +1325,8 @@ class MyLinkedList {
}
```
Scala:
### Scala:
```scala
class ListNode(_x: Int = 0, _next: ListNode = null) {
var next: ListNode = _next
@@ -1389,7 +1396,7 @@ class MyLinkedList() {
}
```
Rust:
### Rust:
```rust
#[derive(Debug)]
@@ -1482,4 +1489,3 @@ impl MyLinkedList {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -270,18 +270,29 @@ impl Solution {
**动态规划**
```Rust
impl Solution {
fn max(a: i32, b: i32) -> i32 {
if a > b { a } else { b }
}
pub fn max_profit(prices: Vec<i32>, fee: i32) -> i32 {
let n = prices.len();
let mut dp = vec![vec![0; 2]; n];
dp[0][0] -= prices[0];
for i in 1..n {
dp[i][0] = Self::max(dp[i - 1][0], dp[i - 1][1] - prices[i]);
dp[i][1] = Self::max(dp[i - 1][1], dp[i - 1][0] + prices[i] - fee);
let mut dp = vec![vec![0; 2]; prices.len()];
dp[0][0] = -prices[0];
for (i, &p) in prices.iter().enumerate().skip(1) {
dp[i][0] = dp[i - 1][0].max(dp[i - 1][1] - p);
dp[i][1] = dp[i - 1][1].max(dp[i - 1][0] + p - fee);
}
Self::max(dp[n - 1][0], dp[n - 1][1])
dp[prices.len() - 1][1]
}
}
```
**动态规划空间优化**
```rust
impl Solution {
pub fn max_profit(prices: Vec<i32>, fee: i32) -> i32 {
let (mut low, mut res) = (-prices[0], 0);
for p in prices {
low = low.max(res - p);
res = res.max(p + low - fee);
}
res
}
}
```

View File

@@ -13,19 +13,22 @@
给你一个按 非递减顺序 排序的整数数组 nums返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1
输入nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100],排序后,数组变为 [0,1,9,16,100]
* 输入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]
* 输入nums = [-7,-3,2,3,11]
* 输出:[4,9,9,49,121]
# 思路
## 算法公开课
针对本题,我录制了视频讲解[双指针法经典题目!LeetCode:977.有序数组的平方](https://www.bilibili.com/video/BV1QB4y1D7ep)结合本题解一起看,事半功倍!
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[双指针法经典题目!LeetCode:977.有序数组的平方](https://www.bilibili.com/video/BV1QB4y1D7ep)相信结合视频再看本篇题解,更有助于大家对本题的理解**。
## 暴力排序
## 思路
### 暴力排序
最直观的想法,莫过于:每个数平方之后,排个序,美滋滋,代码如下:
@@ -44,7 +47,7 @@ public:
这个时间复杂度是 O(n + nlogn) 可以说是O(nlogn)的时间复杂度,但为了和下面双指针法算法时间复杂度有鲜明对比,我记为 O(n + nlog n)。
## 双指针法
### 双指针法
数组其实是有序的, 只不过负数平方之后可能成为最大数了。
@@ -96,7 +99,8 @@ public:
## 其他语言版本
Java
### Java
```Java
class Solution {
public int[] sortedSquares(int[] nums) {
@@ -138,7 +142,8 @@ class Solution {
}
```
Python
### Python
```Python
版本一双指针法
class Solution:
@@ -173,7 +178,8 @@ class Solution:
return sorted(x*x for x in nums)
```
Go
### Go
```Go
func sortedSquares(nums []int) []int {
n := len(nums)
@@ -193,7 +199,8 @@ func sortedSquares(nums []int) []int {
return ans
}
```
Rust
### Rust:
```rust
impl Solution {
pub fn sorted_squares(nums: Vec<i32>) -> Vec<i32> {
@@ -214,7 +221,8 @@ impl Solution {
}
}
```
Javascript
### Javascript
```Javascript
/**
* @param {number[]} nums
@@ -239,7 +247,7 @@ var sortedSquares = function(nums) {
};
```
Typescript
### Typescript
双指针法:
@@ -274,7 +282,7 @@ function sortedSquares(nums: number[]): number[] {
};
```
Swift:
### Swift:
```swift
func sortedSquares(_ nums: [Int]) -> [Int] {
@@ -302,7 +310,7 @@ func sortedSquares(_ nums: [Int]) -> [Int] {
}
```
Ruby:
### Ruby:
```ruby
def sorted_squares(nums)
@@ -320,8 +328,8 @@ def sorted_squares(nums)
end
```
### C:
C:
```c
int* sortedSquares(int* nums, int numsSize, int* returnSize){
//返回的数组大小就是原数组大小
@@ -354,7 +362,8 @@ int* sortedSquares(int* nums, int numsSize, int* returnSize){
}
```
PHP:
### PHP:
```php
class Solution {
/**
@@ -383,7 +392,7 @@ class Solution {
}
```
Kotlin:
### Kotlin:
双指针法
```kotlin
@@ -434,7 +443,7 @@ class Solution {
}
```
Scala:
### Scala:
双指针:
```scala
@@ -470,7 +479,8 @@ object Solution {
}
```
C#
### C#
```csharp
public class Solution {
public int[] SortedSquares(int[] nums) {
@@ -501,3 +511,4 @@ public class Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -16,6 +16,7 @@
输入words = ["bella","label","roller"]
输出:["e","l","l"]
示例 2
输入words = ["cool","lock","cook"]

View File

@@ -149,7 +149,63 @@ public:
### Java
深度优先遍历版本:
深度优先遍历(没有终止条件 + 空間優化淹沒島嶼沒有使用visited數組)
```java
//DFS
class Solution {
int count = 0;
int[][] dir ={
{0, 1},
{1, 0},
{-1, 0},
{0, -1}
};
private void dfs(int[][] grid, int x, int y){
if(grid[x][y] == 0)
return;
grid[x][y] = 0;
count++;
for(int i = 0; i < 4; i++){
int nextX = x + dir[i][0];
int nextY = y + dir[i][1];
if(nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length)
continue;
dfs(grid, nextX, nextY);
}
}
public int numEnclaves(int[][] grid) {
for(int i = 0; i < grid.length; i++){
if(grid[i][0] == 1)
dfs(grid, i, 0);
if(grid[i][grid[0].length - 1] == 1)
dfs(grid, i, grid[0].length - 1);
}
//初始化的時候j 的上下限有調整過,必免重複操作。
for(int j = 1; j < grid[0].length - 1; j++){
if(grid[0][j] == 1)
dfs(grid, 0, j);
if(grid[grid.length - 1][j] == 1)
dfs(grid, grid.length - 1, j);
}
count = 0;
for(int i = 1; i < grid.length - 1; i++){
for(int j = 1; j < grid[0].length - 1; j++){
if(grid[i][j] == 1)
dfs(grid, i, j);
}
}
return count;
}
}
```
深度优先遍历(没有终止条件)
```java
class Solution {
@@ -206,7 +262,7 @@ class Solution {
}
```
广度优先遍历版本:
广度优先遍历使用visited數組
```java
class Solution {
@@ -269,6 +325,72 @@ class Solution {
}
```
廣度优先遍历(空間優化淹沒島嶼沒有使用visited數組)
```java
//BFS
class Solution {
int count = 0;
int[][] dir ={
{0, 1},
{1, 0},
{-1, 0},
{0, -1}
};
private void bfs(int[][] grid, int x, int y){
Queue<Integer> que = new LinkedList<>();
que.offer(x);
que.offer(y);
count++;
grid[x][y] = 0;
while(!que.isEmpty()){
int currX = que.poll();
int currY = que.poll();
for(int i = 0; i < 4; i++){
int nextX = currX + dir[i][0];
int nextY = currY + dir[i][1];
if(nextX < 0 || nextY < 0 || nextX >= grid.length || nextY >= grid[0].length)
continue;
if(grid[nextX][nextY] == 1){
que.offer(nextX);
que.offer(nextY);
count++;
grid[nextX][nextY] = 0;
}
}
}
}
public int numEnclaves(int[][] grid) {
for(int i = 0; i < grid.length; i++){
if(grid[i][0] == 1)
bfs(grid, i, 0);
if(grid[i][grid[0].length - 1] == 1)
bfs(grid, i, grid[0].length - 1);
}
for(int j = 1; j < grid[0].length; j++){
if(grid[0][j] == 1)
bfs(grid, 0 , j);
if(grid[grid.length - 1][j] == 1)
bfs(grid, grid.length - 1, j);
}
count = 0;
for(int i = 1; i < grid.length - 1; i++){
for(int j = 1; j < grid[0].length - 1; j++){
if(grid[i][j] == 1)
bfs(grid,i ,j);
}
}
return count;
}
}
```
### Python
深度优先遍历

View File

@@ -5,8 +5,6 @@
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
> 匹配问题都是栈的强项
# 1047. 删除字符串中的所有相邻重复项
@@ -30,11 +28,13 @@
* 1 <= S.length <= 20000
* S 仅由小写英文字母组成。
# 思路
## 算法公开课
《代码随想录》算法视频公开课:[栈的好戏还要继续!| LeetCode1047. 删除字符串中的所有相邻重复项](https://www.bilibili.com/video/BV12a411P7mw),相信结合视频看本篇题解,更有助于大家对本题的理解。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[栈的好戏还要继续!| LeetCode1047. 删除字符串中的所有相邻重复项](https://www.bilibili.com/video/BV12a411P7mw),相信结合视频看本篇题解,更有助于大家对本题的理解**
## 正题
## 思路
### 正题
本题要删除相邻相同元素,相对于[20. 有效的括号](https://programmercarl.com/0020.%E6%9C%89%E6%95%88%E7%9A%84%E6%8B%AC%E5%8F%B7.html)来说其实也是匹配问题20. 有效的括号 是匹配左右括号,本题是匹配相邻元素,最后都是做消除的操作。
@@ -105,7 +105,7 @@ public:
* 时间复杂度: O(n)
* 空间复杂度: O(1),返回值不计空间复杂度
## 题外话
### 题外话
这道题目就像是我们玩过的游戏对对碰,如果相同的元素挨在一起就要消除。
@@ -125,8 +125,7 @@ public:
## 其他语言版本
Java
### Java
使用 Deque 作为堆栈
```Java
@@ -203,7 +202,8 @@ class Solution {
}
```
Python
### Python
```python
# 方法一,使用栈
class Solution:
@@ -239,7 +239,7 @@ class Solution:
return ''.join(res[0: slow])
```
Go
### Go
```go
func removeDuplicates(s string) string {
@@ -258,7 +258,7 @@ func removeDuplicates(s string) string {
}
```
javaScript:
### JavaScript:
法一:使用栈
@@ -295,7 +295,7 @@ var removeDuplicates = function(s) {
};
```
TypeScript
### TypeScript
```typescript
function removeDuplicates(s: string): string {
@@ -318,7 +318,7 @@ function removeDuplicates(s: string): string {
};
```
C:
### C:
方法一:使用栈
```c
@@ -371,7 +371,8 @@ char * removeDuplicates(char * s){
}
```
Swift
### Swift
```swift
func removeDuplicates(_ s: String) -> String {
var stack = [Character]()
@@ -386,8 +387,8 @@ func removeDuplicates(_ s: String) -> String {
}
```
### C#:
C#:
```csharp
public string RemoveDuplicates(string s) {
//拿字符串直接作为栈,省去了栈还要转为字符串的操作
@@ -405,8 +406,8 @@ public string RemoveDuplicates(string s) {
}
```
### PHP:
PHP:
```php
class Solution {
function removeDuplicates($s) {
@@ -431,8 +432,8 @@ class Solution {
}
```
### Scala:
Scala:
```scala
object Solution {
import scala.collection.mutable
@@ -455,7 +456,7 @@ object Solution {
}
```
rust:
### Rust:
```rust
impl Solution {

View File

@@ -156,6 +156,21 @@ var balancedStringSplit = function(s) {
};
```
### TypeScript
```ts
function balancedStringSplit(s: string): number {
let count: number = 0
let res: number = 0
for(let i of s){
if(i === 'R') count++
else count--
if(count === 0) res++
}
return res
};
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">

View File

@@ -31,9 +31,9 @@
## 思路
本题是并查集基础题目。
本题是并查集基础题目。 如果还不了解并查集,可以看这里:[并查集理论基础](https://programmercarl.com/图论并查集理论基础.html)
首先要知道并查集可以解决什么问题呢?
并查集可以解决什么问题呢?
主要就是集合问题,两个节点在不在一个集合,也可以将两个节点添加到一个集合中。
@@ -70,7 +70,7 @@ void join(int u, int v) {
}
```
以上模板中,只要修改 n 大小就可以,本n不会超过2 * 10^5。
以上模板中,只要修改 n 大小就可以,本n不会超过2 * 10^5。
并查集主要有三个功能。

View File

@@ -92,7 +92,7 @@
* 递归:中序,双指针操作
* 迭代:模拟中序,逻辑相同
* [求二叉搜索树的众数](https://programmercarl.com/0501.二叉搜索树中的众数.html)
* 递归:中序,清空结果集的技巧,遍历一遍便可求众数集合
* [二叉搜索树转成累加树](https://programmercarl.com/0538.把二叉搜索树转换为累加树.html)
@@ -154,29 +154,13 @@
这个图是 [代码随想录知识星球](https://programmercarl.com/other/kstar.html) 成员:[](https://wx.zsxq.com/dweb2/index/footprint/185251215558842),所画,总结的非常好,分享给大家。
**最后二叉树系列就这么完美结束了估计这应该是最长的系列了感谢大家33天的坚持与陪伴接下来我们又要开始新的系列了「回溯算法」**
## 其他语言版本
Java
Python
Go
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -8,8 +8,11 @@
# 二叉树理论基础篇
## 算法公开课
《代码随想录》算法视频公开课:[关于二叉树,你该了解这些!](https://www.bilibili.com/video/BV1Hy4y1t7ij),相信结合视频看本篇题解,更有助于大家对本题的理解。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[关于二叉树,你该了解这些!](https://www.bilibili.com/video/BV1Hy4y1t7ij),相信结合视频看本篇题解,更有助于大家对本题的理解**
## 题目分类
题目分类大纲如下:
@@ -189,8 +192,7 @@ struct TreeNode {
## 其他语言版本
Java
### Java
```java
public class TreeNode {
@@ -208,8 +210,7 @@ public class TreeNode {
}
```
Python
### Python
```python
class TreeNode:
@@ -219,7 +220,7 @@ class TreeNode:
self.right = right
```
Go
### Go
```go
type TreeNode struct {
@@ -229,7 +230,7 @@ type TreeNode struct {
}
```
JavaScript
### JavaScript
```javascript
function TreeNode(val, left, right) {
@@ -239,7 +240,7 @@ function TreeNode(val, left, right) {
}
```
TypeScript
### TypeScript
```typescript
class TreeNode {
@@ -254,7 +255,7 @@ class TreeNode {
}
```
Swift:
### Swift:
```Swift
class TreeNode<T> {
@@ -271,7 +272,7 @@ class TreeNode<T> {
}
```
Scala:
### Scala:
```scala
class TreeNode(_value: Int = 0, _left: TreeNode = null, _right: TreeNode = null) {
@@ -281,7 +282,7 @@ class TreeNode(_value: Int = 0, _left: TreeNode = null, _right: TreeNode = null)
}
```
rust:
### Rust:
```rust
#[derive(Debug, PartialEq, Eq)]

View File

@@ -5,10 +5,11 @@
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
> 统一写法是一种什么感觉
# 二叉树的统一迭代法
> 统一写法是一种什么感觉
## 思路
此时我们在[二叉树一入递归深似海从此offer是路人](https://programmercarl.com/二叉树的递归遍历.html)中用递归的方式,实现了二叉树前中后序的遍历。
@@ -28,7 +29,7 @@
如何标记呢,**就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记。** 这种方法也可以叫做标记法。
## 迭代法中序遍历
### 迭代法中序遍历
中序遍历代码如下:(详细注释)
@@ -71,7 +72,7 @@ public:
此时我们再来看前序遍历代码。
## 迭代法前序遍历
### 迭代法前序遍历
迭代法前序遍历代码如下: (**注意此时我们和中序遍历相比仅仅改变了两行代码的顺序**)
@@ -102,7 +103,7 @@ public:
};
```
## 迭代法后序遍历
### 迭代法后序遍历
后续遍历代码如下: (**注意此时我们和中序遍历相比仅仅改变了两行代码的顺序**)
@@ -143,15 +144,11 @@ public:
所以大家根据自己的个人喜好,对于二叉树的前中后序遍历,选择一种自己容易理解的递归和迭代法。
## 其他语言版本
# 其他语言版本
Java
### Java
迭代法前序遍历代码如下:
```java
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
@@ -235,7 +232,7 @@ class Solution {
}
```
Python
### Python
迭代法前序遍历:
```python
@@ -309,7 +306,8 @@ class Solution:
return result
```
Go
### Go
> 前序遍历统一迭代法
```GO
@@ -442,7 +440,7 @@ func postorderTraversal(root *TreeNode) []int {
}
```
javaScript:
### JavaScript:
> 前序遍历统一迭代法
@@ -522,7 +520,7 @@ var postorderTraversal = function(root, res = []) {
```
TypeScript
### TypeScript
```typescript
// 前序遍历(迭代法)
@@ -591,7 +589,8 @@ function postorderTraversal(root: TreeNode | null): number[] {
return res;
};
```
Scala:
### Scala:
```scala
// 前序遍历
object Solution {
@@ -667,7 +666,7 @@ object Solution {
}
```
rust:
### Rust:
```rust
impl Solution{
@@ -747,3 +746,4 @@ impl Solution{
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -4,16 +4,17 @@
</a>
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
> 听说还可以用非递归的方式
# 二叉树的迭代遍历
《代码随想录》算法视频公开课
* [写出二叉树的非递归遍历很难么?(前序和后序)](https://www.bilibili.com/video/BV15f4y1W7i2)
* [写出二叉树的非递归遍历很难么?(中序))](https://www.bilibili.com/video/BV1Zf4y1a77g)
相信结合视频在看本篇题解,更有助于大家对本题的理解。
## 算法公开课
[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)
> 听说还可以用非递归的方式
* **[写出二叉树的非递归遍历很难么?(前序和后序)](https://www.bilibili.com/video/BV15f4y1W7i2)**
* **[写出二叉树的非递归遍历很难么?(中序))](https://www.bilibili.com/video/BV1Zf4y1a77g)**
**相信结合视频在看本篇题解,更有助于大家对本题的理解。**
看完本篇大家可以使用迭代法再重新解决如下三道leetcode上的题目
@@ -21,13 +22,15 @@
* [94.二叉树的中序遍历](https://leetcode.cn/problems/binary-tree-inorder-traversal/)
* [145.二叉树的后序遍历](https://leetcode.cn/problems/binary-tree-postorder-traversal/)
## 思路
为什么可以用迭代法(非递归的方式)来实现二叉树的前后中序遍历呢?
我们在[栈与队列:匹配问题都是栈的强项](https://programmercarl.com/1047.删除字符串中的所有相邻重复项.html)中提到了,**递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中**,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。
此时大家应该知道我们用栈也可以是实现二叉树的前后中序遍历了。
## 前序遍历(迭代法)
### 前序遍历(迭代法)
我们先看一下前序遍历。
@@ -69,7 +72,7 @@ public:
但接下来,**再用迭代法写中序遍历的时候,会发现套路又不一样了,目前的前序遍历的逻辑无法直接应用到中序遍历上。**
## 中序遍历(迭代法)
### 中序遍历(迭代法)
为了解释清楚,我说明一下 刚刚在迭代的过程中,其实我们有两个操作:
@@ -112,7 +115,7 @@ public:
```
## 后序遍历(迭代法)
### 后序遍历(迭代法)
再来看后序遍历先序遍历是中左右后续遍历是左右中那么我们只需要调整一下先序遍历的代码顺序就变成中右左的遍历顺序然后在反转result数组输出的结果顺序就是左右中了如下图
@@ -142,7 +145,7 @@ public:
```
# 总结
## 总结
此时我们用迭代法写出了二叉树的前后中序遍历,大家可以看出前序和中序是完全两种代码风格,并不像递归写法那样代码稍做调整,就可以实现前后中序。
@@ -155,11 +158,9 @@ public:
当然可以,这种写法,还不是很好理解,我们将在下一篇文章里重点讲解,敬请期待!
## 其他语言版本
# 其他语言版本
Java
### Java
```java
// 前序遍历顺序:中-左-右,入栈顺序:中-右-左
@@ -233,10 +234,7 @@ class Solution {
}
```
Python
### Python
```python
# 前序遍历-迭代-LC144_二叉树的前序遍历
@@ -281,7 +279,7 @@ class Solution:
# 取栈顶元素右结点
cur = cur.right
return result
```
```
```python
# 后序遍历-迭代-LC145_二叉树的后序遍历
@@ -303,10 +301,9 @@ class Solution:
stack.append(node.right)
# 将最终的数组翻转
return result[::-1]
```
```
Go
### Go
> 迭代法前序遍历
@@ -400,7 +397,7 @@ func inorderTraversal(root *TreeNode) []int {
}
```
javaScript
### JavaScript
```js
@@ -464,7 +461,7 @@ var postorderTraversal = function(root, res = []) {
};
```
TypeScript
### TypeScript
```typescript
// 前序遍历(迭代法)
@@ -519,7 +516,7 @@ function postorderTraversal(root: TreeNode | null): number[] {
};
```
Swift
### Swift
```swift
// 前序遍历迭代法
@@ -578,7 +575,8 @@ func inorderTraversal(_ root: TreeNode?) -> [Int] {
return result
}
```
Scala:
### Scala:
```scala
// 前序遍历(迭代法)
object Solution {
@@ -645,7 +643,7 @@ object Solution {
}
```
rust:
### Rust:
```rust
use std::cell::RefCell;

View File

@@ -4,15 +4,15 @@
</a>
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
> 一看就会,一写就废!
# 二叉树的递归遍历
## 算法公开课
《代码随想录》算法视频公开课:[每次写递归都要靠直觉? 这次带你学透二叉树的递归遍历!](https://www.bilibili.com/video/BV1Wh411S7xt),相信结合视频看本篇题解,更有助于大家对本题的理解。
**[《代码随想录》算法视频公开课](https://programmercarl.com/other/gongkaike.html)[每次写递归都要靠直觉? 这次带你学透二叉树的递归遍历!](https://www.bilibili.com/video/BV1Wh411S7xt),相信结合视频看本篇题解,更有助于大家对本题的理解**
> 一看就会,一写就废!
## 思路
这次我们要好好谈一谈递归,为什么很多同学看递归算法都是“一看就会,一写就废”。
@@ -109,14 +109,10 @@ void traversal(TreeNode* cur, vector<int>& vec) {
可能有同学感觉前后中序遍历的递归太简单了,要打迭代法(非递归),别急,我们明天打迭代法,打个通透!
## 其他语言版本
### Java
# 其他语言版本
Java
```Java
// 前序遍历·递归·LC144_二叉树的前序遍历
class Solution {
@@ -171,7 +167,8 @@ class Solution {
}
```
Python
### Python
```python
# 前序遍历-递归-LC144_二叉树的前序遍历
# Definition for a binary tree node.
@@ -219,7 +216,7 @@ class Solution:
return left + right + [root.val]
```
Go
### Go
前序遍历:
```go
@@ -273,7 +270,7 @@ func postorderTraversal(root *TreeNode) (res []int) {
}
```
Javascript版本
### Javascript
前序遍历:
```Javascript
@@ -327,7 +324,7 @@ var postorderTraversal = function(root) {
};
```
TypeScript:
### TypeScript:
```typescript
// 前序遍历
@@ -370,7 +367,7 @@ function postorderTraversal(node: TreeNode | null): number[] {
}
```
C:
### C:
```c
//前序遍历:
@@ -422,8 +419,9 @@ int* postorderTraversal(struct TreeNode* root, int* returnSize){
}
```
Swift:
### Swift:
前序遍历144.二叉树的前序遍历)
```Swift
func preorderTraversal(_ root: TreeNode?) -> [Int] {
var res = [Int]()
@@ -473,7 +471,10 @@ func postorder(_ root: TreeNode?, res: inout [Int]) {
res.append(root!.val)
}
```
Scala: 前序遍历144.二叉树的前序遍历)
### Scala:
前序遍历144.二叉树的前序遍历)
```scala
object Solution {
import scala.collection.mutable.ListBuffer
@@ -525,7 +526,7 @@ object Solution {
}
```
rust:
### Rust:
```rust
use std::cell::RefCell;

View File

@@ -15,7 +15,7 @@
输入s = "We are happy."
输出:"We%20are%20happy."
# 思路
## 思路
如果想把这道题目做到极致,就不要只用额外的辅助空间了!
@@ -86,7 +86,7 @@ public:
* [142.环形链表II](https://programmercarl.com/0142.环形链表II.html)
* [344.反转字符串](https://programmercarl.com/0344.反转字符串.html)
# 拓展
## 拓展
这里也给大家拓展一下字符串和数组有什么差别,
@@ -121,7 +121,8 @@ for (int i = 0; i < a.size(); i++) {
## 其他语言版本
C
### C
```C
char* replaceSpace(char* s){
//统计空格数量
@@ -152,8 +153,8 @@ char* replaceSpace(char* s){
}
```
### Java
Java
```Java
//使用一个新的对象,复制 str复制的过程对其判断是空格则替换否则直接复制类似于数组复制
public static String replaceSpace(String s) {
@@ -211,8 +212,8 @@ public String replaceSpace(String s) {
}
```
### Go
Go
```go
// 遍历添加
func replaceSpace(s string) string {
@@ -264,9 +265,10 @@ func replaceSpace(s string) string {
### python
因为字符串是不可变类型所以操作字符串需要将其转换为列表因此空间复杂度不可能为O(1)
python
#### 因为字符串是不可变类型所以操作字符串需要将其转换为列表因此空间复杂度不可能为O(1)
(版本一)转换成列表,并且添加相匹配的空间,然后进行填充
```python
class Solution:
@@ -328,7 +330,7 @@ class Solution:
def replaceSpace(self, s: str) -> str:
return s.replace(' ', '%20')
```
javaScript:
### JavaScript:
```js
/**
@@ -366,7 +368,7 @@ javaScript:
};
```
TypeScript
### TypeScript
```typescript
function replaceSpace(s: string): string {
@@ -393,7 +395,7 @@ function replaceSpace(s: string): string {
};
```
Swift:
### Swift:
```swift
func replaceSpace(_ s: String) -> String {
@@ -434,7 +436,7 @@ func replaceSpace(_ s: String) -> String {
}
```
Scala:
### Scala:
方式一: 双指针
```scala
@@ -491,8 +493,8 @@ object Solution {
}
```
### PHP
PHP
```php
function replaceSpace($s){
$sLen = strlen($s);
@@ -527,7 +529,7 @@ function spaceLen($s){
}
```
Rust
### Rust:
```Rust
impl Solution {
@@ -563,3 +565,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -24,7 +24,7 @@
限制:
1 <= k < s.length <= 10000
# 思路
## 思路
为了让本题更有意义提升一下本题难度**不能申请额外空间只能在本串上操作**。
@@ -71,7 +71,7 @@ public:
是不是发现这代码也太简单了,哈哈。
# 总结
## 总结
此时我们已经反转好多次字符串了,来一起回顾一下吧。
@@ -86,7 +86,7 @@ public:
好了,反转字符串一共就介绍到这里,相信大家此时对反转字符串的常见操作已经很了解了。
# 题外话
## 题外话
一些同学热衷于使用substr来做这道题。
其实使用substr 和 反转 时间复杂度是一样的 都是O(n)但是使用substr申请了额外空间所以空间复杂度是O(n)而反转方法的空间复杂度是O(1)。
@@ -96,7 +96,8 @@ public:
## 其他语言版本
Java
### Java
```java
class Solution {
public String reverseLeftWords(String s, int n) {
@@ -141,7 +142,7 @@ class Solution {
}
```
python:
### python:
(版本一)使用切片
```python
@@ -211,7 +212,7 @@ class Solution:
```
Go
### Go
```go
func reverseLeftWords(s string, n int) string {
@@ -234,8 +235,7 @@ func reverse(b []byte, left, right int){
}
```
JavaScript
### JavaScript
```javascript
var reverseLeftWords = function(s, n) {
@@ -279,7 +279,7 @@ var reverseLeftWords = function (s, n) {
};
```
TypeScript
### TypeScript
```typescript
function reverseLeftWords(s: string, n: number): string {
@@ -311,7 +311,7 @@ function reverseLeftWords(s: string, n: number): string {
};
```
Swift:
### Swift:
```swift
func reverseLeftWords(_ s: String, _ n: Int) -> String {
@@ -358,8 +358,7 @@ function reverse(&$s, $start, $end) {
}
```
Scala:
### Scala:
```scala
object Solution {
@@ -388,7 +387,7 @@ object Solution {
}
```
Rust:
### Rust:
```Rust
impl Solution {
@@ -419,3 +418,4 @@ impl Solution {
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
</a>

View File

@@ -8,7 +8,8 @@
相信大家已经对双指针法很熟悉了,但是双指针法并不隶属于某一种数据结构,我们在讲解数组,链表,字符串都用到了双指针法,所有有必要针对双指针法做一个总结。
# 数组篇
# 双指针总结篇
## 数组篇
在[数组:就移除个元素很难么?](https://programmercarl.com/0027.移除元素.html)中,原地移除数组上的元素,我们说到了数组上的元素,不能真正的删除,只能覆盖。
@@ -26,7 +27,7 @@ for (int i = 0; i < array.size(); i++) {
所以此时使用双指针法才展现出效率的优势:**通过两个指针在一个for循环下完成两个for循环的工作。**
# 字符串篇
## 字符串篇
在[字符串:这道题目,使用库函数一行代码搞定](https://programmercarl.com/0344.反转字符串.html)中讲解了反转字符串,注意这里强调要原地反转,要不然就失去了题目的意义。
@@ -48,7 +49,7 @@ for (int i = 0; i < array.size(); i++) {
**主要还是大家用erase用的比较随意一定要注意for循环下用erase的情况一般可以用双指针写效率更高**
# 链表篇
## 链表篇
翻转链表是现场面试,白纸写代码的好题,考察了候选者对链表以及指针的熟悉程度,而且代码也不长,适合在白纸上写。
@@ -62,7 +63,7 @@ for (int i = 0; i < array.size(); i++) {
那么找到环的入口,其实需要点简单的数学推理,我在文章中把找环的入口清清楚楚的推理的一遍,如果对找环入口不够清楚的同学建议自己看一看[链表:环找到了,那入口呢?](https://programmercarl.com/0142.环形链表II.html)。
# N数之和篇
## N数之和篇
在[哈希表:解决了两数之和,那么能解决三数之和么?](https://programmercarl.com/0015.三数之和.html)中讲到使用哈希法可以解决1.两数之和的问题
@@ -87,7 +88,7 @@ for (int i = 0; i < array.size(); i++) {
同样的道理五数之和n数之和都是在这个基础上累加。
# 总结
## 总结
本文中一共介绍了leetcode上九道使用双指针解决问题的经典题目除了链表一些题目一定要使用双指针其他题目都是使用双指针来提高效率一般是将O(n^2)的时间复杂度,降为$O(n)$。

Some files were not shown because too many files have changed in this diff Show More