Merge branch 'master' into greedy02

This commit is contained in:
程序员Carl 2022-07-19 11:26:14 +08:00 committed by GitHub
commit b98a63014e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
176 changed files with 5174 additions and 514 deletions

View File

@ -7,7 +7,7 @@
## 1. 两数之和
[力扣题目链接](https://leetcode-cn.com/problems/two-sum/)
[力扣题目链接](https://leetcode.cn/problems/two-sum/)
给定一个整数数组 nums 和一个目标值 target请你在该数组中找出和为目标值的那 两个 整数并返回他们的数组下标。
@ -317,6 +317,20 @@ public class Solution {
}
```
Dart:
```dart
List<int> twoSum(List<int> nums, int target) {
var tmp = [];
for (var i = 0; i < nums.length; i++) {
var rest = target - nums[i];
if(tmp.contains(rest)){
return [tmp.indexOf(rest), i];
}
tmp.add(nums[i]);
}
return [0 , 0];
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -8,7 +8,7 @@
# 5.最长回文子串
[力扣题目链接](https://leetcode-cn.com/problems/longest-palindromic-substring/)
[力扣题目链接](https://leetcode.cn/problems/longest-palindromic-substring/)
给你一个字符串 s找到 s 中最长的回文子串。

View File

@ -10,7 +10,7 @@
# 第15题. 三数之和
[力扣题目链接](https://leetcode-cn.com/problems/3sum/)
[力扣题目链接](https://leetcode.cn/problems/3sum/)
给你一个包含 n 个整数的数组 nums判断 nums 中是否存在三个元素 abc 使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
@ -95,7 +95,7 @@ public:
拿这个nums数组来举例首先将数组排序然后有一层for循环i从下标0的地方开始同时定一个下标left 定义在i+1的位置上定义下标right 在数组结尾的位置上。
依然还是在数组中找到 abc 使得a + b +c =0我们这里相当于 a = nums[i] b = nums[left] c = nums[right]。
依然还是在数组中找到 abc 使得a + b +c =0我们这里相当于 a = nums[i]b = nums[left]c = nums[right]。
接下来如何移动left 和right呢 如果nums[i] + nums[left] + nums[right] > 0 就说明 此时三数之和大了因为数组是排序后了所以right下标就应该向左移动这样才能让三数之和小一些。
@ -345,6 +345,76 @@ var threeSum = function(nums) {
return res
};
```
解法二nSum通用解法。递归
```js
/**
* nsum通用解法支持2sum3sum4sum...等等
* 时间复杂度分析:
* 1. n = 2时时间复杂度O(NlogN),排序所消耗的时间。、
* 2. n > 2时时间复杂度为O(N^n-1)即N的n-1次方至少是2次方此时可省略排序所消耗的时间。举例3sum为O(n^2)4sum为O(n^3)
* @param {number[]} nums
* @return {number[][]}
*/
var threeSum = function (nums) {
// nsum通用解法核心方法
function nSumTarget(nums, n, start, target) {
// 前提nums要先排序好
let res = [];
if (n === 2) {
res = towSumTarget(nums, start, target);
} else {
for (let i = start; i < nums.length; i++) {
// 递归求(n - 1)sum
let subRes = nSumTarget(
nums,
n - 1,
i + 1,
target - nums[i]
);
for (let j = 0; j < subRes.length; j++) {
res.push([nums[i], ...subRes[j]]);
}
// 跳过相同元素
while (nums[i] === nums[i + 1]) i++;
}
}
return res;
}
function towSumTarget(nums, start, target) {
// 前提nums要先排序好
let res = [];
let len = nums.length;
let left = start;
let right = len - 1;
while (left < right) {
let sum = nums[left] + nums[right];
if (sum < target) {
while (nums[left] === nums[left + 1]) left++;
left++;
} else if (sum > target) {
while (nums[right] === nums[right - 1]) right--;
right--;
} else {
// 相等
res.push([nums[left], nums[right]]);
// 跳过相同元素
while (nums[left] === nums[left + 1]) left++;
while (nums[right] === nums[right - 1]) right--;
left++;
right--;
}
}
return res;
}
nums.sort((a, b) => a - b);
// n = 3此时求3sum之和
return nSumTarget(nums, 3, 0, 0);
};
```
TypeScript:
```typescript
@ -484,6 +554,71 @@ func threeSum(_ nums: [Int]) -> [[Int]] {
}
```
Rust:
```Rust
// 哈希解法
use std::collections::HashSet;
impl Solution {
pub fn three_sum(nums: Vec<i32>) -> Vec<Vec<i32>> {
let mut result: Vec<Vec<i32>> = Vec::new();
let mut nums = nums;
nums.sort();
let len = nums.len();
for i in 0..len {
if nums[i] > 0 { break; }
if i > 0 && nums[i] == nums[i - 1] { continue; }
let mut set = HashSet::new();
for j in (i + 1)..len {
if j > i + 2 && nums[j] == nums[j - 1] && nums[j] == nums[j - 2] { continue; }
let c = 0 - (nums[i] + nums[j]);
if set.contains(&c) {
result.push(vec![nums[i], nums[j], c]);
set.remove(&c);
} else { set.insert(nums[j]); }
}
}
result
}
}
```
```Rust
// 双指针法
use std::collections::HashSet;
impl Solution {
pub fn three_sum(nums: Vec<i32>) -> Vec<Vec<i32>> {
let mut result: Vec<Vec<i32>> = Vec::new();
let mut nums = nums;
nums.sort();
let len = nums.len();
for i in 0..len {
if nums[i] > 0 { return result; }
if i > 0 && nums[i] == nums[i - 1] { continue; }
let (mut left, mut right) = (i + 1, len - 1);
while left < right {
if nums[i] + nums[left] + nums[right] > 0 {
right -= 1;
// 去重
while left < right && nums[right] == nums[right + 1] { right -= 1; }
} else if nums[i] + nums[left] + nums[right] < 0 {
left += 1;
// 去重
while left < right && nums[left] == nums[left - 1] { left += 1; }
} else {
result.push(vec![nums[i], nums[left], nums[right]]);
// 去重
right -= 1;
left += 1;
while left < right && nums[right] == nums[right + 1] { right -= 1; }
while left < right && nums[left] == nums[left - 1] { left += 1; }
}
}
}
result
}
}
```
C:
```C
//qsort辅助cmp函数

View File

@ -7,7 +7,7 @@
# 17.电话号码的字母组合
[力扣题目链接](https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/)
[力扣题目链接](https://leetcode.cn/problems/letter-combinations-of-a-phone-number/)
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
@ -454,6 +454,49 @@ function letterCombinations(digits: string): string[] {
};
```
## Rust
```Rust
impl Solution {
fn backtracking(result: &mut Vec<String>, s: &mut String, map: &[&str; 10], digits: &String, index: usize) {
let len = digits.len();
if len == index {
result.push(s.to_string());
return;
}
// 在保证不会越界的情况下使用unwrap()将Some()中的值提取出来
let digit= digits.chars().nth(index).unwrap().to_digit(10).unwrap() as usize;
let letters = map[digit];
for i in letters.chars() {
s.push(i);
Self::backtracking(result, s, &map, &digits, index+1);
s.pop();
}
}
pub fn letter_combinations(digits: String) -> Vec<String> {
if digits.len() == 0 {
return vec![];
}
const MAP: [&str; 10] = [
"",
"",
"abc",
"def",
"ghi",
"jkl",
"mno",
"pqrs",
"tuv",
"wxyz"
];
let mut result: Vec<String> = Vec::new();
let mut s: String = String::new();
Self::backtracking(&mut result, &mut s, &MAP, &digits, 0);
result
}
}
```
## C
```c
@ -557,6 +600,37 @@ func letterCombinations(_ digits: String) -> [String] {
}
```
## Scala:
```scala
object Solution {
import scala.collection.mutable
def letterCombinations(digits: String): List[String] = {
var result = mutable.ListBuffer[String]()
if(digits == "") return result.toList // 如果参数为空返回空结果集的List形式
var path = mutable.ListBuffer[Char]()
// 数字和字符的映射关系
val map = Array[String]("", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz")
def backtracking(index: Int): Unit = {
if (index == digits.size) {
result.append(path.mkString) // mkString语法将数组类型直接转换为字符串
return
}
var digit = digits(index) - '0' // 这里使用toInt会报错必须 -'0'
for (i <- 0 until map(digit).size) {
path.append(map(digit)(i))
backtracking(index + 1)
path = path.take(path.size - 1)
}
}
backtracking(0)
result.toList
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -10,7 +10,7 @@
# 第18题. 四数之和
[力扣题目链接](https://leetcode-cn.com/problems/4sum/)
[力扣题目链接](https://leetcode.cn/problems/4sum/)
题意给定一个包含 n 个整数的数组 nums 和一个目标值 target判断 nums 中是否存在四个元素 abc 和 d 使得 a + b + c + d 的值与 target 相等找出所有满足条件且不重复的四元组。
@ -140,6 +140,11 @@ class Solution {
for (int i = 0; i < nums.length; i++) {
// nums[i] > target 直接返回, 剪枝操作
if (nums[i] > 0 && nums[i] > target) {
return result;
}
if (i > 0 && nums[i - 1] == nums[i]) {
continue;
}
@ -153,7 +158,7 @@ class Solution {
int left = j + 1;
int right = nums.length - 1;
while (right > left) {
int sum = nums[i] + nums[j] + nums[left] + nums[right];
long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];
if (sum > target) {
right--;
} else if (sum < target) {
@ -522,6 +527,51 @@ public class Solution
}
}
```
Rust:
```Rust
impl Solution {
pub fn four_sum(nums: Vec<i32>, target: i32) -> Vec<Vec<i32>> {
let mut result: Vec<Vec<i32>> = Vec::new();
let mut nums = nums;
nums.sort();
let len = nums.len();
for k in 0..len {
// 剪枝
if nums[k] > target && (nums[k] > 0 || target > 0) { break; }
// 去重
if k > 0 && nums[k] == nums[k - 1] { continue; }
for i in (k + 1)..len {
// 剪枝
if nums[k] + nums[i] > target && (nums[k] + nums[i] >= 0 || target >= 0) { break; }
// 去重
if i > k + 1 && nums[i] == nums[i - 1] { continue; }
let (mut left, mut right) = (i + 1, len - 1);
while left < right {
if nums[k] + nums[i] > target - (nums[left] + nums[right]) {
right -= 1;
// 去重
while left < right && nums[right] == nums[right + 1] { right -= 1; }
} else if nums[k] + nums[i] < target - (nums[left] + nums[right]) {
left += 1;
// 去重
while left < right && nums[left] == nums[left - 1] { left += 1; }
} else {
result.push(vec![nums[k], nums[i], nums[left], nums[right]]);
// 去重
while left < right && nums[right] == nums[right - 1] { right -= 1; }
while left < right && nums[left] == nums[left + 1] { left += 1; }
left += 1;
right -= 1;
}
}
}
}
result
}
}
```
Scala:
```scala
object Solution {

View File

@ -9,7 +9,7 @@
## 19.删除链表的倒数第N个节点
[力扣题目链接](https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/)
[力扣题目链接](https://leetcode.cn/problems/remove-nth-node-from-end-of-list/)
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
@ -289,6 +289,30 @@ func removeNthFromEnd(_ head: ListNode?, _ n: Int) -> ListNode? {
return dummyHead.next
}
```
PHP:
```php
function removeNthFromEnd($head, $n) {
// 设置虚拟头节点
$dummyHead = new ListNode();
$dummyHead->next = $head;
$slow = $fast = $dummyHead;
while($n-- && $fast != null){
$fast = $fast->next;
}
// fast 再走一步,让 slow 指向删除节点的上一个节点
$fast = $fast->next;
while ($fast != NULL) {
$fast = $fast->next;
$slow = $slow->next;
}
$slow->next = $slow->next->next;
return $dummyHead->next;
}
```
Scala:
```scala
object Solution {

View File

@ -10,7 +10,7 @@
# 20. 有效的括号
[力扣题目链接](https://leetcode-cn.com/problems/valid-parentheses/)
[力扣题目链接](https://leetcode.cn/problems/valid-parentheses/)
给定一个只包括 '('')''{''}''['']' 的字符串,判断字符串是否有效。
@ -400,6 +400,37 @@ bool isValid(char * s){
return !stackTop;
}
```
PHP:
```php
// https://www.php.net/manual/zh/class.splstack.php
class Solution
{
function isValid($s){
$stack = new SplStack();
for ($i = 0; $i < strlen($s); $i++) {
if ($s[$i] == "(") {
$stack->push(')');
} else if ($s[$i] == "{") {
$stack->push('}');
} else if ($s[$i] == "[") {
$stack->push(']');
// 2、遍历匹配过程中发现栈内没有要匹配的字符 return false
// 3、遍历匹配过程中栈已为空没有匹配的字符了说明右括号没有找到对应的左括号 return false
} else if ($stack->isEmpty() || $stack->top() != $s[$i]) {
return false;
} else {//$stack->top() == $s[$i]
$stack->pop();
}
}
// 1、遍历完但是栈不为空,说明有相应的括号没有被匹配,return false
return $stack->isEmpty();
}
}
```
Scala:
```scala
object Solution {
@ -422,5 +453,6 @@ object Solution {
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -7,7 +7,7 @@
## 24. 两两交换链表中的节点
[力扣题目链接](https://leetcode-cn.com/problems/swap-nodes-in-pairs/)
[力扣题目链接](https://leetcode.cn/problems/swap-nodes-in-pairs/)
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
@ -254,20 +254,19 @@ TypeScript
```typescript
function swapPairs(head: ListNode | null): ListNode | null {
const dummyHead: ListNode = new ListNode(0, head);
let cur: ListNode = dummyHead;
while(cur.next !== null && cur.next.next !== null) {
const tem: ListNode = cur.next;
const tem1: ListNode = cur.next.next.next;
cur.next = cur.next.next; // step 1
cur.next.next = tem; // step 2
cur.next.next.next = tem1; // step 3
cur = cur.next.next;
}
return dummyHead.next;
}
const dummyNode: ListNode = new ListNode(0, head);
let curNode: ListNode | null = dummyNode;
while (curNode && curNode.next && curNode.next.next) {
let firstNode: ListNode = curNode.next,
secNode: ListNode = curNode.next.next,
thirdNode: ListNode | null = curNode.next.next.next;
curNode.next = secNode;
secNode.next = firstNode;
firstNode.next = thirdNode;
curNode = firstNode;
}
return dummyNode.next;
};
```
Kotlin:

View File

@ -7,7 +7,7 @@
## 27. 移除元素
[力扣题目链接](https://leetcode-cn.com/problems/remove-element/)
[力扣题目链接](https://leetcode.cn/problems/remove-element/)
给你一个数组 nums 和一个值 val你需要 原地 移除所有数值等于 val 的元素并返回移除后数组的新长度。
@ -219,6 +219,7 @@ func removeElement(nums []int, val int) int {
res++
}
}
nums=nums[:res]
return res
}
```
@ -339,7 +340,6 @@ int removeElement(int* nums, int numsSize, int val){
}
```
Kotlin:
```kotlin
fun removeElement(nums: IntArray, `val`: Int): Int {
@ -351,7 +351,6 @@ fun removeElement(nums: IntArray, `val`: Int): Int {
}
```
Scala:
```scala
object Solution {
@ -368,5 +367,20 @@ object Solution {
}
```
C#:
```csharp
public class Solution {
public int RemoveElement(int[] nums, int val) {
int slow = 0;
for (int fast = 0; fast < nums.Length; fast++) {
if (val != nums[fast]) {
nums[slow++] = nums[fast];
}
}
return slow;
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -9,7 +9,7 @@
# 28. 实现 strStr()
[力扣题目链接](https://leetcode-cn.com/problems/implement-strstr/)
[力扣题目链接](https://leetcode.cn/problems/implement-strstr/)
实现 strStr() 函数。
@ -1241,5 +1241,49 @@ function getNext(&$next, $s){
}
}
```
Rust:
> 前缀表统一不减一
```Rust
impl Solution {
pub fn get_next(next: &mut Vec<usize>, s: &Vec<char>) {
let len = s.len();
let mut j = 0;
for i in 1..len {
while j > 0 && s[i] != s[j] {
j = next[j - 1];
}
if s[i] == s[j] {
j += 1;
}
next[i] = j;
}
}
pub fn str_str(haystack: String, needle: String) -> i32 {
let (haystack_len, needle_len) = (haystack.len(), needle.len());
if haystack_len == 0 { return 0; }
if haystack_len < needle_len { return -1;}
let (haystack, needle) = (haystack.chars().collect::<Vec<char>>(), needle.chars().collect::<Vec<char>>());
let mut next: Vec<usize> = vec![0; haystack_len];
Self::get_next(&mut next, &needle);
let mut j = 0;
for i in 0..haystack_len {
while j > 0 && haystack[i] != needle[j] {
j = next[j - 1];
}
if haystack[i] == needle[j] {
j += 1;
}
if j == needle_len {
return (i - needle_len + 1) as i32;
}
}
return -1;
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -9,7 +9,7 @@
# 31.下一个排列
[力扣题目链接](https://leetcode-cn.com/problems/next-permutation/)
[力扣题目链接](https://leetcode.cn/problems/next-permutation/)
实现获取 下一个排列 的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
@ -171,13 +171,13 @@ class Solution(object):
i = n-2
while i >= 0 and nums[i] >= nums[i+1]:
i -= 1
if i > -1: // i==-1,不存在下一个更大的排列
j = n-1
while j >= 0 and nums[j] <= nums[i]:
j -= 1
nums[i], nums[j] = nums[j], nums[i]
start, end = i+1, n-1
while start < end:
nums[start], nums[end] = nums[end], nums[start]
@ -190,6 +190,26 @@ class Solution(object):
## Go
```go
//卡尔的解法
func nextPermutation(nums []int) {
for i:=len(nums)-1;i>=0;i--{
for j:=len(nums)-1;j>i;j--{
if nums[j]>nums[i]{
//交换
nums[j],nums[i]=nums[i],nums[j]
reverse(nums,0+i+1,len(nums)-1)
return
}
}
}
reverse(nums,0,len(nums)-1)
}
//对目标切片指定区间的反转方法
func reverse(a []int,begin,end int){
for i,j:=begin,end;i<j;i,j=i+1,j-1{
a[i],a[j]=a[j],a[i]
}
}
```
## JavaScript

View File

@ -480,6 +480,62 @@ var searchRange = function(nums, target) {
return [-1, -1];
};
```
### TypeScript
```typescript
function searchRange(nums: number[], target: number): number[] {
const leftBoard: number = getLeftBorder(nums, target);
const rightBoard: number = getRightBorder(nums, target);
// target 在nums区间左侧或右侧
if (leftBoard === (nums.length - 1) || rightBoard === 0) return [-1, -1];
// target 不存在与nums范围内
if (rightBoard - leftBoard <= 1) return [-1, -1];
// target 存在于nums范围内
return [leftBoard + 1, rightBoard - 1];
};
// 查找第一个大于target的元素下标
function getRightBorder(nums: number[], target: number): number {
let left: number = 0,
right: number = nums.length - 1;
// 0表示target在nums区间的左边
let rightBoard: number = 0;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (nums[mid] <= target) {
// 右边界一定在mid右边不含mid
left = mid + 1;
rightBoard = left;
} else {
// 右边界在mid左边含mid
right = mid - 1;
}
}
return rightBoard;
}
// 查找第一个小于target的元素下标
function getLeftBorder(nums: number[], target: number): number {
let left: number = 0,
right: number = nums.length - 1;
// length-1表示target在nums区间的右边
let leftBoard: number = nums.length - 1;
while (left <= right) {
let mid = Math.floor((left + right) / 2);
if (nums[mid] >= target) {
// 左边界一定在mid左边不含mid
right = mid - 1;
leftBoard = right;
} else {
// 左边界在mid右边含mid
left = mid + 1;
}
}
return leftBoard;
}
```
### Scala
```scala
object Solution {
@ -527,5 +583,6 @@ object Solution {
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -9,7 +9,7 @@
# 35.搜索插入位置
[力扣题目链接](https://leetcode-cn.com/problems/search-insert-position/)
[力扣题目链接](https://leetcode.cn/problems/search-insert-position/)
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
@ -283,6 +283,28 @@ var searchInsert = function (nums, target) {
};
```
### TypeScript
```typescript
// 第一种二分法
function searchInsert(nums: number[], target: number): number {
const length: number = nums.length;
let left: number = 0,
right: number = length - 1;
while (left <= right) {
const mid: number = Math.floor((left + right) / 2);
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] === target) {
return mid;
} else {
right = mid - 1;
}
}
return right + 1;
};
```
### Swift
```swift

View File

@ -9,7 +9,7 @@
# 37. 解数独
[力扣题目链接](https://leetcode-cn.com/problems/sudoku-solver/)
[力扣题目链接](https://leetcode.cn/problems/sudoku-solver/)
编写一个程序,通过填充空格来解决数独问题。
@ -602,5 +602,100 @@ func solveSudoku(_ board: inout [[Character]]) {
}
```
### Scala
详细写法:
```scala
object Solution {
def solveSudoku(board: Array[Array[Char]]): Unit = {
backtracking(board)
}
def backtracking(board: Array[Array[Char]]): Boolean = {
for (i <- 0 until 9) {
for (j <- 0 until 9) {
if (board(i)(j) == '.') { // 必须是为 . 的数字才放数字
for (k <- '1' to '9') { // 这个位置放k是否合适
if (isVaild(i, j, k, board)) {
board(i)(j) = k
if (backtracking(board)) return true // 找到了立刻返回
board(i)(j) = '.' // 回溯
}
}
return false // 9个数都试完了都不行就返回false
}
}
}
true // 遍历完所有的都没返回false说明找到了
}
def isVaild(x: Int, y: Int, value: Char, board: Array[Array[Char]]): Boolean = {
// 行
for (i <- 0 until 9 ) {
if (board(i)(y) == value) {
return false
}
}
// 列
for (j <- 0 until 9) {
if (board(x)(j) == value) {
return false
}
}
// 宫
var row = (x / 3) * 3
var col = (y / 3) * 3
for (i <- row until row + 3) {
for (j <- col until col + 3) {
if (board(i)(j) == value) {
return false
}
}
}
true
}
}
```
遵循Scala至简原则写法
```scala
object Solution {
def solveSudoku(board: Array[Array[Char]]): Unit = {
backtracking(board)
}
def backtracking(board: Array[Array[Char]]): Boolean = {
// 双重for循环 + 循环守卫
for (i <- 0 until 9; j <- 0 until 9 if board(i)(j) == '.') {
// 必须是为 . 的数字才放数字,使用循环守卫判断该位置是否可以放置当前循环的数字
for (k <- '1' to '9' if isVaild(i, j, k, board)) { // 这个位置放k是否合适
board(i)(j) = k
if (backtracking(board)) return true // 找到了立刻返回
board(i)(j) = '.' // 回溯
}
return false // 9个数都试完了都不行就返回false
}
true // 遍历完所有的都没返回false说明找到了
}
def isVaild(x: Int, y: Int, value: Char, board: Array[Array[Char]]): Boolean = {
// 行,循环守卫进行判断
for (i <- 0 until 9 if board(i)(y) == value) return false
// 列,循环守卫进行判断
for (j <- 0 until 9 if board(x)(j) == value) return false
// 宫,循环守卫进行判断
var row = (x / 3) * 3
var col = (y / 3) * 3
for (i <- row until row + 3; j <- col until col + 3 if board(i)(j) == value) return false
true // 最终没有返回false就说明该位置可以填写true
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -7,7 +7,7 @@
# 39. 组合总和
[力扣题目链接](https://leetcode-cn.com/problems/combination-sum/)
[力扣题目链接](https://leetcode.cn/problems/combination-sum/)
给定一个无重复元素的数组 candidates 和一个目标数 target 找出 candidates 中所有可以使数字和为 target 的组合。
@ -291,7 +291,7 @@ class Solution:
for i in range(start_index, len(candidates)):
sum_ += candidates[i]
self.path.append(candidates[i])
self.backtracking(candidates, target, sum_, i) # 因为无限制重复选取所以不是i-1
self.backtracking(candidates, target, sum_, i) # 因为无限制重复选取所以不是i+1
sum_ -= candidates[i] # 回溯
self.path.pop() # 回溯
```
@ -502,5 +502,35 @@ func combinationSum(_ candidates: [Int], _ target: Int) -> [[Int]] {
}
```
## Scala
```scala
object Solution {
import scala.collection.mutable
def combinationSum(candidates: Array[Int], target: Int): List[List[Int]] = {
var result = mutable.ListBuffer[List[Int]]()
var path = mutable.ListBuffer[Int]()
def backtracking(sum: Int, index: Int): Unit = {
if (sum == target) {
result.append(path.toList) // 如果正好等于target就添加到结果集
return
}
// 应该是从当前索引开始的而不是从0
// 剪枝优化添加循环守卫当sum + c(i) <= target的时候才循环才可以进入下一次递归
for (i <- index until candidates.size if sum + candidates(i) <= target) {
path.append(candidates(i))
backtracking(sum + candidates(i), i)
path = path.take(path.size - 1)
}
}
backtracking(0, 0)
result.toList
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -9,7 +9,7 @@
# 40.组合总和II
[力扣题目链接](https://leetcode-cn.com/problems/combination-sum-ii/)
[力扣题目链接](https://leetcode.cn/problems/combination-sum-ii/)
给定一个数组 candidates 和一个目标数 target 找出 candidates 中所有可以使数字和为 target 的组合。
@ -693,5 +693,37 @@ func combinationSum2(_ candidates: [Int], _ target: Int) -> [[Int]] {
}
```
## Scala
```scala
object Solution {
import scala.collection.mutable
def combinationSum2(candidates: Array[Int], target: Int): List[List[Int]] = {
var res = mutable.ListBuffer[List[Int]]()
var path = mutable.ListBuffer[Int]()
var candidate = candidates.sorted
def backtracking(sum: Int, startIndex: Int): Unit = {
if (sum == target) {
res.append(path.toList)
return
}
for (i <- startIndex until candidate.size if sum + candidate(i) <= target) {
if (!(i > startIndex && candidate(i) == candidate(i - 1))) {
path.append(candidate(i))
backtracking(sum + candidate(i), i + 1)
path = path.take(path.size - 1)
}
}
}
backtracking(0, 0)
res.toList
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -9,7 +9,7 @@
# 42. 接雨水
[力扣题目链接](https://leetcode-cn.com/problems/trapping-rain-water/)
[力扣题目链接](https://leetcode.cn/problems/trapping-rain-water/)
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
@ -640,8 +640,44 @@ func min(a,b int)int{
}
```
单调栈解法
```go
func trap(height []int) int {
if len(height) <= 2 {
return 0
}
st := make([]int, 1, len(height)) // 切片模拟单调栈st存储的是高度数组下标
var res int
for i := 1; i < len(height); i++ {
if height[i] < height[st[len(st)-1]] {
st = append(st, i)
} else if height[i] == height[st[len(st)-1]] {
st = st[:len(st)-1] // 比较的新元素和栈顶的元素相等,去掉栈中的,入栈新元素下标
st = append(st, i)
} else {
for len(st) != 0 && height[i] > height[st[len(st)-1]] {
top := st[len(st)-1]
st = st[:len(st)-1]
if len(st) != 0 {
tmp := (min(height[i], height[st[len(st)-1]]) - height[top]) * (i - st[len(st)-1] - 1)
res += tmp
}
}
st = append(st, i)
}
}
return res
}
func min(x, y int) int {
if x >= y {
return y
}
return x
}
```
### JavaScript:
```javascript
@ -744,6 +780,91 @@ var trap = function(height) {
};
```
### TypeScript
双指针法:
```typescript
function trap(height: number[]): number {
const length: number = height.length;
let resVal: number = 0;
for (let i = 0; i < length; i++) {
let leftMaxHeight: number = height[i],
rightMaxHeight: number = height[i];
let leftIndex: number = i - 1,
rightIndex: number = i + 1;
while (leftIndex >= 0) {
if (height[leftIndex] > leftMaxHeight)
leftMaxHeight = height[leftIndex];
leftIndex--;
}
while (rightIndex < length) {
if (height[rightIndex] > rightMaxHeight)
rightMaxHeight = height[rightIndex];
rightIndex++;
}
resVal += Math.min(leftMaxHeight, rightMaxHeight) - height[i];
}
return resVal;
};
```
动态规划:
```typescript
function trap(height: number[]): number {
const length: number = height.length;
const leftMaxHeightDp: number[] = [],
rightMaxHeightDp: number[] = [];
leftMaxHeightDp[0] = height[0];
rightMaxHeightDp[length - 1] = height[length - 1];
for (let i = 1; i < length; i++) {
leftMaxHeightDp[i] = Math.max(height[i], leftMaxHeightDp[i - 1]);
}
for (let i = length - 2; i >= 0; i--) {
rightMaxHeightDp[i] = Math.max(height[i], rightMaxHeightDp[i + 1]);
}
let resVal: number = 0;
for (let i = 0; i < length; i++) {
resVal += Math.min(leftMaxHeightDp[i], rightMaxHeightDp[i]) - height[i];
}
return resVal;
};
```
单调栈:
```typescript
function trap(height: number[]): number {
const length: number = height.length;
const stack: number[] = [];
stack.push(0);
let resVal: number = 0;
for (let i = 1; i < length; i++) {
let top = stack[stack.length - 1];
if (height[top] > height[i]) {
stack.push(i);
} else if (height[top] === height[i]) {
stack.pop();
stack.push(i);
} else {
while (stack.length > 0 && height[top] < height[i]) {
let mid = stack.pop();
if (stack.length > 0) {
let left = stack[stack.length - 1];
let h = Math.min(height[left], height[i]) - height[mid];
let w = i - left - 1;
resVal += h * w;
top = stack[stack.length - 1];
}
}
stack.push(i);
}
}
return resVal;
};
```
### C:
一种更简便的双指针方法:

View File

@ -9,7 +9,7 @@
# 45.跳跃游戏II
[力扣题目链接](https://leetcode-cn.com/problems/jump-game-ii/)
[力扣题目链接](https://leetcode.cn/problems/jump-game-ii/)
给定一个非负整数数组,你最初位于数组的第一个位置。

View File

@ -7,7 +7,7 @@
# 46.全排列
[力扣题目链接](https://leetcode-cn.com/problems/permutations/)
[力扣题目链接](https://leetcode.cn/problems/permutations/)
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
@ -341,7 +341,7 @@ function permute(nums: number[]): number[][] {
return resArr;
function backTracking(nums: number[], route: number[]): void {
if (route.length === nums.length) {
resArr.push(route.slice());
resArr.push([...route]);
return;
}
let tempVal: number;
@ -456,6 +456,36 @@ func permute(_ nums: [Int]) -> [[Int]] {
}
```
### Scala
```scala
object Solution {
import scala.collection.mutable
def permute(nums: Array[Int]): List[List[Int]] = {
var result = mutable.ListBuffer[List[Int]]()
var path = mutable.ListBuffer[Int]()
def backtracking(used: Array[Boolean]): Unit = {
if (path.size == nums.size) {
// 如果path的长度和nums相等那么可以添加到结果集
result.append(path.toList)
return
}
// 添加循环守卫,只有当当前数字没有用过的情况下才进入回溯
for (i <- nums.indices if used(i) == false) {
used(i) = true
path.append(nums(i))
backtracking(used) // 回溯
path.remove(path.size - 1)
used(i) = false
}
}
backtracking(new Array[Boolean](nums.size)) // 调用方法
result.toList // 最终返回结果集的List形式
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -8,7 +8,7 @@
## 47.全排列 II
[力扣题目链接](https://leetcode-cn.com/problems/permutations-ii/)
[力扣题目链接](https://leetcode.cn/problems/permutations-ii/)
给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
@ -268,7 +268,7 @@ var permuteUnique = function (nums) {
function backtracing( used) {
if (path.length === nums.length) {
result.push(path.slice())
result.push([...path])
return
}
for (let i = 0; i < nums.length; i++) {
@ -303,7 +303,7 @@ function permuteUnique(nums: number[]): number[][] {
return resArr;
function backTracking(nums: number[], route: number[]): void {
if (route.length === nums.length) {
resArr.push(route.slice());
resArr.push([...route]);
return;
}
for (let i = 0, length = nums.length; i < length; i++) {
@ -422,5 +422,43 @@ int** permuteUnique(int* nums, int numsSize, int* returnSize, int** returnColumn
}
```
### Scala
```scala
object Solution {
import scala.collection.mutable
def permuteUnique(nums: Array[Int]): List[List[Int]] = {
var result = mutable.ListBuffer[List[Int]]()
var path = mutable.ListBuffer[Int]()
var num = nums.sorted // 首先对数据进行排序
def backtracking(used: Array[Boolean]): Unit = {
if (path.size == num.size) {
// 如果path的size等于num了那么可以添加到结果集
result.append(path.toList)
return
}
// 循环守卫,当前元素没被使用过就进入循环体
for (i <- num.indices if used(i) == false) {
// 当前索引为0不存在和前一个数字相等可以进入回溯
// 当前索引值和上一个索引不相等,可以回溯
// 前一个索引对应的值没有被选,可以回溯
// 因为Scala没有continue只能将逻辑反过来写
if (i == 0 || (i > 0 && num(i) != num(i - 1)) || used(i-1) == false) {
used(i) = true
path.append(num(i))
backtracking(used)
path.remove(path.size - 1)
used(i) = false
}
}
}
backtracking(new Array[Boolean](nums.length))
result.toList
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -7,7 +7,7 @@
# 第51题. N皇后
[力扣题目链接](https://leetcode-cn.com/problems/n-queens/)
[力扣题目链接](https://leetcode.cn/problems/n-queens/)
n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
@ -455,7 +455,7 @@ var solveNQueens = function(n) {
};
```
## TypeScript
### TypeScript
```typescript
function solveNQueens(n: number): string[][] {
@ -683,5 +683,77 @@ char *** solveNQueens(int n, int* returnSize, int** returnColumnSizes){
}
```
### Scala
```scala
object Solution {
import scala.collection.mutable
def solveNQueens(n: Int): List[List[String]] = {
var result = mutable.ListBuffer[List[String]]()
def judge(x: Int, y: Int, maze: Array[Array[Boolean]]): Boolean = {
// 正上方
var xx = x
while (xx >= 0) {
if (maze(xx)(y)) return false
xx -= 1
}
// 左边
var yy = y
while (yy >= 0) {
if (maze(x)(yy)) return false
yy -= 1
}
// 左上方
xx = x
yy = y
while (xx >= 0 && yy >= 0) {
if (maze(xx)(yy)) return false
xx -= 1
yy -= 1
}
xx = x
yy = y
// 右上方
while (xx >= 0 && yy < n) {
if (maze(xx)(yy)) return false
xx -= 1
yy += 1
}
true
}
def backtracking(row: Int, maze: Array[Array[Boolean]]): Unit = {
if (row == n) {
// 将结果转换为题目所需要的形式
var path = mutable.ListBuffer[String]()
for (x <- maze) {
var tmp = mutable.ListBuffer[String]()
for (y <- x) {
if (y == true) tmp.append("Q")
else tmp.append(".")
}
path.append(tmp.mkString)
}
result.append(path.toList)
return
}
for (j <- 0 until n) {
// 判断这个位置是否可以放置皇后
if (judge(row, j, maze)) {
maze(row)(j) = true
backtracking(row + 1, maze)
maze(row)(j) = false
}
}
}
backtracking(0, Array.ofDim[Boolean](n, n))
result.toList
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -8,7 +8,7 @@
# 52. N皇后II
题目链接https://leetcode-cn.com/problems/n-queens-ii/
题目链接https://leetcode.cn/problems/n-queens-ii/
n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
@ -44,7 +44,7 @@ n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并
# 思路
看:[51.N皇后](https://mp.weixin.qq.com/s/lU_QwCMj6g60nh8m98GAWg) ,基本没有区别
看:[51.N皇后](https://mp.weixin.qq.com/s/lU_QwCMj6g60nh8m98GAWg) ,基本没有区别
# C++代码

View File

@ -7,7 +7,7 @@
# 53. 最大子序和
[力扣题目链接](https://leetcode-cn.com/problems/maximum-subarray/)
[力扣题目链接](https://leetcode.cn/problems/maximum-subarray/)
给定一个整数数组 nums 找到一个具有最大和的连续子数组子数组最少包含一个元素返回其最大和。

View File

@ -6,7 +6,7 @@
## 53. 最大子序和
[力扣题目链接](https://leetcode-cn.com/problems/maximum-subarray/)
[力扣题目链接](https://leetcode.cn/problems/maximum-subarray/)
给定一个整数数组 nums 找到一个具有最大和的连续子数组子数组最少包含一个元素返回其最大和。
@ -186,6 +186,7 @@ const maxSubArray = nums => {
};
```
Scala:
```scala
@ -203,5 +204,24 @@ object Solution {
}
```
TypeScript
```typescript
function maxSubArray(nums: number[]): number {
/**
dp[i]以nums[i]结尾的最大和
*/
const dp: number[] = []
dp[0] = nums[0];
let resMax: number = 0;
for (let i = 1; i < nums.length; i++) {
dp[i] = Math.max(dp[i - 1] + nums[i], nums[i]);
resMax = Math.max(resMax, dp[i]);
}
return resMax;
};
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -8,7 +8,7 @@
## 54.螺旋矩阵
[力扣题目链接](https://leetcode-cn.com/problems/spiral-matrix/)
[力扣题目链接](https://leetcode.cn/problems/spiral-matrix/)
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
@ -128,8 +128,8 @@ public:
## 类似题目
* [59.螺旋矩阵II](https://leetcode-cn.com/problems/spiral-matrix-ii/)
* [剑指Offer 29.顺时针打印矩阵](https://leetcode-cn.com/problems/shun-shi-zhen-da-yin-ju-zhen-lcof/)
* [59.螺旋矩阵II](https://leetcode.cn/problems/spiral-matrix-ii/)
* [剑指Offer 29.顺时针打印矩阵](https://leetcode.cn/problems/shun-shi-zhen-da-yin-ju-zhen-lcof/)
## 其他语言版本
Python:

View File

@ -7,7 +7,7 @@
# 55. 跳跃游戏
[力扣题目链接](https://leetcode-cn.com/problems/jump-game/)
[力扣题目链接](https://leetcode.cn/problems/jump-game/)
给定一个非负整数数组,你最初位于数组的第一个位置。

View File

@ -7,7 +7,7 @@
# 56. 合并区间
[力扣题目链接](https://leetcode-cn.com/problems/merge-intervals/)
[力扣题目链接](https://leetcode.cn/problems/merge-intervals/)
给出一个区间的集合,请合并所有重叠的区间。
@ -136,24 +136,38 @@ public:
### Java
```java
/**
时间复杂度 O(NlogN) 排序需要O(NlogN)
空间复杂度 O(logN) java 的内置排序是快速排序 需要 O(logN)空间
*/
class Solution {
public int[][] merge(int[][] intervals) {
List<int[]> res = new LinkedList<>();
Arrays.sort(intervals, (o1, o2) -> Integer.compare(o1[0], o2[0]));
//按照左边界排序
Arrays.sort(intervals, (x, y) -> Integer.compare(x[0], y[0]));
//initial start 是最小左边界
int start = intervals[0][0];
int rightmostRightBound = intervals[0][1];
for (int i = 1; i < intervals.length; i++) {
if (intervals[i][0] > intervals[i - 1][1]) {
res.add(new int[]{start, intervals[i - 1][1]});
//如果左边界大于最大右边界
if (intervals[i][0] > rightmostRightBound) {
//加入区间 并且更新start
res.add(new int[]{start, rightmostRightBound});
start = intervals[i][0];
rightmostRightBound = intervals[i][1];
} else {
intervals[i][1] = Math.max(intervals[i][1], intervals[i - 1][1]);
//更新最大右边界
rightmostRightBound = Math.max(rightmostRightBound, intervals[i][1]);
}
}
res.add(new int[]{start, intervals[intervals.length - 1][1]});
res.add(new int[]{start, rightmostRightBound});
return res.toArray(new int[res.size()][]);
}
}
}
```
```java
// 版本2

View File

@ -8,7 +8,7 @@
## 59.螺旋矩阵II
[力扣题目链接](https://leetcode-cn.com/problems/spiral-matrix-ii/)
[力扣题目链接](https://leetcode.cn/problems/spiral-matrix-ii/)
给定一个正整数 n生成一个包含 1 到 n^2 所有元素且元素按顺时针顺序螺旋排列的正方形矩阵。
@ -24,6 +24,8 @@
## 思路
为了利于录友们理解,我特意录制了视频,[拿下螺旋矩阵,《代码随想录》第五题!](https://www.bilibili.com/video/BV1SL4y1N7mV),结合本篇文章一起看,效果更佳。
这道题目可以说在面试中出现频率较高的题目,**本题并不涉及到什么算法,就是模拟过程,但却十分考察对代码的掌控能力。**
要如何画出这个螺旋排列的正方形矩阵呢?
@ -74,7 +76,7 @@ public:
int loop = n / 2; // 每个圈循环几次例如n为奇数3那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
int mid = n / 2; // 矩阵中间的位置例如n为3 中间的位置就是(11)n为5中间位置为(2, 2)
int count = 1; // 用来给矩阵中每一个空格赋值
int offset = 1; // 每一圈循环,需要控制每一条边遍历的长度
int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
int i,j;
while (loop --) {
i = startx;
@ -82,11 +84,11 @@ public:
// 下面开始的四个for就是模拟转了一圈
// 模拟填充上行从左到右(左闭右开)
for (j = starty; j < starty + n - offset; j++) {
for (j = starty; j < n - offset; j++) {
res[startx][j] = count++;
}
// 模拟填充右列从上到下(左闭右开)
for (i = startx; i < startx + n - offset; i++) {
for (i = startx; i < n - offset; i++) {
res[i][j] = count++;
}
// 模拟填充下行从右到左(左闭右开)
@ -103,7 +105,7 @@ public:
starty++;
// offset 控制每一圈里每一条边遍历的长度
offset += 2;
offset += 1;
}
// 如果n为奇数的话需要单独给矩阵最中间的位置赋值

View File

@ -6,7 +6,7 @@
# 62.不同路径
[力扣题目链接](https://leetcode-cn.com/problems/unique-paths/)
[力扣题目链接](https://leetcode.cn/problems/unique-paths/)
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
@ -374,6 +374,30 @@ function uniquePaths(m: number, n: number): number {
};
```
### Rust
```Rust
impl Solution {
pub fn unique_paths(m: i32, n: i32) -> i32 {
let m = m as usize;
let n = n as usize;
let mut dp = vec![vec![0; n]; m];
for i in 0..m {
dp[i][0] = 1;
}
for j in 0..n {
dp[0][j] = 1;
}
for i in 1..m {
for j in 1..n {
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
dp[m-1][n-1]
}
}
```
### C
```c

View File

@ -6,7 +6,7 @@
# 63. 不同路径 II
[力扣题目链接](https://leetcode-cn.com/problems/unique-paths-ii/)
[力扣题目链接](https://leetcode.cn/problems/unique-paths-ii/)
一个机器人位于一个 m x n 网格的左上角 起始点在下图中标记为“Start” )。
@ -384,6 +384,42 @@ function uniquePathsWithObstacles(obstacleGrid: number[][]): number {
};
```
### Rust
```Rust
impl Solution {
pub fn unique_paths_with_obstacles(obstacle_grid: Vec<Vec<i32>>) -> i32 {
let m: usize = obstacle_grid.len();
let n: usize = obstacle_grid[0].len();
if obstacle_grid[0][0] == 1 || obstacle_grid[m-1][n-1] == 1 {
return 0;
}
let mut dp = vec![vec![0; n]; m];
for i in 0..m {
if obstacle_grid[i][0] == 1 {
break;
}
else { dp[i][0] = 1; }
}
for j in 0..n {
if obstacle_grid[0][j] == 1 {
break;
}
else { dp[0][j] = 1; }
}
for i in 1..m {
for j in 1..n {
if obstacle_grid[i][j] == 1 {
continue;
}
dp[i][j] = dp[i-1][j] + dp[i][j-1];
}
}
dp[m-1][n-1]
}
}
```
### C
```c

View File

@ -5,7 +5,7 @@
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
# 70. 爬楼梯
[力扣题目链接](https://leetcode-cn.com/problems/climbing-stairs/)
[力扣题目链接](https://leetcode.cn/problems/climbing-stairs/)
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

View File

@ -11,7 +11,7 @@
## 70. 爬楼梯
[力扣题目链接](https://leetcode-cn.com/problems/climbing-stairs/)
[力扣题目链接](https://leetcode.cn/problems/climbing-stairs/)
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

View File

@ -6,7 +6,7 @@
## 72. 编辑距离
[力扣题目链接](https://leetcode-cn.com/problems/edit-distance/)
[力扣题目链接](https://leetcode.cn/problems/edit-distance/)
给你两个单词 word1 和 word2请你计算出将 word1 转换成 word2 所使用的最少操作数 。
@ -327,5 +327,42 @@ const minDistance = (word1, word2) => {
};
```
TypeScript
```typescript
function minDistance(word1: string, word2: string): number {
/**
dp[i][j]: word1前i个字符word2前j个字符最少操作数
dp[0][0]=0表示word1前0个字符为'', word2前0个字符为''
*/
const length1: number = word1.length,
length2: number = word2.length;
const dp: number[][] = new Array(length1 + 1).fill(0)
.map(_ => new Array(length2 + 1).fill(0));
for (let i = 0; i <= length1; i++) {
dp[i][0] = i;
}
for (let i = 0; i <= length2; i++) {
dp[0][i] = i;
}
for (let i = 1; i <= length1; i++) {
for (let j = 1; j <= length2; j++) {
if (word1[i - 1] === word2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = Math.min(
dp[i - 1][j],
dp[i][j - 1],
dp[i - 1][j - 1]
) + 1;
}
}
}
return dp[length1][length2];
};
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -9,7 +9,7 @@
# 第77题. 组合
[力扣题目链接](https://leetcode-cn.com/problems/combinations/ )
[力扣题目链接](https://leetcode.cn/problems/combinations/ )
给定两个整数 n 和 k返回 1 ... n 中所有可能的 k 个数的组合。
@ -535,6 +535,56 @@ func backtrack(n,k,start int,track []int){
}
```
### Rust
```Rust
impl Solution {
fn backtracking(result: &mut Vec<Vec<i32>>, path: &mut Vec<i32>, n: i32, k: i32, startIndex: i32) {
let len= path.len() as i32;
if len == k{
result.push(path.to_vec());
return;
}
for i in startIndex..= n {
path.push(i);
Self::backtracking(result, path, n, k, i+1);
path.pop();
}
}
pub fn combine(n: i32, k: i32) -> Vec<Vec<i32>> {
let mut result: Vec<Vec<i32>> = Vec::new();
let mut path: Vec<i32> = Vec::new();
Self::backtracking(&mut result, &mut path, n, k, 1);
result
}
}
```
剪枝
```Rust
impl Solution {
fn backtracking(result: &mut Vec<Vec<i32>>, path: &mut Vec<i32>, n: i32, k: i32, startIndex: i32) {
let len= path.len() as i32;
if len == k{
result.push(path.to_vec());
return;
}
// 此处剪枝
for i in startIndex..= n - (k - len) + 1 {
path.push(i);
Self::backtracking(result, path, n, k, i+1);
path.pop();
}
}
pub fn combine(n: i32, k: i32) -> Vec<Vec<i32>> {
let mut result: Vec<Vec<i32>> = Vec::new();
let mut path: Vec<i32> = Vec::new();
Self::backtracking(&mut result, &mut path, n, k, 1);
result
}
}
```
### C
```c
int* path;
@ -673,5 +723,63 @@ func combine(_ n: Int, _ k: Int) -> [[Int]] {
}
```
### Scala
暴力:
```scala
object Solution {
import scala.collection.mutable // 导包
def combine(n: Int, k: Int): List[List[Int]] = {
var result = mutable.ListBuffer[List[Int]]() // 存放结果集
var path = mutable.ListBuffer[Int]() //存放符合条件的结果
def backtracking(n: Int, k: Int, startIndex: Int): Unit = {
if (path.size == k) {
// 如果path的size == k就达到题目要求添加到结果集并返回
result.append(path.toList)
return
}
for (i <- startIndex to n) { // 遍历从startIndex到n
path.append(i) // 先把数字添加进去
backtracking(n, k, i + 1) // 进行下一步回溯
path = path.take(path.size - 1) // 回溯完再删除掉刚刚添加的数字
}
}
backtracking(n, k, 1) // 执行回溯
result.toList // 最终返回result的List形式return关键字可以省略
}
}
```
剪枝:
```scala
object Solution {
import scala.collection.mutable // 导包
def combine(n: Int, k: Int): List[List[Int]] = {
var result = mutable.ListBuffer[List[Int]]() // 存放结果集
var path = mutable.ListBuffer[Int]() //存放符合条件的结果
def backtracking(n: Int, k: Int, startIndex: Int): Unit = {
if (path.size == k) {
// 如果path的size == k就达到题目要求添加到结果集并返回
result.append(path.toList)
return
}
// 剪枝优化
for (i <- startIndex to (n - (k - path.size) + 1)) {
path.append(i) // 先把数字添加进去
backtracking(n, k, i + 1) // 进行下一步回溯
path = path.take(path.size - 1) // 回溯完再删除掉刚刚添加的数字
}
}
backtracking(n, k, 1) // 执行回溯
result.toList // 最终返回result的List形式return关键字可以省略
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -14,7 +14,7 @@
文中的回溯法是可以剪枝优化的本篇我们继续来看一下题目77. 组合。
链接https://leetcode-cn.com/problems/combinations/
链接https://leetcode.cn/problems/combinations/
**看本篇之前,需要先看[回溯算法:求组合问题!](https://programmercarl.com/0077.组合.html)**。
@ -261,6 +261,32 @@ function combine(n: number, k: number): number[][] {
};
```
Rust:
```Rust
impl Solution {
fn backtracking(result: &mut Vec<Vec<i32>>, path: &mut Vec<i32>, n: i32, k: i32, startIndex: i32) {
let len= path.len() as i32;
if len == k{
result.push(path.to_vec());
return;
}
// 此处剪枝
for i in startIndex..= n - (k - len) + 1 {
path.push(i);
Self::backtracking(result, path, n, k, i+1);
path.pop();
}
}
pub fn combine(n: i32, k: i32) -> Vec<Vec<i32>> {
let mut result: Vec<Vec<i32>> = Vec::new();
let mut path: Vec<i32> = Vec::new();
Self::backtracking(&mut result, &mut path, n, k, 1);
result
}
}
```
C:
```c
@ -346,5 +372,34 @@ func combine(_ n: Int, _ k: Int) -> [[Int]] {
}
```
Scala:
```scala
object Solution {
import scala.collection.mutable // 导包
def combine(n: Int, k: Int): List[List[Int]] = {
var result = mutable.ListBuffer[List[Int]]() // 存放结果集
var path = mutable.ListBuffer[Int]() //存放符合条件的结果
def backtracking(n: Int, k: Int, startIndex: Int): Unit = {
if (path.size == k) {
// 如果path的size == k就达到题目要求添加到结果集并返回
result.append(path.toList)
return
}
// 剪枝优化
for (i <- startIndex to (n - (k - path.size) + 1)) {
path.append(i) // 先把数字添加进去
backtracking(n, k, i + 1) // 进行下一步回溯
path = path.take(path.size - 1) // 回溯完再删除掉刚刚添加的数字
}
}
backtracking(n, k, 1) // 执行回溯
result.toList // 最终返回result的List形式return关键字可以省略
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -7,7 +7,7 @@
# 78.子集
[力扣题目链接](https://leetcode-cn.com/problems/subsets/)
[力扣题目链接](https://leetcode.cn/problems/subsets/)
给定一组不含重复元素的整数数组 nums返回该数组所有可能的子集幂集
@ -260,7 +260,7 @@ var subsets = function(nums) {
let result = []
let path = []
function backtracking(startIndex) {
result.push(path.slice())
result.push([...path])
for(let i = startIndex; i < nums.length; i++) {
path.push(nums[i])
backtracking(i + 1)
@ -280,7 +280,7 @@ function subsets(nums: number[]): number[][] {
backTracking(nums, 0, []);
return resArr;
function backTracking(nums: number[], startIndex: number, route: number[]): void {
resArr.push(route.slice());
resArr.push([...route]);
let length = nums.length;
if (startIndex === length) return;
for (let i = startIndex; i < length; i++) {
@ -373,6 +373,60 @@ func subsets(_ nums: [Int]) -> [[Int]] {
}
```
## Scala
思路一: 使用本题解思路
```scala
object Solution {
import scala.collection.mutable
def subsets(nums: Array[Int]): List[List[Int]] = {
var result = mutable.ListBuffer[List[Int]]()
var path = mutable.ListBuffer[Int]()
def backtracking(startIndex: Int): Unit = {
result.append(path.toList) // 存放结果
if (startIndex >= nums.size) {
return
}
for (i <- startIndex until nums.size) {
path.append(nums(i)) // 添加元素
backtracking(i + 1)
path.remove(path.size - 1) // 删除
}
}
backtracking(0)
result.toList
}
}
```
思路二: 将原问题转换为二叉树,针对每一个元素都有**选或不选**两种选择,直到遍历到最后,所有的叶子节点即为本题的答案:
```scala
object Solution {
import scala.collection.mutable
def subsets(nums: Array[Int]): List[List[Int]] = {
var result = mutable.ListBuffer[List[Int]]()
def backtracking(path: mutable.ListBuffer[Int], startIndex: Int): Unit = {
if (startIndex == nums.length) {
result.append(path.toList)
return
}
path.append(nums(startIndex))
backtracking(path, startIndex + 1) // 选择元素
path.remove(path.size - 1)
backtracking(path, startIndex + 1) // 不选择元素
}
backtracking(mutable.ListBuffer[Int](), 0)
result.toList
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -7,7 +7,7 @@
# 84.柱状图中最大的矩形
[力扣题目链接](https://leetcode-cn.com/problems/largest-rectangle-in-histogram/)
[力扣题目链接](https://leetcode.cn/problems/largest-rectangle-in-histogram/)
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
@ -486,5 +486,95 @@ var largestRectangleArea = function(heights) {
return maxArea;
};
```
TypeScript
> 双指针法(会超时):
```typescript
function largestRectangleArea(heights: number[]): number {
let resMax: number = 0;
for (let i = 0, length = heights.length; i < length; i++) {
// 左开右开
let left: number = i - 1,
right: number = i + 1;
while (left >= 0 && heights[left] >= heights[i]) {
left--;
}
while (right < length && heights[right] >= heights[i]) {
right++;
}
resMax = Math.max(resMax, heights[i] * (right - left - 1));
}
return resMax;
};
```
> 动态规划预处理:
```typescript
function largestRectangleArea(heights: number[]): number {
const length: number = heights.length;
const leftHeightDp: number[] = [],
rightHeightDp: number[] = [];
leftHeightDp[0] = -1;
rightHeightDp[length - 1] = length;
for (let i = 1; i < length; i++) {
let j = i - 1;
while (j >= 0 && heights[i] <= heights[j]) {
j = leftHeightDp[j];
}
leftHeightDp[i] = j;
}
for (let i = length - 2; i >= 0; i--) {
let j = i + 1;
while (j < length && heights[i] <= heights[j]) {
j = rightHeightDp[j];
}
rightHeightDp[i] = j;
}
let resMax: number = 0;
for (let i = 0; i < length; i++) {
let area = heights[i] * (rightHeightDp[i] - leftHeightDp[i] - 1);
resMax = Math.max(resMax, area);
}
return resMax;
};
```
> 单调栈:
```typescript
function largestRectangleArea(heights: number[]): number {
heights.push(0);
const length: number = heights.length;
// 栈底->栈顶:严格单调递增
const stack: number[] = [];
stack.push(0);
let resMax: number = 0;
for (let i = 1; i < length; i++) {
let top = stack[stack.length - 1];
if (heights[top] < heights[i]) {
stack.push(i);
} else if (heights[top] === heights[i]) {
stack.pop();
stack.push(i);
} else {
while (stack.length > 0 && heights[top] > heights[i]) {
let mid = stack.pop();
let left = stack.length > 0 ? stack[stack.length - 1] : -1;
let w = i - left - 1;
let h = heights[mid];
resMax = Math.max(resMax, w * h);
top = stack[stack.length - 1];
}
stack.push(i);
}
}
return resMax;
};
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -8,7 +8,7 @@
## 90.子集II
[力扣题目链接](https://leetcode-cn.com/problems/subsets-ii/)
[力扣题目链接](https://leetcode.cn/problems/subsets-ii/)
给定一个可能包含重复元素的整数数组 nums返回该数组所有可能的子集幂集
@ -299,7 +299,7 @@ var subsetsWithDup = function(nums) {
return a - b
})
function backtracing(startIndex, sortNums) {
result.push(path.slice(0))
result.push([...path])
if(startIndex > nums.length - 1) {
return
}
@ -327,7 +327,7 @@ function subsetsWithDup(nums: number[]): number[][] {
backTraking(nums, 0, []);
return resArr;
function backTraking(nums: number[], startIndex: number, route: number[]): void {
resArr.push(route.slice());
resArr.push([...route]);
let length: number = nums.length;
if (startIndex === length) return;
for (let i = startIndex; i < length; i++) {
@ -434,6 +434,63 @@ func subsetsWithDup(_ nums: [Int]) -> [[Int]] {
}
```
### Scala
不使用userd数组:
```scala
object Solution {
import scala.collection.mutable
def subsetsWithDup(nums: Array[Int]): List[List[Int]] = {
var result = mutable.ListBuffer[List[Int]]()
var path = mutable.ListBuffer[Int]()
var num = nums.sorted // 排序
def backtracking(startIndex: Int): Unit = {
result.append(path.toList)
if (startIndex >= num.size){
return
}
for (i <- startIndex until num.size) {
// 同一树层重复的元素不进入回溯
if (!(i > startIndex && num(i) == num(i - 1))) {
path.append(num(i))
backtracking(i + 1)
path.remove(path.size - 1)
}
}
}
backtracking(0)
result.toList
}
}
```
使用Set去重:
```scala
object Solution {
import scala.collection.mutable
def subsetsWithDup(nums: Array[Int]): List[List[Int]] = {
var result = mutable.Set[List[Int]]()
var num = nums.sorted
def backtracking(path: mutable.ListBuffer[Int], startIndex: Int): Unit = {
if (startIndex == num.length) {
result.add(path.toList)
return
}
path.append(num(startIndex))
backtracking(path, startIndex + 1) // 选择
path.remove(path.size - 1)
backtracking(path, startIndex + 1) // 不选择
}
backtracking(mutable.ListBuffer[Int](), 0)
result.toList
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -8,7 +8,7 @@
# 93.复原IP地址
[力扣题目链接](https://leetcode-cn.com/problems/restore-ip-addresses/)
[力扣题目链接](https://leetcode.cn/problems/restore-ip-addresses/)
给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。
@ -444,7 +444,7 @@ var restoreIpAddresses = function(s) {
return;
}
for(let j = i; j < s.length; j++) {
const str = s.substr(i, j - i + 1);
const str = s.slice(i, j + 1);
if(str.length > 3 || +str > 255) break;
if(str.length > 1 && str[0] === "0") break;
path.push(str);
@ -659,6 +659,48 @@ func restoreIpAddresses(_ s: String) -> [String] {
}
```
## Scala
```scala
object Solution {
import scala.collection.mutable
def restoreIpAddresses(s: String): List[String] = {
var result = mutable.ListBuffer[String]()
if (s.size < 4 || s.length > 12) return result.toList
var path = mutable.ListBuffer[String]()
// 判断IP中的一个字段是否为正确的
def isIP(sub: String): Boolean = {
if (sub.size > 1 && sub(0) == '0') return false
if (sub.toInt > 255) return false
true
}
def backtracking(startIndex: Int): Unit = {
if (startIndex >= s.size) {
if (path.size == 4) {
result.append(path.mkString(".")) // mkString方法可以把集合里的数据以指定字符串拼接
return
}
return
}
// subString
for (i <- startIndex until startIndex + 3 if i < s.size) {
var subString = s.substring(startIndex, i + 1)
if (isIP(subString)) { // 如果合法则进行下一轮
path.append(subString)
backtracking(i + 1)
path = path.take(path.size - 1)
}
}
}
backtracking(0)
result.toList
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -6,7 +6,7 @@
# 96.不同的二叉搜索树
[力扣题目链接](https://leetcode-cn.com/problems/unique-binary-search-trees/)
[力扣题目链接](https://leetcode.cn/problems/unique-binary-search-trees/)
给定一个整数 n求以 1 ... n 为节点组成的二叉搜索树有多少种?

View File

@ -7,7 +7,7 @@
# 98.验证二叉搜索树
[力扣题目链接](https://leetcode-cn.com/problems/validate-binary-search-tree/)
[力扣题目链接](https://leetcode.cn/problems/validate-binary-search-tree/)
给定一个二叉树,判断其是否是一个有效的二叉搜索树。
@ -589,7 +589,50 @@ function isValidBST(root: TreeNode | null): boolean {
};
```
## Scala
辅助数组解决:
```scala
object Solution {
import scala.collection.mutable
def isValidBST(root: TreeNode): Boolean = {
var arr = new mutable.ArrayBuffer[Int]()
// 递归中序遍历二叉树将节点添加到arr
def traversal(node: TreeNode): Unit = {
if (node == null) return
traversal(node.left)
arr.append(node.value)
traversal(node.right)
}
traversal(root)
// 这个数组如果是升序就代表是二叉搜索树
for (i <- 1 until arr.size) {
if (arr(i) <= arr(i - 1)) return false
}
true
}
}
```
递归中解决:
```scala
object Solution {
def isValidBST(root: TreeNode): Boolean = {
var flag = true
var preValue:Long = Long.MinValue // 这里要使用Long类型
def traversal(node: TreeNode): Unit = {
if (node == null || flag == false) return
traversal(node.left)
if (node.value > preValue) preValue = node.value
else flag = false
traversal(node.right)
}
traversal(root)
flag
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -8,7 +8,7 @@
# 100. 相同的树
[力扣题目链接](https://leetcode-cn.com/problems/same-tree/)
[力扣题目链接](https://leetcode.cn/problems/same-tree/)
给定两个二叉树,编写一个函数来检验它们是否相同。
@ -240,6 +240,46 @@ Go
JavaScript
TypeScript:
> 递归法-先序遍历
```typescript
function isSameTree(p: TreeNode | null, q: TreeNode | null): boolean {
if (p === null && q === null) return true;
if (p === null || q === null) return false;
if (p.val !== q.val) return false;
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
};
```
> 迭代法-层序遍历
```typescript
function isSameTree(p: TreeNode | null, q: TreeNode | null): boolean {
const queue1: (TreeNode | null)[] = [],
queue2: (TreeNode | null)[] = [];
queue1.push(p);
queue2.push(q);
while (queue1.length > 0 && queue2.length > 0) {
const node1 = queue1.shift(),
node2 = queue2.shift();
if (node1 === null && node2 === null) continue;
if (
(node1 === null || node2 === null) ||
node1!.val !== node2!.val
) return false;
queue1.push(node1!.left);
queue1.push(node1!.right);
queue2.push(node2!.left);
queue2.push(node2!.right);
}
return true;
};
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -7,7 +7,7 @@
# 101. 对称二叉树
[力扣题目链接](https://leetcode-cn.com/problems/symmetric-tree/)
[力扣题目链接](https://leetcode.cn/problems/symmetric-tree/)
给定一个二叉树,检查它是否是镜像对称的。
@ -437,6 +437,31 @@ class Solution:
return True
```
层次遍历
```python
class Solution:
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
if not root:
return True
que = [root]
while que:
this_level_length = len(que)
for i in range(this_level_length // 2):
# 要么其中一个是None但另外一个不是
if (not que[i] and que[this_level_length - 1 - i]) or (que[i] and not que[this_level_length - 1 - i]):
return False
# 要么两个都不是None
if que[i] and que[i].val != que[this_level_length - 1 - i].val:
return False
for i in range(this_level_length):
if not que[i]: continue
que.append(que[i].left)
que.append(que[i].right)
que = que[this_level_length:]
return True
```
## Go
```go
@ -725,5 +750,25 @@ func isSymmetric3(_ root: TreeNode?) -> Bool {
}
```
## Scala
递归:
```scala
object Solution {
def isSymmetric(root: TreeNode): Boolean = {
if (root == null) return true // 如果等于空直接返回true
def compare(left: TreeNode, right: TreeNode): Boolean = {
if (left == null && right == null) return true // 如果左右都为空则为true
if (left == null && right != null) return false // 如果左空右不空不对称返回false
if (left != null && right == null) return false // 如果左不空右空不对称返回false
// 如果左右的值相等,并且往下递归
left.value == right.value && compare(left.left, right.right) && compare(left.right, right.left)
}
// 分别比较左子树和右子树
compare(root.left, root.right)
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -26,7 +26,7 @@
# 102.二叉树的层序遍历
[力扣题目链接](https://leetcode-cn.com/problems/binary-tree-level-order-traversal/)
[力扣题目链接](https://leetcode.cn/problems/binary-tree-level-order-traversal/)
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
@ -379,7 +379,7 @@ pub fn level_order(root: Option<Rc<RefCell<TreeNode>>>) -> Vec<Vec<i32>> {
# 107.二叉树的层次遍历 II
[力扣题目链接](https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii/)
[力扣题目链接](https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/)
给定一个二叉树,返回其节点值自底向上的层次遍历。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
@ -660,7 +660,7 @@ pub fn level_order(root: Option<Rc<RefCell<TreeNode>>>) -> Vec<Vec<i32>> {
# 199.二叉树的右视图
[力扣题目链接](https://leetcode-cn.com/problems/binary-tree-right-side-view/)
[力扣题目链接](https://leetcode.cn/problems/binary-tree-right-side-view/)
给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
@ -907,7 +907,7 @@ object Solution {
# 637.二叉树的层平均值
[力扣题目链接](https://leetcode-cn.com/problems/average-of-levels-in-binary-tree/)
[力扣题目链接](https://leetcode.cn/problems/average-of-levels-in-binary-tree/)
给定一个非空二叉树, 返回一个由每层节点平均值组成的数组。
@ -1163,7 +1163,7 @@ object Solution {
# 429.N叉树的层序遍历
[力扣题目链接](https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal/)
[力扣题目链接](https://leetcode.cn/problems/n-ary-tree-level-order-traversal/)
给定一个 N 叉树,返回其节点值的层序遍历。 (即从左到右,逐层遍历)。
@ -1434,7 +1434,7 @@ object Solution {
# 515.在每个树行中找最大值
[力扣题目链接](https://leetcode-cn.com/problems/find-largest-value-in-each-tree-row/)
[力扣题目链接](https://leetcode.cn/problems/find-largest-value-in-each-tree-row/)
您需要在二叉树的每一行中找到最大的值。
@ -1668,7 +1668,7 @@ object Solution {
# 116.填充每个节点的下一个右侧节点指针
[力扣题目链接](https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node/)
[力扣题目链接](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/)
给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:
@ -1956,7 +1956,7 @@ object Solution {
```
# 117.填充每个节点的下一个右侧节点指针II
[力扣题目链接](https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node-ii/)
[力扣题目链接](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node-ii/)
思路:
@ -2236,7 +2236,7 @@ object Solution {
```
# 104.二叉树的最大深度
[力扣题目链接](https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/)
[力扣题目链接](https://leetcode.cn/problems/maximum-depth-of-binary-tree/)
给定一个二叉树,找出其最大深度。
@ -2477,7 +2477,7 @@ object Solution {
# 111.二叉树的最小深度
[力扣题目链接](https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/)
[力扣题目链接](https://leetcode.cn/problems/minimum-depth-of-binary-tree/)
相对于 104.二叉树的最大深度 ,本题还也可以使用层序遍历的方式来解决,思路是一样的。
@ -2629,21 +2629,21 @@ JavaScript
var minDepth = function(root) {
if (root === null) return 0;
let queue = [root];
let deepth = 0;
let depth = 0;
while (queue.length) {
let n = queue.length;
deepth++;
depth++;
for (let i=0; i<n; i++) {
let node = queue.shift();
// 如果左右节点都是null则该节点深度最小
// 如果左右节点都是null(在遇见的第一个leaf节点上),则该节点深度最小
if (node.left === null && node.right === null) {
return deepth;
return depth;
}
node.left && queue.push(node.left);;
node.right && queue.push (node.right);
node.right && queue.push(node.right);
}
}
return deepth;
return depth;
};
```

View File

@ -12,7 +12,7 @@
# 104.二叉树的最大深度
[力扣题目链接](https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/)
[力扣题目链接](https://leetcode.cn/problems/maximum-depth-of-binary-tree/)
给定一个二叉树,找出其最大深度。
@ -223,7 +223,7 @@ impl Solution {
# 559.n叉树的最大深度
[力扣题目链接](https://leetcode-cn.com/problems/maximum-depth-of-n-ary-tree/)
[力扣题目链接](https://leetcode.cn/problems/maximum-depth-of-n-ary-tree/)
给定一个 n 叉树,找到其最大深度。
@ -294,14 +294,13 @@ class solution {
/**
* 递归法
*/
public int maxdepth(treenode root) {
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
int leftdepth = maxdepth(root.left);
int rightdepth = maxdepth(root.right);
return math.max(leftdepth, rightdepth) + 1;
int leftDepth = maxDepth(root.left);
int rightDepth = maxDepth(root.right);
return Math.max(leftDepth, rightDepth) + 1;
}
}
```
@ -311,23 +310,23 @@ class solution {
/**
* 迭代法,使用层序遍历
*/
public int maxdepth(treenode root) {
public int maxDepth(TreeNode root) {
if(root == null) {
return 0;
}
deque<treenode> deque = new linkedlist<>();
Deque<TreeNode> deque = new LinkedList<>();
deque.offer(root);
int depth = 0;
while (!deque.isempty()) {
while (!deque.isEmpty()) {
int size = deque.size();
depth++;
for (int i = 0; i < size; i++) {
treenode poll = deque.poll();
if (poll.left != null) {
deque.offer(poll.left);
TreeNode node = deque.poll();
if (node.left != null) {
deque.offer(node.left);
}
if (poll.right != null) {
deque.offer(poll.right);
if (node.right != null) {
deque.offer(node.right);
}
}
}
@ -495,7 +494,7 @@ class solution:
## go
### 104.二叉树的最大深度
```go
/**
* definition for a binary tree node.
@ -548,6 +547,8 @@ func maxdepth(root *treenode) int {
## javascript
### 104.二叉树的最大深度
```javascript
var maxdepth = function(root) {
if (root === null) return 0;
@ -595,6 +596,8 @@ var maxDepth = function(root) {
};
```
### 559.n叉树的最大深度
N叉树的最大深度 递归写法
```js
var maxDepth = function(root) {
@ -627,9 +630,9 @@ var maxDepth = function(root) {
};
```
## TypeScript
## TypeScript
> 二叉树的最大深度:
### 104.二叉树的最大深度
```typescript
// 后续遍历(自下而上)
@ -672,7 +675,7 @@ function maxDepth(root: TreeNode | null): number {
};
```
> N叉树的最大深度
### 559.n叉树的最大深度
```typescript
// 后续遍历(自下而上)
@ -702,6 +705,8 @@ function maxDepth(root: TreeNode | null): number {
## C
### 104.二叉树的最大深度
二叉树最大深度递归
```c
int maxDepth(struct TreeNode* root){
@ -758,7 +763,8 @@ int maxDepth(struct TreeNode* root){
## Swift
>二叉树最大深度
### 104.二叉树的最大深度
```swift
// 递归 - 后序
func maxDepth1(_ root: TreeNode?) -> Int {
@ -797,7 +803,8 @@ func maxDepth(_ root: TreeNode?) -> Int {
}
```
>N叉树最大深度
### 559.n叉树的最大深度
```swift
// 递归
func maxDepth(_ root: Node?) -> Int {
@ -833,5 +840,84 @@ func maxDepth1(_ root: Node?) -> Int {
}
```
## Scala
### 104.二叉树的最大深度
递归法:
```scala
object Solution {
def maxDepth(root: TreeNode): Int = {
def process(curNode: TreeNode): Int = {
if (curNode == null) return 0
// 递归左节点和右节点,返回最大的,最后+1
math.max(process(curNode.left), process(curNode.right)) + 1
}
// 调用递归方法return关键字可以省略
process(root)
}
}
```
迭代法:
```scala
object Solution {
import scala.collection.mutable
def maxDepth(root: TreeNode): Int = {
var depth = 0
if (root == null) return depth
val queue = mutable.Queue[TreeNode]()
queue.enqueue(root)
while (!queue.isEmpty) {
val len = queue.size
for (i <- 0 until len) {
val curNode = queue.dequeue()
if (curNode.left != null) queue.enqueue(curNode.left)
if (curNode.right != null) queue.enqueue(curNode.right)
}
depth += 1 // 只要有层次就+=1
}
depth
}
}
```
### 559.n叉树的最大深度
递归法:
```scala
object Solution {
def maxDepth(root: Node): Int = {
if (root == null) return 0
var depth = 0
for (node <- root.children) {
depth = math.max(depth, maxDepth(node))
}
depth + 1
}
}
```
迭代法: (层序遍历)
```scala
object Solution {
import scala.collection.mutable
def maxDepth(root: Node): Int = {
if (root == null) return 0
var depth = 0
val queue = mutable.Queue[Node]()
queue.enqueue(root)
while (!queue.isEmpty) {
val len = queue.size
depth += 1
for (i <- 0 until len) {
val curNode = queue.dequeue()
for (node <- curNode.children) queue.enqueue(node)
}
}
depth
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -12,7 +12,7 @@
# 106.从中序与后序遍历序列构造二叉树
[力扣题目链接](https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/)
[力扣题目链接](https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/)
根据一棵树的中序遍历与后序遍历构造二叉树。
@ -394,7 +394,7 @@ public:
# 105.从前序与中序遍历序列构造二叉树
[力扣题目链接](https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/)
[力扣题目链接](https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/)
根据一棵树的前序遍历与中序遍历构造二叉树。
@ -584,35 +584,29 @@ tree2 的前序遍历是[1 2 3] 后序遍历是[3 2 1]。
```java
class Solution {
Map<Integer, Integer> map; // 方便根据数值查找位置
public TreeNode buildTree(int[] inorder, int[] postorder) {
return buildTree1(inorder, 0, inorder.length, postorder, 0, postorder.length);
map = new HashMap<>();
for (int i = 0; i < inorder.length; i++) { // 用map保存中序序列的数值对应位置
map.put(inorder[i], i);
}
return findNode(inorder, 0, inorder.length, postorder,0, postorder.length); // 前闭后开
}
public TreeNode buildTree1(int[] inorder, int inLeft, int inRight,
int[] postorder, int postLeft, int postRight) {
// 没有元素了
if (inRight - inLeft < 1) {
public TreeNode findNode(int[] inorder, int inBegin, int inEnd, int[] postorder, int postBegin, int postEnd) {
// 参数里的范围都是前闭后开
if (inBegin >= inEnd || postBegin >= postEnd) { // 不满足左闭右开,说明没有元素,返回空树
return null;
}
// 只有一个元素了
if (inRight - inLeft == 1) {
return new TreeNode(inorder[inLeft]);
}
// 后序数组postorder里最后一个即为根结点
int rootVal = postorder[postRight - 1];
TreeNode root = new TreeNode(rootVal);
int rootIndex = 0;
// 根据根结点的值找到该值在中序数组inorder里的位置
for (int i = inLeft; i < inRight; i++) {
if (inorder[i] == rootVal) {
rootIndex = i;
break;
}
}
// 根据rootIndex划分左右子树
root.left = buildTree1(inorder, inLeft, rootIndex,
postorder, postLeft, postLeft + (rootIndex - inLeft));
root.right = buildTree1(inorder, rootIndex + 1, inRight,
postorder, postLeft + (rootIndex - inLeft), postRight - 1);
int rootIndex = map.get(postorder[postEnd - 1]); // 找到后序遍历的最后一个元素在中序遍历中的位置
TreeNode root = new TreeNode(inorder[rootIndex]); // 构造结点
int lenOfLeft = rootIndex - inBegin; // 保存中序左子树个数,用来确定后序数列的个数
root.left = findNode(inorder, inBegin, rootIndex,
postorder, postBegin, postBegin + lenOfLeft);
root.right = findNode(inorder, rootIndex + 1, inEnd,
postorder, postBegin + lenOfLeft, postEnd - 1);
return root;
}
}
@ -622,31 +616,29 @@ class Solution {
```java
class Solution {
Map<Integer, Integer> map;
public TreeNode buildTree(int[] preorder, int[] inorder) {
return helper(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
}
public TreeNode helper(int[] preorder, int preLeft, int preRight,
int[] inorder, int inLeft, int inRight) {
// 递归终止条件
if (inLeft > inRight || preLeft > preRight) return null;
// val 为前序遍历第一个的值,也即是根节点的值
// idx 为根据根节点的值来找中序遍历的下标
int idx = inLeft, val = preorder[preLeft];
TreeNode root = new TreeNode(val);
for (int i = inLeft; i <= inRight; i++) {
if (inorder[i] == val) {
idx = i;
break;
}
map = new HashMap<>();
for (int i = 0; i < inorder.length; i++) { // 用map保存中序序列的数值对应位置
map.put(inorder[i], i);
}
// 根据 idx 来递归找左右子树
root.left = helper(preorder, preLeft + 1, preLeft + (idx - inLeft),
inorder, inLeft, idx - 1);
root.right = helper(preorder, preLeft + (idx - inLeft) + 1, preRight,
inorder, idx + 1, inRight);
return findNode(preorder, 0, preorder.length, inorder, 0, inorder.length); // 前闭后开
}
public TreeNode findNode(int[] preorder, int preBegin, int preEnd, int[] inorder, int inBegin, int inEnd) {
// 参数里的范围都是前闭后开
if (preBegin >= preEnd || inBegin >= inEnd) { // 不满足左闭右开,说明没有元素,返回空树
return null;
}
int rootIndex = map.get(preorder[preBegin]); // 找到前序遍历的第一个元素在中序遍历中的位置
TreeNode root = new TreeNode(inorder[rootIndex]); // 构造结点
int lenOfLeft = rootIndex - inBegin; // 保存中序左子树个数,用来确定前序数列的个数
root.left = findNode(preorder, preBegin + 1, preBegin + lenOfLeft + 1,
inorder, inBegin, rootIndex);
root.right = findNode(preorder, preBegin + lenOfLeft + 1, preEnd,
inorder, rootIndex + 1, inEnd);
return root;
}
}
@ -1091,7 +1083,53 @@ class Solution_0106 {
}
```
## Scala
106 从中序与后序遍历序列构造二叉树
```scala
object Solution {
def buildTree(inorder: Array[Int], postorder: Array[Int]): TreeNode = {
// 1、如果长度为0则直接返回null
var len = inorder.size
if (len == 0) return null
// 2、后序数组的最后一个元素是当前根元素
var rootValue = postorder(len - 1)
var root: TreeNode = new TreeNode(rootValue, null, null)
if (len == 1) return root // 如果数组只有一个节点,就直接返回
// 3、在中序数组中找到切割点的索引
var delimiterIndex: Int = inorder.indexOf(rootValue)
// 4、切分数组往下迭代
root.left = buildTree(inorder.slice(0, delimiterIndex), postorder.slice(0, delimiterIndex))
root.right = buildTree(inorder.slice(delimiterIndex + 1, len), postorder.slice(delimiterIndex, len - 1))
root // 返回rootreturn关键字可以省略
}
}
```
105 从前序与中序遍历序列构造二叉树
```scala
object Solution {
def buildTree(preorder: Array[Int], inorder: Array[Int]): TreeNode = {
// 1、如果长度为0直接返回空
var len = inorder.size
if (len == 0) return null
// 2、前序数组的第一个元素是当前子树根节点
var rootValue = preorder(0)
var root = new TreeNode(rootValue, null, null)
if (len == 1) return root // 如果数组元素只有一个,那么返回根节点
// 3、在中序数组中找到切割点
var delimiterIndex = inorder.indexOf(rootValue)
// 4、切分数组往下迭代
root.left = buildTree(preorder.slice(1, delimiterIndex + 1), inorder.slice(0, delimiterIndex))
root.right = buildTree(preorder.slice(delimiterIndex + 1, preorder.size), inorder.slice(delimiterIndex + 1, len))
root
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -9,7 +9,7 @@
# 108.将有序数组转换为二叉搜索树
[力扣题目链接](https://leetcode-cn.com/problems/convert-sorted-array-to-binary-search-tree/)
[力扣题目链接](https://leetcode.cn/problems/convert-sorted-array-to-binary-search-tree/)
将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树。
@ -448,5 +448,27 @@ struct TreeNode* sortedArrayToBST(int* nums, int numsSize) {
}
```
## Scala
递归:
```scala
object Solution {
def sortedArrayToBST(nums: Array[Int]): TreeNode = {
def buildTree(left: Int, right: Int): TreeNode = {
if (left > right) return null // 当left大于right的时候返回空
// 最中间的节点是当前节点
var mid = left + (right - left) / 2
var curNode = new TreeNode(nums(mid))
curNode.left = buildTree(left, mid - 1)
curNode.right = buildTree(mid + 1, right)
curNode
}
buildTree(0, nums.size - 1)
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -9,7 +9,7 @@
# 110.平衡二叉树
[力扣题目链接](https://leetcode-cn.com/problems/balanced-binary-tree/)
[力扣题目链接](https://leetcode.cn/problems/balanced-binary-tree/)
给定一个二叉树,判断它是否是高度平衡的二叉树。
@ -531,40 +531,26 @@ class Solution:
迭代法:
```python
class Solution:
def isBalanced(self, root: TreeNode) -> bool:
st = []
def isBalanced(self, root: Optional[TreeNode]) -> bool:
if not root:
return True
st.append(root)
while st:
node = st.pop() #中
if abs(self.getDepth(node.left) - self.getDepth(node.right)) > 1:
return False
if node.right:
st.append(node.right) #右(空节点不入栈)
if node.left:
st.append(node.left) #左(空节点不入栈)
return True
def getDepth(self, cur):
st = []
if cur:
st.append(cur)
depth = 0
result = 0
while st:
node = st.pop()
height_map = {}
stack = [root]
while stack:
node = stack.pop()
if node:
st.append(node) #中
st.append(None)
depth += 1
if node.right: st.append(node.right) #右
if node.left: st.append(node.left) #左
stack.append(node)
stack.append(None)
if node.left: stack.append(node.left)
if node.right: stack.append(node.right)
else:
node = st.pop()
depth -= 1
result = max(result, depth)
return result
real_node = stack.pop()
left, right = height_map.get(real_node.left, 0), height_map.get(real_node.right, 0)
if abs(left - right) > 1:
return False
height_map[real_node] = 1 + max(left, right)
return True
```

View File

@ -9,7 +9,7 @@
# 111.二叉树的最小深度
[力扣题目链接](https://leetcode-cn.com/problems/minimum-depth-of-binary-tree/)
[力扣题目链接](https://leetcode.cn/problems/minimum-depth-of-binary-tree/)
给定一个二叉树,找出其最小深度。
@ -488,6 +488,46 @@ func minDepth(_ root: TreeNode?) -> Int {
}
```
## Scala
递归法:
```scala
object Solution {
def minDepth(root: TreeNode): Int = {
if (root == null) return 0
if (root.left == null && root.right != null) return 1 + minDepth(root.right)
if (root.left != null && root.right == null) return 1 + minDepth(root.left)
// 如果两侧都不为空则取最小值return关键字可以省略
1 + math.min(minDepth(root.left), minDepth(root.right))
}
}
```
迭代法:
```scala
object Solution {
import scala.collection.mutable
def minDepth(root: TreeNode): Int = {
if (root == null) return 0
var depth = 0
val queue = mutable.Queue[TreeNode]()
queue.enqueue(root)
while (!queue.isEmpty) {
depth += 1
val len = queue.size
for (i <- 0 until len) {
val curNode = queue.dequeue()
if (curNode.left != null) queue.enqueue(curNode.left)
if (curNode.right != null) queue.enqueue(curNode.right)
if (curNode.left == null && curNode.right == null) return depth
}
}
depth
}
}
```
rust:
```rust
impl Solution {
@ -550,6 +590,7 @@ impl Solution {
}
min_depth
}
```
-----------------------

View File

@ -16,7 +16,7 @@
# 112. 路径总和
[力扣题目链接](https://leetcode-cn.com/problems/path-sum/)
[力扣题目链接](https://leetcode.cn/problems/path-sum/)
给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。
@ -216,7 +216,7 @@ public:
# 113. 路径总和ii
[力扣题目链接](https://leetcode-cn.com/problems/path-sum-ii/)
[力扣题目链接](https://leetcode.cn/problems/path-sum-ii/)
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
@ -300,7 +300,7 @@ public:
## java
lc112
### 0112.路径总和
```java
class solution {
public boolean haspathsum(treenode root, int targetsum) {
@ -373,7 +373,7 @@ class solution {
```
0113.路径总和-ii
### 0113.路径总和-ii
```java
class solution {
@ -436,7 +436,7 @@ class Solution {
## python
0112.路径总和
### 0112.路径总和
**递归**
```python
@ -488,7 +488,7 @@ class solution:
return false
```
0113.路径总和-ii
### 0113.路径总和-ii
**递归**
```python
@ -545,7 +545,7 @@ class Solution:
## go
112. 路径总和
### 112. 路径总和
```go
//递归法
@ -570,7 +570,7 @@ func hasPathSum(root *TreeNode, targetSum int) bool {
}
```
113. 路径总和 II
### 113. 路径总和 II
```go
/**
@ -612,7 +612,7 @@ func traverse(node *TreeNode, result *[][]int, currPath *[]int, targetSum int) {
## javascript
0112.路径总和
### 0112.路径总和
**递归**
```javascript
@ -673,7 +673,7 @@ let hasPathSum = function(root, targetSum) {
};
```
0113.路径总和-ii
### 0113.路径总和-ii
**递归**
```javascript
@ -768,7 +768,7 @@ let pathSum = function(root, targetSum) {
## TypeScript
> 0112.路径总和
### 0112.路径总和
**递归法:**
@ -850,7 +850,7 @@ function hasPathSum(root: TreeNode | null, targetSum: number): boolean {
};
```
> 0112.路径总和 ii
### 0112.路径总和 ii
**递归法:**
@ -888,7 +888,7 @@ function pathSum(root: TreeNode | null, targetSum: number): number[][] {
## Swift
0112.路径总和
### 0112.路径总和
**递归**
@ -955,7 +955,7 @@ func hasPathSum(_ root: TreeNode?, _ targetSum: Int) -> Bool {
}
```
0113.路径总和 II
### 0113.路径总和 II
**递归**
@ -1126,7 +1126,90 @@ int** pathSum(struct TreeNode* root, int targetSum, int* returnSize, int** retur
}
```
## Scala
### 0112.路径总和
**递归:**
```scala
object Solution {
def hasPathSum(root: TreeNode, targetSum: Int): Boolean = {
if(root == null) return false
var res = false
def traversal(curNode: TreeNode, sum: Int): Unit = {
if (res) return // 如果直接标记为true了就没有往下递归的必要了
if (curNode.left == null && curNode.right == null && sum == targetSum) {
res = true
return
}
// 往下递归
if (curNode.left != null) traversal(curNode.left, sum + curNode.left.value)
if (curNode.right != null) traversal(curNode.right, sum + curNode.right.value)
}
traversal(root, root.value)
res // return关键字可以省略
}
}
```
**迭代:**
```scala
object Solution {
import scala.collection.mutable
def hasPathSum(root: TreeNode, targetSum: Int): Boolean = {
if (root == null) return false
val stack = mutable.Stack[(TreeNode, Int)]()
stack.push((root, root.value)) // 将根节点元素放入stack
while (!stack.isEmpty) {
val curNode = stack.pop() // 取出栈顶元素
// 如果遇到叶子节点看当前的值是否等于targetSum等于则返回true
if (curNode._1.left == null && curNode._1.right == null && curNode._2 == targetSum) {
return true
}
if (curNode._1.right != null) stack.push((curNode._1.right, curNode._2 + curNode._1.right.value))
if (curNode._1.left != null) stack.push((curNode._1.left, curNode._2 + curNode._1.left.value))
}
false //如果没有返回true即可返回falsereturn关键字可以省略
}
}
```
### 0113.路径总和 II
**递归:**
```scala
object Solution {
import scala.collection.mutable.ListBuffer
def pathSum(root: TreeNode, targetSum: Int): List[List[Int]] = {
val res = ListBuffer[List[Int]]()
if (root == null) return res.toList
val path = ListBuffer[Int]();
def traversal(cur: TreeNode, count: Int): Unit = {
if (cur.left == null && cur.right == null && count == 0) {
res.append(path.toList)
return
}
if (cur.left != null) {
path.append(cur.left.value)
traversal(cur.left, count - cur.left.value)
path.remove(path.size - 1)
}
if (cur.right != null) {
path.append(cur.right.value)
traversal(cur.right, count - cur.right.value)
path.remove(path.size - 1)
}
}
path.append(root.value)
traversal(root, targetSum - root.value)
res.toList
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -6,7 +6,7 @@
## 115.不同的子序列
[力扣题目链接](https://leetcode-cn.com/problems/distinct-subsequences/)
[力扣题目链接](https://leetcode.cn/problems/distinct-subsequences/)
给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。
@ -267,6 +267,36 @@ const numDistinct = (s, t) => {
};
```
TypeScript
```typescript
function numDistinct(s: string, t: string): number {
/**
dp[i][j]: s前i个字符t前j个字符s子序列中t出现的个数
dp[0][0]=1, 表示s前0个字符为''t前0个字符为''
*/
const sLen: number = s.length,
tLen: number = t.length;
const dp: number[][] = new Array(sLen + 1).fill(0)
.map(_ => new Array(tLen + 1).fill(0));
for (let m = 0; m < sLen; m++) {
dp[m][0] = 1;
}
for (let i = 1; i <= sLen; i++) {
for (let j = 1; j <= tLen; j++) {
if (s[i - 1] === t[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
} else {
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[sLen][tLen];
};
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -7,7 +7,7 @@
# 116. 填充每个节点的下一个右侧节点指针
[力扣题目链接](https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node/)
[力扣题目链接](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/)
给定一个 完美二叉树 ,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下:

View File

@ -6,7 +6,7 @@
## 121. 买卖股票的最佳时机
[力扣题目链接](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/)
[力扣题目链接](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/)
给定一个数组 prices 它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

View File

@ -7,7 +7,7 @@
# 122.买卖股票的最佳时机II
[力扣题目链接](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/)
[力扣题目链接](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/)
给定一个数组它的第 i 个元素是一支给定股票第 i 天的价格。

View File

@ -6,7 +6,7 @@
## 122.买卖股票的最佳时机II
[力扣题目链接](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/)
[力扣题目链接](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/)
给定一个数组它的第 i 个元素是一支给定股票第 i 天的价格。

View File

@ -6,7 +6,7 @@
## 123.买卖股票的最佳时机III
[力扣题目链接](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iii/)
[力扣题目链接](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/)
给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

View File

@ -7,7 +7,7 @@
# 127. 单词接龙
[力扣题目链接](https://leetcode-cn.com/problems/word-ladder/)
[力扣题目链接](https://leetcode.cn/problems/word-ladder/)
字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列:
* 序列中第一个单词是 beginWord 。

View File

@ -3,9 +3,12 @@
<img src="https://code-thinking-1253855093.file.myqcloud.com/pics/20210924105952.png" width="1000"/>
</a>
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
# 129. 求根节点到叶节点数字之和
[力扣题目链接](https://leetcode-cn.com/problems/sum-root-to-leaf-numbers/)
[力扣题目链接](https://leetcode.cn/problems/sum-root-to-leaf-numbers/)
# 思路
@ -245,6 +248,29 @@ class Solution:
```
Go
```go
func sumNumbers(root *TreeNode) int {
sum = 0
travel(root, root.Val)
return sum
}
func travel(root *TreeNode, tmpSum int) {
if root.Left == nil && root.Right == nil {
sum += tmpSum
} else {
if root.Left != nil {
travel(root.Left, tmpSum*10+root.Left.Val)
}
if root.Right != nil {
travel(root.Right, tmpSum*10+root.Right.Val)
}
}
}
```
JavaScript
```javascript
var sumNumbers = function(root) {
@ -289,7 +315,40 @@ var sumNumbers = function(root) {
};
```
TypeScript
```typescript
function sumNumbers(root: TreeNode | null): number {
if (root === null) return 0;
let resTotal: number = 0;
const route: number[] = [];
route.push(root.val);
recur(root, route);
return resTotal;
function recur(node: TreeNode, route: number[]): void {
if (node.left === null && node.right === null) {
resTotal += listToSum(route);
return;
}
if (node.left !== null) {
route.push(node.left.val);
recur(node.left, route);
route.pop();
};
if (node.right !== null) {
route.push(node.right.val);
recur(node.right, route);
route.pop();
};
}
function listToSum(nums: number[]): number {
return Number(nums.join(''));
}
};
```
C:
```c
//sum记录总和
int sum;

View File

@ -9,7 +9,7 @@
# 131.分割回文串
[力扣题目链接](https://leetcode-cn.com/problems/palindrome-partitioning/)
[力扣题目链接](https://leetcode.cn/problems/palindrome-partitioning/)
给定一个字符串 s将 s 分割成一些子串,使每个子串都是回文串。
@ -442,7 +442,7 @@ var partition = function(s) {
}
for(let j = i; j < len; j++) {
if(!isPalindrome(s, i, j)) continue;
path.push(s.substr(i, j - i + 1));
path.push(s.slice(i, j + 1));
backtracking(j + 1);
path.pop();
}
@ -676,5 +676,50 @@ impl Solution {
}
}
```
## Scala
```scala
object Solution {
import scala.collection.mutable
def partition(s: String): List[List[String]] = {
var result = mutable.ListBuffer[List[String]]()
var path = mutable.ListBuffer[String]()
// 判断字符串是否回文
def isPalindrome(start: Int, end: Int): Boolean = {
var (left, right) = (start, end)
while (left < right) {
if (s(left) != s(right)) return false
left += 1
right -= 1
}
true
}
// 回溯算法
def backtracking(startIndex: Int): Unit = {
if (startIndex >= s.size) {
result.append(path.toList)
return
}
// 添加循环守卫,如果当前分割是回文子串则进入回溯
for (i <- startIndex until s.size if isPalindrome(startIndex, i)) {
path.append(s.substring(startIndex, i + 1))
backtracking(i + 1)
path = path.take(path.size - 1)
}
}
backtracking(0)
result.toList
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -8,7 +8,7 @@
# 132. 分割回文串 II
[力扣题目链接](https://leetcode-cn.com/problems/palindrome-partitioning-ii/)
[力扣题目链接](https://leetcode.cn/problems/palindrome-partitioning-ii/)
给你一个字符串 s请你将 s 分割成一些子串,使每个子串都是回文。
@ -206,6 +206,55 @@ public:
## Java
```java
class Solution {
public int minCut(String s) {
if(null == s || "".equals(s)){
return 0;
}
int len = s.length();
// 1.
// 记录子串[i..j]是否是回文串
boolean[][] isPalindromic = new boolean[len][len];
// 从下到上,从左到右
for(int i = len - 1; i >= 0; i--){
for(int j = i; j < len; j++){
if(s.charAt(i) == s.charAt(j)){
if(j - i <= 1){
isPalindromic[i][j] = true;
} else{
isPalindromic[i][j] = isPalindromic[i + 1][j - 1];
}
} else{
isPalindromic[i][j] = false;
}
}
}
// 2.
// dp[i] 表示[0..i]的最小分割次数
int[] dp = new int[len];
for(int i = 0; i < len; i++){
//初始考虑最坏的情况。 1个字符分割0次 len个字符分割 len - 1次
dp[i] = i;
}
for(int i = 1; i < len; i++){
if(isPalindromic[0][i]){
// s[0..i]是回文了,那 dp[i] = 0, 一次也不用分割
dp[i] = 0;
continue;
}
for(int j = 0; j < i; j++){
// 按文中的思路,不清楚就拿 "ababa" 为例,先写出 isPalindromic 数组,再进行求解
if(isPalindromic[j + 1][i]){
dp[i] = Math.min(dp[i], dp[j] + 1);
}
}
}
return dp[len - 1];
}
}
```
## Python
@ -240,6 +289,7 @@ class Solution:
## Go
```go
```
## JavaScript

View File

@ -7,7 +7,7 @@
# 134. 加油站
[力扣题目链接](https://leetcode-cn.com/problems/gas-station/)
[力扣题目链接](https://leetcode.cn/problems/gas-station/)
在一条环路上有 N 个加油站其中第 i 个加油站有汽油 gas[i] 升。

View File

@ -7,7 +7,7 @@
# 135. 分发糖果
[力扣题目链接](https://leetcode-cn.com/problems/candy/)
[力扣题目链接](https://leetcode.cn/problems/candy/)
老师想给孩子们分发糖果,有 N 个孩子站成了一条直线老师会根据每个孩子的表现预先给他们评分。

View File

@ -8,7 +8,7 @@
## 139.单词拆分
[力扣题目链接](https://leetcode-cn.com/problems/word-break/)
[力扣题目链接](https://leetcode.cn/problems/word-break/)
给定一个非空字符串 s 和一个包含非空单词的列表 wordDict判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

View File

@ -7,6 +7,8 @@
# 141. 环形链表
[力扣题目链接](https://leetcode.cn/problems/linked-list-cycle/submissions/)
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1则在该链表中没有环。注意pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
@ -103,7 +105,7 @@ class Solution:
return False
```
## Go
### Go
```go
func hasCycle(head *ListNode) bool {
@ -139,6 +141,23 @@ var hasCycle = function(head) {
};
```
### TypeScript
```typescript
function hasCycle(head: ListNode | null): boolean {
let slowNode: ListNode | null = head,
fastNode: ListNode | null = head;
while (fastNode !== null && fastNode.next !== null) {
slowNode = slowNode!.next;
fastNode = fastNode.next.next;
if (slowNode === fastNode) return true;
}
return false;
};
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -11,7 +11,7 @@
## 142.环形链表II
[力扣题目链接](https://leetcode-cn.com/problems/linked-list-cycle-ii/)
[力扣题目链接](https://leetcode.cn/problems/linked-list-cycle-ii/)
题意:
给定一个链表返回链表开始入环的第一个节点。 如果链表无环则返回 null。
@ -301,13 +301,13 @@ function detectCycle(head: ListNode | null): ListNode | null {
let slowNode: ListNode | null = head,
fastNode: ListNode | null = head;
while (fastNode !== null && fastNode.next !== null) {
slowNode = (slowNode as ListNode).next;
slowNode = slowNode!.next;
fastNode = fastNode.next.next;
if (slowNode === fastNode) {
slowNode = head;
while (slowNode !== fastNode) {
slowNode = (slowNode as ListNode).next;
fastNode = (fastNode as ListNode).next;
slowNode = slowNode!.next;
fastNode = fastNode!.next;
}
return slowNode;
}

View File

@ -6,6 +6,8 @@
# 143.重排链表
[力扣题目链接](https://leetcode.cn/problems/reorder-list/submissions/)
![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210726160122.png)
## 思路
@ -465,7 +467,81 @@ var reorderList = function(head, s = [], tmp) {
}
```
### TypeScript
> 辅助数组法:
```typescript
function reorderList(head: ListNode | null): void {
if (head === null) return;
const helperArr: ListNode[] = [];
let curNode: ListNode | null = head;
while (curNode !== null) {
helperArr.push(curNode);
curNode = curNode.next;
}
let node: ListNode = head;
let left: number = 1,
right: number = helperArr.length - 1;
let count: number = 0;
while (left <= right) {
if (count % 2 === 0) {
node.next = helperArr[right--];
} else {
node.next = helperArr[left++];
}
count++;
node = node.next;
}
node.next = null;
};
```
> 分割链表法:
```typescript
function reorderList(head: ListNode | null): void {
if (head === null || head.next === null) return;
let fastNode: ListNode = head,
slowNode: ListNode = head;
while (fastNode.next !== null && fastNode.next.next !== null) {
slowNode = slowNode.next!;
fastNode = fastNode.next.next;
}
let head1: ListNode | null = head;
// 反转后半部分链表
let head2: ListNode | null = reverseList(slowNode.next);
// 分割链表
slowNode.next = null;
/**
直接在head1链表上进行插入
head1 链表长度一定大于或等于head2,
因此在下面的循环中只要head2不为null, head1 一定不为null
*/
while (head2 !== null) {
const tempNode1: ListNode | null = head1!.next,
tempNode2: ListNode | null = head2.next;
head1!.next = head2;
head2.next = tempNode1;
head1 = tempNode1;
head2 = tempNode2;
}
};
function reverseList(head: ListNode | null): ListNode | null {
let curNode: ListNode | null = head,
preNode: ListNode | null = null;
while (curNode !== null) {
const tempNode: ListNode | null = curNode.next;
curNode.next = preNode;
preNode = curNode;
curNode = tempNode;
}
return preNode;
}
```
### C
方法三:反转链表
```c
//翻转链表

View File

@ -11,7 +11,7 @@
# 150. 逆波兰表达式求值
[力扣题目链接](https://leetcode-cn.com/problems/evaluate-reverse-polish-notation/)
[力扣题目链接](https://leetcode.cn/problems/evaluate-reverse-polish-notation/)
根据 逆波兰表示法,求表达式的值。
@ -325,6 +325,33 @@ func evalRPN(_ tokens: [String]) -> Int {
return stack.last!
}
```
PHP
```php
class Solution {
function evalRPN($tokens) {
$st = new SplStack();
for($i = 0;$i<count($tokens);$i++){
// 是数字直接入栈
if(is_numeric($tokens[$i])){
$st->push($tokens[$i]);
}else{
// 是符号进行运算
$num1 = $st->pop();
$num2 = $st->pop();
if ($tokens[$i] == "+") $st->push($num2 + $num1);
if ($tokens[$i] == "-") $st->push($num2 - $num1);
if ($tokens[$i] == "*") $st->push($num2 * $num1);
// 注意处理小数部分
if ($tokens[$i] == "/") $st->push(intval($num2 / $num1));
}
}
return $st->pop();
}
}
```
Scala:
```scala
object Solution {
@ -351,6 +378,7 @@ object Solution {
// 最后返回栈顶不需要加return关键字
stack.pop()
}
}
```
-----------------------

View File

@ -10,7 +10,7 @@
# 151.翻转字符串里的单词
[力扣题目链接](https://leetcode-cn.com/problems/reverse-words-in-a-string/)
[力扣题目链接](https://leetcode.cn/problems/reverse-words-in-a-string/)
给定一个字符串,逐个翻转字符串中的每个单词。
@ -79,7 +79,7 @@ void removeExtraSpaces(string& s) {
逻辑很简单从前向后遍历遇到空格了就erase。
如果不仔细琢磨一下erase的时间复杂还以为以上的代码是O(n)的时间复杂度呢。
如果不仔细琢磨一下erase的时间复杂还以为以上的代码是O(n)的时间复杂度呢。
想一下真正的时间复杂度是多少一个erase本来就是O(n)的操作erase实现原理题目[数组:就移除个元素很难么?](https://programmercarl.com/0027.移除元素.html)最优的算法来移除元素也要O(n)。
@ -234,7 +234,7 @@ public:
}
void removeExtraSpaces(string& s) {//去除所有空格并在相邻单词之间添加空格, 快慢指针。
int slow = 0; //整体思想参考Leetcode: 27. 移除元素https://leetcode-cn.com/problems/remove-element/
int slow = 0; //整体思想参考Leetcode: 27. 移除元素https://leetcode.cn/problems/remove-element/
for (int i = 0; i < s.size(); ++i) { //
if (s[i] != ' ') { //遇到非空格就处理,即删除所有空格。
if (slow != 0) s[slow++] = ' '; //手动控制空格给单词之间添加空格。slow != 0说明不是第一个单词需要在单词前添加空格。
@ -817,7 +817,105 @@ object Solution {
```
PHP:
```php
function reverseWords($s) {
$this->removeExtraSpaces($s);
$this->reverseString($s, 0, strlen($s)-1);
// 将每个单词反转
$start = 0;
for ($i = 0; $i <= strlen($s); $i++) {
// 到达空格或者串尾,说明一个单词结束。进行翻转。
if ($i == strlen($s) || $s[$i] == ' ') {
// 翻转,注意是左闭右闭 []的翻转。
$this->reverseString($s, $start, $i-1);
// +1: 单词与单词直接有个空格
$start = $i + 1;
}
}
return $s;
}
// 移除多余空格
function removeExtraSpaces(&$s){
$slow = 0;
for ($i = 0; $i < strlen($s); $i++) {
if ($s[$i] != ' ') {
if ($slow != 0){
$s[$slow++] = ' ';
}
while ($i < strlen($s) && $s[$i] != ' ') {
$s[$slow++] = $s[$i++];
}
}
}
// 移动覆盖处理,丢弃多余的脏数据。
$s = substr($s,0,$slow);
return ;
}
// 翻转字符串
function reverseString(&$s, $start, $end) {
for ($i = $start, $j = $end; $i < $j; $i++, $j--) {
$tmp = $s[$i];
$s[$i] = $s[$j];
$s[$j] = $tmp;
}
return ;
}
```
Rust:
```Rust
// 根据C++版本二思路进行实现
// 函数名根据Rust编译器建议由驼峰命名法改为蛇形命名法
impl Solution {
pub fn reverse(s: &mut Vec<char>, mut begin: usize, mut end: usize){
while begin < end {
let temp = s[begin];
s[begin] = s[end];
s[end] = temp;
begin += 1;
end -= 1;
}
}
pub fn remove_extra_spaces(s: &mut Vec<char>) {
let mut slow: usize = 0;
let len = s.len();
// 注意这里不能用for循环不然在里面那个while循环中对i的递增会失效
let mut i: usize = 0;
while i < len {
if !s[i].is_ascii_whitespace() {
if slow != 0 {
s[slow] = ' ';
slow += 1;
}
while i < len && !s[i].is_ascii_whitespace() {
s[slow] = s[i];
slow += 1;
i += 1;
}
}
i += 1;
}
s.resize(slow, ' ');
}
pub fn reverse_words(s: String) -> String {
let mut s = s.chars().collect::<Vec<char>>();
Self::remove_extra_spaces(&mut s);
let len = s.len();
Self::reverse(&mut s, 0, len - 1);
let mut start = 0;
for i in 0..=len {
if i == len || s[i].is_ascii_whitespace() {
Self::reverse(&mut s, start, i - 1);
start = i + 1;
}
}
s.iter().collect::<String>()
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -6,7 +6,7 @@
## 188.买卖股票的最佳时机IV
[力扣题目链接](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-iv/)
[力扣题目链接](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iv/)
给定一个整数数组 prices ,它的第 i 个元素 prices[i] 是一支给定的股票在第 i 天的价格。

View File

@ -7,6 +7,8 @@
# 189. 旋转数组
[力扣题目链接](https://leetcode.cn/problems/rotate-array/)
给定一个数组将数组中的元素向右移动 k 个位置其中 k 是非负数。
进阶:
@ -160,6 +162,27 @@ var rotate = function (nums, k) {
};
```
## TypeScript
```typescript
function rotate(nums: number[], k: number): void {
const length: number = nums.length;
k %= length;
reverseByRange(nums, 0, length - 1);
reverseByRange(nums, 0, k - 1);
reverseByRange(nums, k, length - 1);
};
function reverseByRange(nums: number[], left: number, right: number): void {
while (left < right) {
const temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
left++;
right--;
}
}
```
-----------------------

View File

@ -6,7 +6,7 @@
## 198.打家劫舍
[力扣题目链接](https://leetcode-cn.com/problems/house-robber/)
[力扣题目链接](https://leetcode.cn/problems/house-robber/)
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

View File

@ -10,7 +10,7 @@
# 第202题. 快乐数
[力扣题目链接](https://leetcode-cn.com/problems/happy-number/)
[力扣题目链接](https://leetcode.cn/problems/happy-number/)
编写一个算法来判断一个数 n 是不是快乐数。
@ -315,6 +315,36 @@ class Solution {
}
```
Rust:
```Rust
use std::collections::HashSet;
impl Solution {
pub fn get_sum(mut n: i32) -> i32 {
let mut sum = 0;
while n > 0 {
sum += (n % 10) * (n % 10);
n /= 10;
}
sum
}
pub fn is_happy(n: i32) -> bool {
let mut n = n;
let mut set = HashSet::new();
loop {
let sum = Self::get_sum(n);
if sum == 1 {
return true;
}
if set.contains(&sum) {
return false;
} else { set.insert(sum); }
n = sum;
}
}
}
```
C:
```C
typedef struct HashNodeTag {
@ -417,6 +447,7 @@ object Solution {
}
sum
}
```
C#

View File

@ -9,7 +9,7 @@
# 203.移除链表元素
[力扣题目链接](https://leetcode-cn.com/problems/remove-linked-list-elements/)
[力扣题目链接](https://leetcode.cn/problems/remove-linked-list-elements/)
题意:删除链表中等于给定值 val 的所有节点。
@ -28,6 +28,8 @@
# 思路
为了方便大家理解,我特意录制了视频:[手把手带你学会操作链表,移除链表元素](https://www.bilibili.com/video/BV18B4y1s7R9),结合视频在看本题解,事半功倍。
这里以链表 1 4 2 4 来举例移除元素4。
![203_链表删除元素1](https://img-blog.csdnimg.cn/20210316095351161.png)
@ -395,18 +397,18 @@ function removeElements(head: ListNode | null, val: number): ListNode | null {
```typescript
function removeElements(head: ListNode | null, val: number): ListNode | null {
let dummyHead = new ListNode(0, head);
let pre: ListNode = dummyHead, cur: ListNode | null = dummyHead.next;
// 删除非头部节点
// 添加虚拟节点
const data = new ListNode(0, head);
let pre = data, cur = data.next;
while (cur) {
if (cur.val === val) {
pre.next = cur.next;
pre.next = cur.next
} else {
pre = cur;
}
cur = cur.next;
}
return head.next;
return data.next;
};
```
@ -485,17 +487,19 @@ RUST:
// }
impl Solution {
pub fn remove_elements(head: Option<Box<ListNode>>, val: i32) -> Option<Box<ListNode>> {
let mut head = head;
let mut dummy_head = ListNode::new(0);
let mut cur = &mut dummy_head;
while let Some(mut node) = head {
head = std::mem::replace(&mut node.next, None);
if node.val != val {
cur.next = Some(node);
let mut dummyHead = Box::new(ListNode::new(0));
dummyHead.next = head;
let mut cur = dummyHead.as_mut();
// 使用take()替换std::men::replace(&mut node.next, None)达到相同的效果,并且更普遍易读
while let Some(nxt) = cur.next.take() {
if nxt.val == val {
cur.next = nxt.next;
} else {
cur.next = Some(nxt);
cur = cur.next.as_mut().unwrap();
}
}
dummy_head.next
dummyHead.next
}
}
```

View File

@ -7,7 +7,7 @@
# 205. 同构字符串
[力扣题目链接](https://leetcode-cn.com/problems/isomorphic-strings/)
[力扣题目链接](https://leetcode.cn/problems/isomorphic-strings/)
给定两个字符串 s  t判断它们是否是同构的。
@ -156,6 +156,28 @@ var isIsomorphic = function(s, t) {
};
```
## TypeScript
```typescript
function isIsomorphic(s: string, t: string): boolean {
const helperMap1: Map<string, string> = new Map();
const helperMap2: Map<string, string> = new Map();
for (let i = 0, length = s.length; i < length; i++) {
let temp1: string | undefined = helperMap1.get(s[i]);
let temp2: string | undefined = helperMap2.get(t[i]);
if (temp1 === undefined && temp2 === undefined) {
helperMap1.set(s[i], t[i]);
helperMap2.set(t[i], s[i]);
} else if (temp1 !== t[i] || temp2 !== s[i]) {
return false;
}
}
return true;
};
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -9,7 +9,7 @@
# 206.反转链表
[力扣题目链接](https://leetcode-cn.com/problems/reverse-linked-list/)
[力扣题目链接](https://leetcode.cn/problems/reverse-linked-list/)
题意:反转一个单链表。
@ -496,8 +496,26 @@ struct ListNode* reverseList(struct ListNode* head){
return reverse(NULL, head);
}
```
Scala:
PHP:
```php
// 双指针法:
function reverseList($head) {
$cur = $head;
$pre = NULL;
while($cur){
$temp = $cur->next;
$cur->next = $pre;
$pre = $cur;
$cur = $temp;
}
return $pre;
}
```
Scala:
双指针法:
```scala
object Solution {
@ -529,6 +547,7 @@ object Solution {
cur.next = pre
reverse(cur, tmp) // 此时cur成为前一个节点tmp是当前节点
}
}
```
-----------------------

View File

@ -5,9 +5,9 @@
<p align="center"><strong><a href="https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A">参与本项目</a>,贡献其他语言版本的代码,拥抱开源,让更多学习算法的小伙伴们收益!</strong></p>
## 209.长度最小的子数组
# 209.长度最小的子数组
[力扣题目链接](https://leetcode-cn.com/problems/minimum-size-subarray-sum/)
[力扣题目链接](https://leetcode.cn/problems/minimum-size-subarray-sum/)
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
@ -17,6 +17,9 @@
输出2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
# 思路
为了易于大家理解,我特意录制了[拿下滑动窗口! | LeetCode 209 长度最小的子数组](https://www.bilibili.com/video/BV1tZ4y1q7XE)
## 暴力解法
@ -47,8 +50,8 @@ public:
}
};
```
时间复杂度O(n^2)
空间复杂度O(1)
* 时间复杂度O(n^2)
* 空间复杂度O(1)
## 滑动窗口
@ -56,6 +59,20 @@ public:
所谓滑动窗口,**就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果**。
在暴力解法中是一个for循环滑动窗口的起始位置一个for循环为滑动窗口的终止位置用两个for循环 完成了一个不断搜索区间的过程。
那么滑动窗口如何用一个for循环来完成这个操作呢。
首先要思考 如果用一个for循环那么应该表示 滑动窗口的起始位置,还是终止位置。
如果只用一个for循环来表示 滑动窗口的起始位置,那么如何遍历剩下的终止位置?
此时难免再次陷入 暴力解法的怪圈。
所以 只用一个for循环那么这个循环的索引一定是表示 滑动窗口的终止位置。
那么问题来了, 滑动窗口的起始位置如何移动呢?
这里还是以题目中的示例来举例s=7 数组是 231243来看一下查找的过程
![209.长度最小的子数组](https://code-thinking.cdn.bcebos.com/gifs/209.%E9%95%BF%E5%BA%A6%E6%9C%80%E5%B0%8F%E7%9A%84%E5%AD%90%E6%95%B0%E7%BB%84.gif)
@ -74,7 +91,7 @@ public:
窗口的起始位置如何移动如果当前窗口的值大于s了窗口就要向前移动了也就是该缩小了
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,窗口的起始位置设置为数组的起始位置就可以了
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引
解题的关键在于 窗口的起始位置如何移动,如图所示:
@ -107,8 +124,8 @@ public:
};
```
时间复杂度O(n)
空间复杂度O(1)
* 时间复杂度O(n)
* 空间复杂度O(1)
**一些录友会疑惑为什么时间复杂度是O(n)**。
@ -116,8 +133,8 @@ public:
## 相关题目推荐
* [904.水果成篮](https://leetcode-cn.com/problems/fruit-into-baskets/)
* [76.最小覆盖子串](https://leetcode-cn.com/problems/minimum-window-substring/)
* [904.水果成篮](https://leetcode.cn/problems/fruit-into-baskets/)
* [76.最小覆盖子串](https://leetcode.cn/problems/minimum-window-substring/)
@ -448,6 +465,27 @@ object Solution {
}
}
```
C#:
```csharp
public class Solution {
public int MinSubArrayLen(int s, int[] nums) {
int n = nums.Length;
int ans = int.MaxValue;
int start = 0, end = 0;
int sum = 0;
while (end < n) {
sum += nums[end];
while (sum >= s)
{
ans = Math.Min(ans, end - start + 1);
sum -= nums[start];
start++;
}
end++;
}
return ans == int.MaxValue ? 0 : ans;
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -6,7 +6,7 @@
## 213.打家劫舍II
[力扣题目链接](https://leetcode-cn.com/problems/house-robber-ii/)
[力扣题目链接](https://leetcode.cn/problems/house-robber-ii/)
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。

View File

@ -11,7 +11,7 @@
# 216.组合总和III
[力扣题目链接](https://leetcode-cn.com/problems/combination-sum-iii/)
[力扣题目链接](https://leetcode.cn/problems/combination-sum-iii/)
找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。
@ -360,39 +360,30 @@ func backTree(n,k,startIndex int,track *[]int,result *[][]int){
## javaScript
```js
// 等差数列
var maxV = k => k * (9 + 10 - k) / 2;
var minV = k => k * (1 + k) / 2;
/**
* @param {number} k
* @param {number} n
* @return {number[][]}
*/
var combinationSum3 = function(k, n) {
if (k > 9 || k < 1) return [];
// if (n > maxV(k) || n < minV(k)) return [];
// if (n === maxV(k)) return [Array.from({length: k}).map((v, i) => 9 - i)];
// if (n === minV(k)) return [Array.from({length: k}).map((v, i) => i + 1)];
const res = [], path = [];
backtracking(k, n, 1, 0);
return res;
function backtracking(k, n, i, sum){
const len = path.length;
if (len > k || sum > n) return;
if (maxV(k - len) < n - sum) return;
if (minV(k - len) > n - sum) return;
if(len === k && sum == n) {
res.push(Array.from(path));
const backtrack = (start) => {
const l = path.length;
if (l === k) {
const sum = path.reduce((a, b) => a + b);
if (sum === n) {
res.push([...path]);
}
return;
}
const min = Math.min(n - sum, 9 + len - k + 1);
for(let a = i; a <= min; a++) {
path.push(a);
sum += a;
backtracking(k, n, a + 1, sum);
for (let i = start; i <= 9 - (k - l) + 1; i++) {
path.push(i);
backtrack(i + 1);
path.pop();
sum -= a;
}
}
let res = [], path = [];
backtrack(1);
return res;
};
```
@ -420,6 +411,35 @@ function combinationSum3(k: number, n: number): number[][] {
};
```
## Rust
```Rust
impl Solution {
fn backtracking(result: &mut Vec<Vec<i32>>, path:&mut Vec<i32>, targetSum:i32, k: i32, mut sum: i32, startIndex: i32) {
let len = path.len() as i32;
if len == k {
if sum == targetSum {
result.push(path.to_vec());
}
return;
}
for i in startIndex..=9 {
sum += i;
path.push(i);
Self::backtracking(result, path, targetSum, k, sum, i+1);
sum -= i;
path.pop();
}
}
pub fn combination_sum3(k: i32, n: i32) -> Vec<Vec<i32>> {
let mut result: Vec<Vec<i32>> = Vec::new();
let mut path: Vec<i32> = Vec::new();
Self::backtracking(&mut result, &mut path, n, k, 0, 1);
result
}
}
```
## C
```c
@ -511,5 +531,35 @@ func combinationSum3(_ count: Int, _ targetSum: Int) -> [[Int]] {
}
```
## Scala
```scala
object Solution {
import scala.collection.mutable
def combinationSum3(k: Int, n: Int): List[List[Int]] = {
var result = mutable.ListBuffer[List[Int]]()
var path = mutable.ListBuffer[Int]()
def backtracking(k: Int, n: Int, sum: Int, startIndex: Int): Unit = {
if (sum > n) return // 剪枝如果sum>目标和,就返回
if (sum == n && path.size == k) {
result.append(path.toList)
return
}
// 剪枝
for (i <- startIndex to (9 - (k - path.size) + 1)) {
path.append(i)
backtracking(k, n, sum + i, i + 1)
path = path.take(path.size - 1)
}
}
backtracking(k, n, 0, 1) // 调用递归方法
result.toList // 最终返回结果集的List形式
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -7,7 +7,7 @@
# 222.完全二叉树的节点个数
[力扣题目链接](https://leetcode-cn.com/problems/count-complete-tree-nodes/)
[力扣题目链接](https://leetcode.cn/problems/count-complete-tree-nodes/)
给出一个完全二叉树,求出该树的节点个数。
@ -646,5 +646,68 @@ func countNodes(_ root: TreeNode?) -> Int {
}
```
## Scala
递归:
```scala
object Solution {
def countNodes(root: TreeNode): Int = {
if(root == null) return 0
1 + countNodes(root.left) + countNodes(root.right)
}
}
```
层序遍历:
```scala
object Solution {
import scala.collection.mutable
def countNodes(root: TreeNode): Int = {
if (root == null) return 0
val queue = mutable.Queue[TreeNode]()
var node = 0
queue.enqueue(root)
while (!queue.isEmpty) {
val len = queue.size
for (i <- 0 until len) {
node += 1
val curNode = queue.dequeue()
if (curNode.left != null) queue.enqueue(curNode.left)
if (curNode.right != null) queue.enqueue(curNode.right)
}
}
node
}
}
```
利用完全二叉树性质:
```scala
object Solution {
def countNodes(root: TreeNode): Int = {
if (root == null) return 0
var leftNode = root.left
var rightNode = root.right
// 向左向右往下探
var leftDepth = 0
while (leftNode != null) {
leftDepth += 1
leftNode = leftNode.left
}
var rightDepth = 0
while (rightNode != null) {
rightDepth += 1
rightNode = rightNode.right
}
// 如果相等就是一个满二叉树
if (leftDepth == rightDepth) {
return (2 << leftDepth) - 1
}
// 如果不相等就不是一个完全二叉树,继续向下递归
countNodes(root.left) + countNodes(root.right) + 1
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -10,7 +10,7 @@
# 225. 用队列实现栈
[力扣题目链接](https://leetcode-cn.com/problems/implement-stack-using-queues/)
[力扣题目链接](https://leetcode.cn/problems/implement-stack-using-queues/)
使用队列实现栈的下列操作:
@ -816,7 +816,6 @@ class MyStack {
}
```
Scala:
使用两个队列模拟栈:
```scala
import scala.collection.mutable
@ -897,6 +896,86 @@ class MyStack() {
def empty(): Boolean = {
queue.isEmpty
}
}
```
PHP
> 双对列
```php
// SplQueue 类通过使用一个双向链表来提供队列的主要功能。(PHP 5 >= 5.3.0, PHP 7, PHP 8)
// https://www.php.net/manual/zh/class.splqueue.php
class MyStack {
public $queueMain; // 保存数据
public $queueTmp; // 辅助作用
function __construct() {
$this->queueMain=new SplQueue();
$this->queueTmp=new SplQueue();
}
// queueMain: 1,2,3 <= add
function push($x) {
$this->queueMain->enqueue($x);
}
function pop() {
$qmSize = $this->queueMain->Count();
$qmSize --;
// queueMain: 3,2,1 => pop =>2,1 => add => 2,1 :queueTmp
while($qmSize --){
$this->queueTmp->enqueue($this->queueMain->dequeue());
}
// queueMain: 3
$val = $this->queueMain->dequeue();
// queueMain <= queueTmp
$this->queueMain = $this->queueTmp;
// 清空queueTmp,下次使用
$this->queueTmp = new SplQueue();
return $val;
}
function top() {
// 底层是双链表实现:从双链表的末尾查看节点
return $this->queueMain->top();
}
function empty() {
return $this->queueMain->isEmpty();
}
}
```
> 单对列
```php
class MyStack {
public $queue;
function __construct() {
$this->queue=new SplQueue();
}
function push($x) {
$this->queue->enqueue($x);
}
function pop() {
$qmSize = $this->queue->Count();
$qmSize --;
//queue: 3,2,1 => pop =>2,1 => add => 2,1,3 :queue
while($qmSize --){
$this->queue->enqueue($this->queue->dequeue());
}
$val = $this->queue->dequeue();
return $val;
}
function top() {
return $this->queue->top();
}
function empty() {
return $this->queue->isEmpty();
}
}
```
-----------------------

View File

@ -7,7 +7,7 @@
# 226.翻转二叉树
[力扣题目链接](https://leetcode-cn.com/problems/invert-binary-tree/)
[力扣题目链接](https://leetcode.cn/problems/invert-binary-tree/)
翻转一棵二叉树。
@ -470,25 +470,14 @@ func invertTree(root *TreeNode) *TreeNode {
使用递归版本的前序遍历
```javascript
var invertTree = function(root) {
//1. 首先使用递归版本的前序遍历实现二叉树翻转
//交换节点函数
const inverNode=function(left,right){
let temp=left;
left=right;
right=temp;
//需要重新给root赋值一下
root.left=left;
root.right=right;
// 终止条件
if (!root) {
return null;
}
//确定递归函数的参数和返回值inverTree=function(root)
//确定终止条件
if(root===null){
return root;
}
//确定节点处理逻辑 交换
inverNode(root.left,root.right);
invertTree(root.left);
invertTree(root.right);
// 交换左右节点
const rightNode = root.right;
root.right = invertTree(root.left);
root.left = invertTree(rightNode);
return root;
};
```
@ -818,5 +807,53 @@ func invertTree(_ root: TreeNode?) -> TreeNode? {
}
```
### Scala
深度优先遍历(前序遍历):
```scala
object Solution {
def invertTree(root: TreeNode): TreeNode = {
if (root == null) return root
// 递归
def process(node: TreeNode): Unit = {
if (node == null) return
// 翻转节点
val curNode = node.left
node.left = node.right
node.right = curNode
process(node.left)
process(node.right)
}
process(root)
root
}
}
```
广度优先遍历(层序遍历):
```scala
object Solution {
import scala.collection.mutable
def invertTree(root: TreeNode): TreeNode = {
if (root == null) return root
val queue = mutable.Queue[TreeNode]()
queue.enqueue(root)
while (!queue.isEmpty) {
val len = queue.size
for (i <- 0 until len) {
var curNode = queue.dequeue()
if (curNode.left != null) queue.enqueue(curNode.left)
if (curNode.right != null) queue.enqueue(curNode.right)
// 翻转
var tmpNode = curNode.left
curNode.left = curNode.right
curNode.right = tmpNode
}
}
root
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -9,7 +9,7 @@
# 232.用栈实现队列
[力扣题目链接](https://leetcode-cn.com/problems/implement-queue-using-stacks/)
[力扣题目链接](https://leetcode.cn/problems/implement-queue-using-stacks/)
使用栈实现队列的下列操作:
@ -495,6 +495,53 @@ void myQueueFree(MyQueue* obj) {
obj->stackOutTop = 0;
}
```
PHP:
```php
// SplStack 类通过使用一个双向链表来提供栈的主要功能。[PHP 5 >= 5.3.0, PHP 7, PHP 8]
// https://www.php.net/manual/zh/class.splstack.php
class MyQueue {
// 双栈模拟队列In栈存储数据Out栈辅助处理
private $stackIn;
private $stackOut;
function __construct() {
$this->stackIn = new SplStack();
$this->stackOut = new SplStack();
}
// In: 1 2 3 <= push
function push($x) {
$this->stackIn->push($x);
}
function pop() {
$this->peek();
return $this->stackOut->pop();
}
function peek() {
if($this->stackOut->isEmpty()){
$this->shift();
}
return $this->stackOut->top();
}
function empty() {
return $this->stackOut->isEmpty() && $this->stackIn->isEmpty();
}
// 如果Out栈为空把In栈数据压入Out栈
// In: 1 2 3 => pop push => 1 2 3 :Out
private function shift(){
while(!$this->stackIn->isEmpty()){
$this->stackOut->push($this->stackIn->pop());
}
}
}
```
Scala:
```scala
class MyQueue() {
@ -533,6 +580,7 @@ class MyQueue() {
def empty(): Boolean = {
stackIn.isEmpty && stackOut.isEmpty
}
}
```
-----------------------

View File

@ -7,7 +7,7 @@
# 234.回文链表
[力扣题目链接](https://leetcode-cn.com/problems/palindrome-linked-list/)
[力扣题目链接](https://leetcode.cn/problems/palindrome-linked-list/)
请判断一个链表是否为回文链表。
@ -273,7 +273,7 @@ class Solution:
return pre
```
## Go
### Go
```go
@ -319,6 +319,63 @@ var isPalindrome = function(head) {
};
```
### TypeScript
> 数组模拟
```typescript
function isPalindrome(head: ListNode | null): boolean {
const helperArr: number[] = [];
let curNode: ListNode | null = head;
while (curNode !== null) {
helperArr.push(curNode.val);
curNode = curNode.next;
}
let left: number = 0,
right: number = helperArr.length - 1;
while (left < right) {
if (helperArr[left++] !== helperArr[right--]) return false;
}
return true;
};
```
> 反转后半部分链表
```typescript
function isPalindrome(head: ListNode | null): boolean {
if (head === null || head.next === null) return true;
let fastNode: ListNode | null = head,
slowNode: ListNode = head,
preNode: ListNode = head;
while (fastNode !== null && fastNode.next !== null) {
preNode = slowNode;
slowNode = slowNode.next!;
fastNode = fastNode.next.next;
}
preNode.next = null;
let cur1: ListNode | null = head;
let cur2: ListNode | null = reverseList(slowNode);
while (cur1 !== null) {
if (cur1.val !== cur2!.val) return false;
cur1 = cur1.next;
cur2 = cur2!.next;
}
return true;
};
function reverseList(head: ListNode | null): ListNode | null {
let curNode: ListNode | null = head,
preNode: ListNode | null = null;
while (curNode !== null) {
let tempNode: ListNode | null = curNode.next;
curNode.next = preNode;
preNode = curNode;
curNode = tempNode;
}
return preNode;
}
```
-----------------------

View File

@ -7,7 +7,7 @@
# 235. 二叉搜索树的最近公共祖先
[力扣题目链接](https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree/)
[力扣题目链接](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/)
给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。
@ -381,7 +381,36 @@ function lowestCommonAncestor(root: TreeNode | null, p: TreeNode | null, q: Tree
};
```
## Scala
递归:
```scala
object Solution {
def lowestCommonAncestor(root: TreeNode, p: TreeNode, q: TreeNode): TreeNode = {
// scala中每个关键字都有其返回值于是可以不写return
if (root.value > p.value && root.value > q.value) lowestCommonAncestor(root.left, p, q)
else if (root.value < p.value && root.value < q.value) lowestCommonAncestor(root.right, p, q)
else root
}
}
```
迭代:
```scala
object Solution {
def lowestCommonAncestor(root: TreeNode, p: TreeNode, q: TreeNode): TreeNode = {
var curNode = root // 因为root是不可变量所以要赋值给curNode一个可变量
while(curNode != null){
if(curNode.value > p.value && curNode.value > q.value) curNode = curNode.left
else if(curNode.value < p.value && curNode.value < q.value) curNode = curNode.right
else return curNode
}
null
}
}
```
-----------------------

View File

@ -9,7 +9,7 @@
# 236. 二叉树的最近公共祖先
[力扣题目链接](https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree/)
[力扣题目链接](https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/)
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
@ -343,7 +343,25 @@ function lowestCommonAncestor(root: TreeNode | null, p: TreeNode | null, q: Tree
};
```
## Scala
```scala
object Solution {
def lowestCommonAncestor(root: TreeNode, p: TreeNode, q: TreeNode): TreeNode = {
// 递归结束条件
if (root == null || root == p || root == q) {
return root
}
var left = lowestCommonAncestor(root.left, p, q)
var right = lowestCommonAncestor(root.right, p, q)
if (left != null && right != null) return root
if (left == null) return right
left
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -10,7 +10,7 @@
# 239. 滑动窗口最大值
[力扣题目链接](https://leetcode-cn.com/problems/sliding-window-maximum/)
[力扣题目链接](https://leetcode.cn/problems/sliding-window-maximum/)
给定一个数组 nums有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
@ -654,8 +654,7 @@ object Solution {
// 最终返回resreturn关键字可以省略
res
}
}
}
class MyQueue {
var queue = ArrayBuffer[Int]()
@ -678,5 +677,84 @@ class MyQueue {
def peek(): Int = queue.head
}
```
PHP:
```php
class Solution {
/**
* @param Integer[] $nums
* @param Integer $k
* @return Integer[]
*/
function maxSlidingWindow($nums, $k) {
$myQueue = new MyQueue();
// 先将前k的元素放进队列
for ($i = 0; $i < $k; $i++) {
$myQueue->push($nums[$i]);
}
$result = [];
$result[] = $myQueue->max(); // result 记录前k的元素的最大值
for ($i = $k; $i < count($nums); $i++) {
$myQueue->pop($nums[$i - $k]); // 滑动窗口移除最前面元素
$myQueue->push($nums[$i]); // 滑动窗口前加入最后面的元素
$result[]= $myQueue->max(); // 记录对应的最大值
}
return $result;
}
}
// 单调对列构建
class MyQueue{
private $queue;
public function __construct(){
$this->queue = new SplQueue(); //底层是双向链表实现。
}
public function pop($v){
// 判断当前对列是否为空
// 比较当前要弹出的数值是否等于队列出口元素的数值,如果相等则弹出。
// bottom 从链表前端查看元素, dequeue 从双向链表的开头移动一个节点
if(!$this->queue->isEmpty() && $v == $this->queue->bottom()){
$this->queue->dequeue(); //弹出队列
}
}
public function push($v){
// 判断当前对列是否为空
// 如果push的数值大于入口元素的数值那么就将队列后端的数值弹出直到push的数值小于等于队列入口元素的数值为止。
// 这样就保持了队列里的数值是单调从大到小的了。
while (!$this->queue->isEmpty() && $v > $this->queue->top()) {
$this->queue->pop(); // pop从链表末尾弹出一个元素
}
$this->queue->enqueue($v);
}
// 查询当前队列里的最大值 直接返回队首
public function max(){
// bottom 从链表前端查看元素, top从链表末尾查看元素
return $this->queue->bottom();
}
// 辅助理解: 打印队列元素
public function println(){
// "迭代器移动到链表头部": 可理解为从头遍历链表元素做准备。
// 【PHP中没有指针概念所以就没说指针。从数据结构上理解就是把指针指向链表头部】
$this->queue->rewind();
echo "Println: ";
while($this->queue->valid()){
echo $this->queue->current()," -> ";
$this->queue->next();
}
echo "\n";
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -9,7 +9,7 @@
## 242.有效的字母异位词
[力扣题目链接](https://leetcode-cn.com/problems/valid-anagram/)
[力扣题目链接](https://leetcode.cn/problems/valid-anagram/)
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

View File

@ -9,7 +9,7 @@
# 257. 二叉树的所有路径
[力扣题目链接](https://leetcode-cn.com/problems/binary-tree-paths/)
[力扣题目链接](https://leetcode.cn/problems/binary-tree-paths/)
给定一个二叉树,返回所有从根节点到叶子节点的路径。
@ -702,5 +702,35 @@ func binaryTreePaths(_ root: TreeNode?) -> [String] {
}
```
Scala:
递归:
```scala
object Solution {
import scala.collection.mutable.ListBuffer
def binaryTreePaths(root: TreeNode): List[String] = {
val res = ListBuffer[String]()
def traversal(curNode: TreeNode, path: ListBuffer[Int]): Unit = {
path.append(curNode.value)
if (curNode.left == null && curNode.right == null) {
res.append(path.mkString("->")) // mkString函数: 将数组的所有值按照指定字符串拼接
return // 处理完可以直接return
}
if (curNode.left != null) {
traversal(curNode.left, path)
path.remove(path.size - 1)
}
if (curNode.right != null) {
traversal(curNode.right, path)
path.remove(path.size - 1)
}
}
traversal(root, ListBuffer[Int]())
res.toList
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -7,7 +7,7 @@
## 279.完全平方数
[力扣题目链接](https://leetcode-cn.com/problems/perfect-squares/)
[力扣题目链接](https://leetcode.cn/problems/perfect-squares/)
给定正整数 n找到若干个完全平方数比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。

View File

@ -8,7 +8,7 @@
# 283. 移动零
[力扣题目链接](https://leetcode-cn.com/problems/move-zeroes/)
[力扣题目链接](https://leetcode.cn/problems/move-zeroes/)
给定一个数组 nums编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
@ -133,6 +133,27 @@ var moveZeroes = function(nums) {
};
```
TypeScript
```typescript
function moveZeroes(nums: number[]): void {
const length: number = nums.length;
let slowIndex: number = 0,
fastIndex: number = 0;
while (fastIndex < length) {
if (nums[fastIndex] !== 0) {
nums[slowIndex++] = nums[fastIndex];
};
fastIndex++;
}
while (slowIndex < length) {
nums[slowIndex++] = 0;
}
};
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

View File

@ -6,7 +6,7 @@
## 300.最长递增子序列
[力扣题目链接](https://leetcode-cn.com/problems/longest-increasing-subsequence/)
[力扣题目链接](https://leetcode.cn/problems/longest-increasing-subsequence/)
给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

View File

@ -6,7 +6,7 @@
## 309.最佳买卖股票时机含冷冻期
[力扣题目链接](https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/)
[力扣题目链接](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-with-cooldown/)
给定一个整数数组其中第 i 个元素代表了第 i 天的股票价格 。

View File

@ -7,7 +7,7 @@
## 322. 零钱兑换
[力扣题目链接](https://leetcode-cn.com/problems/coin-change/)
[力扣题目链接](https://leetcode.cn/problems/coin-change/)
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额返回 -1。

View File

@ -9,7 +9,7 @@
# 332.重新安排行程
[力扣题目链接](https://leetcode-cn.com/problems/reconstruct-itinerary/)
[力扣题目链接](https://leetcode.cn/problems/reconstruct-itinerary/)
给定一个机票的字符串二维数组 [from, to],子数组中的两个成员分别表示飞机出发和降落的机场地点,对该行程进行重新规划排序。所有这些机票都属于一个从 JFK肯尼迪国际机场出发的先生所以该行程必须从 JFK 开始。

View File

@ -7,7 +7,7 @@
## 337.打家劫舍 III
[力扣题目链接](https://leetcode-cn.com/problems/house-robber-iii/)
[力扣题目链接](https://leetcode.cn/problems/house-robber-iii/)
在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。

View File

@ -6,7 +6,7 @@
# 343. 整数拆分
[力扣题目链接](https://leetcode-cn.com/problems/integer-break/)
[力扣题目链接](https://leetcode.cn/problems/integer-break/)
给定一个正整数 n将其拆分为至少两个正整数的和并使这些整数的乘积最大化。 返回你可以获得的最大乘积。

View File

@ -10,7 +10,7 @@
# 344.反转字符串
[力扣题目链接](https://leetcode-cn.com/problems/reverse-string/)
[力扣题目链接](https://leetcode.cn/problems/reverse-string/)
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
@ -190,13 +190,13 @@ javaScript:
* @return {void} Do not return anything, modify s in-place instead.
*/
var reverseString = function(s) {
return s.reverse();
//Do not return anything, modify s in-place instead.
reverse(s)
};
var reverseString = function(s) {
var reverse = function(s) {
let l = -1, r = s.length;
while(++l < --r) [s[l], s[r]] = [s[r], s[l]];
return s;
};
```
@ -238,6 +238,22 @@ func reverseString(_ s: inout [Character]) {
```
Rust:
```Rust
impl Solution {
pub fn reverse_string(s: &mut Vec<char>) {
let (mut left, mut right) = (0, s.len()-1);
while left < right {
let temp = s[left];
s[left] = s[right];
s[right] = temp;
left += 1;
right -= 1;
}
}
}
```
C:
```c
void reverseString(char* s, int sSize){
@ -266,6 +282,38 @@ public class Solution
}
}
```
PHP
```php
// 双指针
// 一:
function reverseString(&$s) {
$left = 0;
$right = count($s)-1;
while($left<$right){
$temp = $s[$left];
$s[$left] = $s[$right];
$s[$right] = $temp;
$left++;
$right--;
}
}
// 二:
function reverseString(&$s) {
$this->reverse($s,0,count($s)-1);
}
// 按指定位置交换元素
function reverse(&$s, $start, $end) {
for ($i = $start, $j = $end; $i < $j; $i++, $j--) {
$tmp = $s[$i];
$s[$i] = $s[$j];
$s[$j] = $tmp;
}
}
```
Scala:
```scala
object Solution {

View File

@ -11,7 +11,7 @@
# 347.前 K 个高频元素
[力扣题目链接](https://leetcode-cn.com/problems/top-k-frequent-elements/)
[力扣题目链接](https://leetcode.cn/problems/top-k-frequent-elements/)
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
@ -141,13 +141,10 @@ class Solution {
}
Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
// 根据map的value值正序排,相当于一个小顶堆
PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>((o1, o2) -> o1.getValue() - o2.getValue());
// 根据map的value值构建于一个大顶堆o1 - o2: 小顶堆, o2 - o1 : 大顶堆)
PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>((o1, o2) -> o2.getValue() - o1.getValue());
for (Map.Entry<Integer, Integer> entry : entries) {
queue.offer(entry);
if (queue.size() > k) {
queue.poll();
}
}
for (int i = k - 1; i >= 0; i--) {
result[i] = queue.poll().getKey();

View File

@ -12,7 +12,7 @@
## 349. 两个数组的交集
[力扣题目链接](https://leetcode-cn.com/problems/intersection-of-two-arrays/)
[力扣题目链接](https://leetcode.cn/problems/intersection-of-two-arrays/)
题意:给定两个数组,编写一个函数来计算它们的交集。
@ -104,13 +104,8 @@ class Solution {
resSet.add(i);
}
}
int[] resArr = new int[resSet.size()];
int index = 0;
//将结果几何转为数组
for (int i : resSet) {
resArr[index++] = i;
}
return resArr;
return resSet.stream().mapToInt(x -> x).toArray();
}
}
```
@ -356,6 +351,8 @@ object Solution {
}
}
```
C#:
```csharp

View File

@ -9,7 +9,7 @@
# 376. 摆动序列
[力扣题目链接](https://leetcode-cn.com/problems/wiggle-subsequence/)
[力扣题目链接](https://leetcode.cn/problems/wiggle-subsequence/)
如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。
@ -298,6 +298,29 @@ var wiggleMaxLength = function(nums) {
};
```
### Rust
**贪心**
```Rust
impl Solution {
pub fn wiggle_max_length(nums: Vec<i32>) -> i32 {
let len = nums.len() as usize;
if len <= 1 {
return len as i32;
}
let mut preDiff = 0;
let mut curDiff = 0;
let mut result = 1;
for i in 0..len-1 {
curDiff = nums[i+1] - nums[i];
if (preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0) {
result += 1;
preDiff = curDiff;
}
}
result
}
}
```
### C
**贪心**
@ -375,7 +398,31 @@ function wiggleMaxLength(nums: number[]): number {
};
```
### Scala
```scala
object Solution {
def wiggleMaxLength(nums: Array[Int]): Int = {
if (nums.length <= 1) return nums.length
var result = 1
var curDiff = 0 // 当前一对的差值
var preDiff = 0 // 前一对的差值
for (i <- 1 until nums.length) {
curDiff = nums(i) - nums(i - 1) // 计算当前这一对的差值
// 当 curDiff > 0 的情况preDiff <= 0
// 当 curDiff < 0 的情况preDiff >= 0
// 这两种情况算是两个峰值
if ((curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0)) {
result += 1 // 结果集加 1
preDiff = curDiff // 当前差值赋值给上一轮
}
}
result
}
}
```
-----------------------
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>

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