Skip to content

Commit

Permalink
Merge branch 'master' of github.com:jinbudaily/leetcode-master
Browse files Browse the repository at this point in the history
  • Loading branch information
jinbudaily committed Aug 23, 2023
2 parents 660d7bc + 5df6ab7 commit c17e5a9
Show file tree
Hide file tree
Showing 38 changed files with 966 additions and 136 deletions.
6 changes: 3 additions & 3 deletions problems/0001.两数之和.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,20 @@
[242. 有效的字母异位词](https://www.programmercarl.com/0242.有效的字母异位词.html) 这道题目是用数组作为哈希表来解决哈希问题,[349. 两个数组的交集](https://www.programmercarl.com/0349.两个数组的交集.html)这道题目是通过set作为哈希表来解决哈希问题。


首先我在强调一下 **什么时候使用哈希法**,当我们需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法。
首先我再强调一下 **什么时候使用哈希法**,当我们需要查询一个元素是否出现过,或者一个元素是否在集合里的时候,就要第一时间想到哈希法。

本题呢,我就需要一个集合来存放我们遍历过的元素,然后在遍历数组的时候去询问这个集合,某元素是否遍历过,也就是 是否出现在这个集合。

那么我们就应该想到使用哈希法了。

因为本地,我们不仅要知道元素有没有遍历过,还要知道这个元素对应的下标,**需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适**
因为本题,我们不仅要知道元素有没有遍历过,还要知道这个元素对应的下标,**需要使用 key value结构来存放,key来存元素,value来存下标,那么使用map正合适**

再来看一下使用数组和set来做哈希法的局限。

* 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
* set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。

此时就要选择另一种数据结构:map ,map是一种key value的存储结构,可以用key保存数值,用value在保存数值所在的下标
此时就要选择另一种数据结构:map ,map是一种key value的存储结构,可以用key保存数值,用value再保存数值所在的下标

C++中map,有三种类型:

Expand Down
6 changes: 3 additions & 3 deletions problems/0015.三数之和.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ public:

#### a的去重

说道去重,其实主要考虑三个数的去重。 a, b ,c, 对应的就是 nums[i],nums[left],nums[right]
说到去重,其实主要考虑三个数的去重。 a, b ,c, 对应的就是 nums[i],nums[left],nums[right]

a 如果重复了怎么办,a是nums里遍历的元素,那么应该直接跳过去。

Expand All @@ -181,7 +181,7 @@ a 如果重复了怎么办,a是nums里遍历的元素,那么应该直接跳

其实不一样!

都是和 nums[i]进行比较,是比较它的前一个,还是比较他的后一个
都是和 nums[i]进行比较,是比较它的前一个,还是比较它的后一个

如果我们的写法是 这样:

Expand All @@ -191,7 +191,7 @@ if (nums[i] == nums[i + 1]) { // 去重操作
}
```

那就我们就把 三元组中出现重复元素的情况直接pass掉了。 例如{-1, -1 ,2} 这组数据,当遍历到第一个-1 的时候,判断 下一个也是-1,那这组数据就pass了。
那我们就把 三元组中出现重复元素的情况直接pass掉了。 例如{-1, -1 ,2} 这组数据,当遍历到第一个-1 的时候,判断 下一个也是-1,那这组数据就pass了。

**我们要做的是 不能有重复的三元组,但三元组内的元素是可以重复的!**

Expand Down
48 changes: 48 additions & 0 deletions problems/0018.四数之和.md
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,54 @@ object Solution {
}
}
```
### Ruby:

```ruby
def four_sum(nums, target)
#结果集
result = []
nums = nums.sort!

for i in 0..nums.size - 1
return result if i > 0 && nums[i] > target && nums[i] >= 0
#对a进行去重
next if i > 0 && nums[i] == nums[i - 1]

for j in i + 1..nums.size - 1
break if nums[i] + nums[j] > target && nums[i] + nums[j] >= 0
#对b进行去重
next if j > i + 1 && nums[j] == nums[j - 1]
left = j + 1
right = nums.size - 1
while left < right
sum = nums[i] + nums[j] + nums[left] + nums[right]
if sum > target
right -= 1
elsif sum < target
left += 1
else
result << [nums[i], nums[j], nums[left], nums[right]]

#对c进行去重
while left < right && nums[left] == nums[left + 1]
left += 1
end

#对d进行去重
while left < right && nums[right] == nums[right - 1]
right -= 1
end

right -= 1
left += 1
end
end
end
end

return result
end
```
<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
Expand Down
4 changes: 2 additions & 2 deletions problems/0039.组合总和.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ candidates 中的数字可以无限制重复被选取。

如果是多个集合取组合,各个集合之间相互不影响,那么就不用startIndex,例如:[17.电话号码的字母组合](https://programmercarl.com/0017.电话号码的字母组合.html)

**注意以上我只是说求组合的情况,如果是排列问题,又是另一套分析的套路,后面我再讲解排列的时候就重点介绍**
**注意以上我只是说求组合的情况,如果是排列问题,又是另一套分析的套路,后面我在讲解排列的时候会重点介绍**

代码如下:

Expand Down Expand Up @@ -311,7 +311,7 @@ class Solution:

for i in range(startIndex, len(candidates)):
if total + candidates[i] > target:
break
continue
total += candidates[i]
path.append(candidates[i])
self.backtracking(candidates, target, total, i, path, result)
Expand Down
52 changes: 52 additions & 0 deletions problems/0054.螺旋矩阵.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,58 @@ class Solution {
}
```

### Javascript
```
/**
* @param {number[][]} matrix
* @return {number[]}
*/
var spiralOrder = function(matrix) {
let m = matrix.length
let n = matrix[0].length
let startX = startY = 0
let i = 0
let arr = new Array(m*n).fill(0)
let offset = 1
let loop = mid = Math.floor(Math.min(m,n) / 2)
while (loop--) {
let row = startX
let col = startY
// -->
for (; col < n + startY - offset; col++) {
arr[i++] = matrix[row][col]
}
// down
for (; row < m + startX - offset; row++) {
arr[i++] = matrix[row][col]
}
// <--
for (; col > startY; col--) {
arr[i++] = matrix[row][col]
}
for (; row > startX; row--) {
arr[i++] = matrix[row][col]
}
startX++
startY++
offset += 2
}
if (Math.min(m, n) % 2 === 1) {
if (n > m) {
for (let j = mid; j < mid + n - m + 1; j++) {
arr[i++] = matrix[mid][j]
}
} else {
for (let j = mid; j < mid + m - n + 1; j++) {
arr[i++] = matrix[j][mid]
}
}
}
return arr
};
```



<p align="center">
Expand Down
58 changes: 58 additions & 0 deletions problems/0072.编辑距离.md
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,64 @@ int minDistance(char * word1, char * word2){
}
```
Rust:
```rust
impl Solution {
pub fn min_distance(word1: String, word2: String) -> i32 {
let mut dp = vec![vec![0; word2.len() + 1]; word1.len() + 1];
for i in 1..=word2.len() {
dp[0][i] = i;
}
for (j, v) in dp.iter_mut().enumerate().skip(1) {
v[0] = j;
}
for (i, char1) in word1.chars().enumerate() {
for (j, char2) in word2.chars().enumerate() {
if char1 == char2 {
dp[i + 1][j + 1] = dp[i][j];
continue;
}
dp[i + 1][j + 1] = dp[i][j + 1].min(dp[i + 1][j]).min(dp[i][j]) + 1;
}
}
dp[word1.len()][word2.len()] as i32
}
}
```

> 一维 dp
```rust
impl Solution {
pub fn min_distance(word1: String, word2: String) -> i32 {
let mut dp = vec![0; word1.len() + 1];
for (i, v) in dp.iter_mut().enumerate().skip(1) {
*v = i;
}

for char2 in word2.chars() {
// 相当于 dp[i][0] 的初始化
let mut pre = dp[0];
dp[0] += 1; // j = 0, 将前 i 个字符变成空串的个数
for (j, char1) in word1.chars().enumerate() {
let temp = dp[j + 1];
if char1 == char2 {
dp[j + 1] = pre;
} else {
dp[j + 1] = dp[j + 1].min(dp[j]).min(pre) + 1;
}
pre = temp;
}
}

dp[word1.len()] as i32
}
}
```

<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
Expand Down
56 changes: 0 additions & 56 deletions problems/0084.柱状图中最大的矩形.md
Original file line number Diff line number Diff line change
Expand Up @@ -729,62 +729,6 @@ impl Solution {
}
```

Rust

双指针预处理
```rust

impl Solution {
pub fn largest_rectangle_area(v: Vec<i32>) -> i32 {
let n = v.len();
let mut left_smaller_idx = vec![-1; n];
let mut right_smaller_idx = vec![n as i32; n];
for i in 1..n {
let mut mid = i as i32 - 1;
while mid >= 0 && v[mid as usize] >= v[i] {
mid = left_smaller_idx[mid as usize];
}
left_smaller_idx[i] = mid;
}
for i in (0..n-1).rev() {
let mut mid = i + 1;
while mid < n && v[mid] >= v[i] {
mid = right_smaller_idx[mid] as usize;
}
right_smaller_idx[i] = mid as i32;
}
let mut res = 0;
for (idx, &e) in v.iter().enumerate() {
res = res.max((right_smaller_idx[idx] - left_smaller_idx[idx] - 1) * e);
}
dbg!(res)
}
}
```

单调栈
```rust
impl Solution {
pub fn largest_rectangle_area1(mut v: Vec<i32>) -> i32 {
v.insert(0, 0); // 便于使第一个元素能够有左侧<=它的值
v.push(0); // 便于在结束处理最后一个元素后清空残留在栈中的值
let mut res = 0;
let mut stack = vec![]; // 递增的栈
for (idx, &e) in v.iter().enumerate() {
while !stack.is_empty() && v[*stack.last().unwrap()] > e {
let pos = stack.pop().unwrap();
let prev_pos = *stack.last().unwrap();
let s = (idx - prev_pos - 1) as i32 * v[pos];
res = res.max(s);
}
stack.push(idx);
}
res
}
}
```


<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
<img src="../pics/网站星球宣传海报.jpg" width="1000"/>
Expand Down
2 changes: 1 addition & 1 deletion problems/0102.二叉树的层序遍历.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* [102.二叉树的层序遍历](https://leetcode.cn/problems/binary-tree-level-order-traversal/)
* [107.二叉树的层次遍历II](https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/)
* [199.二叉树的右视图](https://leetcode.cn/problems/binary-tree-right-side-view/)
* [637.二叉树的层平均值](https://leetcode.cn/problems/binary-tree-right-side-view/)
* [637.二叉树的层平均值](https://leetcode.cn/problems/average-of-levels-in-binary-tree/)
* [429.N叉树的层序遍历](https://leetcode.cn/problems/n-ary-tree-level-order-traversal/)
* [515.在每个树行中找最大值](https://leetcode.cn/problems/find-largest-value-in-each-tree-row/)
* [116.填充每个节点的下一个右侧节点指针](https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/)
Expand Down
57 changes: 57 additions & 0 deletions problems/0115.不同的子序列.md
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,63 @@ function numDistinct(s: string, t: string): number {
};
```

### Rust:

```rust
impl Solution {
pub fn num_distinct(s: String, t: String) -> i32 {
if s.len() < t.len() {
return 0;
}
let mut dp = vec![vec![0; s.len() + 1]; t.len() + 1];
// i = 0, t 为空字符串,s 作为子序列的个数为 1(删除 s 所有元素)
dp[0] = vec![1; s.len() + 1];
for (i, char_t) in t.chars().enumerate() {
for (j, char_s) in s.chars().enumerate() {
if char_t == char_s {
// t 的前 i 个字符在 s 的前 j 个字符中作为子序列的个数
dp[i + 1][j + 1] = dp[i][j] + dp[i + 1][j];
continue;
}
dp[i + 1][j + 1] = dp[i + 1][j];
}
}
dp[t.len()][s.len()]
}
}
```

> 滚动数组

```rust
impl Solution {
pub fn num_distinct(s: String, t: String) -> i32 {
if s.len() < t.len() {
return 0;
}
let (s, t) = (s.into_bytes(), t.into_bytes());
// 对于 t 为空字符串,s 作为子序列的个数为 1(删除 s 所有元素)
let mut dp = vec![1; s.len() + 1];
for char_t in t {
// dp[i - 1][j - 1],dp[j + 1] 更新之前的值
let mut pre = dp[0];
// 当开始遍历 t,s 的前 0 个字符无法包含任意子序列
dp[0] = 0;
for (j, &char_s) in s.iter().enumerate() {
let temp = dp[j + 1];
if char_t == char_s {
dp[j + 1] = pre + dp[j];
} else {
dp[j + 1] = dp[j];
}
pre = temp;
}
}
dp[s.len()]
}
}
```


<p align="center">
<a href="https://programmercarl.com/other/kstar.html" target="_blank">
Expand Down
Loading

0 comments on commit c17e5a9

Please sign in to comment.