mirror of
https://github.com/youngyangyang04/leetcode-master.git
synced 2025-07-08 16:54:50 +08:00
Merge branch 'youngyangyang04:master' into master
This commit is contained in:
21
README.md
21
README.md
@ -4,9 +4,9 @@
|
||||
👉 推荐 [Gitee同步](https://gitee.com/programmercarl/leetcode-master)
|
||||
|
||||
> 1. **介绍**:本项目是一套完整的刷题计划,旨在帮助大家少走弯路,循序渐进学算法,[关注作者](#关于作者)
|
||||
> 2. **PDF版本** : [「代码随想录」算法精讲 PDF 版本](https://mp.weixin.qq.com/s/NF7NqTD9DU505S6nvR_5Wg) 。
|
||||
> 2. **PDF版本** : [「代码随想录」算法精讲 PDF 版本](https://programmercarl.com/other/algo_pdf.html) 。
|
||||
> 3. **刷题顺序** : README已经将刷题顺序排好了,按照顺序一道一道刷就可以。
|
||||
> 4. **学习社区** : 一起学习打卡/面试技巧/如何选择offer/大厂内推/职场规则/简历修改/技术分享/程序人生。欢迎加入[「代码随想录」知识星球](https://mp.weixin.qq.com/s/QVF6upVMSbgvZy8lHZS3CQ) 。
|
||||
> 4. **学习社区** : 一起学习打卡/面试技巧/如何选择offer/大厂内推/职场规则/简历修改/技术分享/程序人生。欢迎加入[「代码随想录」知识星球](https://programmercarl.com/other/kstar.html) 。
|
||||
> 5. **提交代码**:本项目统一使用C++语言进行讲解,但已经有Java、Python、Go、JavaScript等等多语言版本,感谢[这里的每一位贡献者](https://github.com/youngyangyang04/leetcode-master/graphs/contributors),如果你也想贡献代码点亮你的头像,[点击这里](https://mp.weixin.qq.com/s/tqCxrMEU-ajQumL1i8im9A)了解提交代码的方式。
|
||||
> 6. **转载须知** :以下所有文章皆为我([程序员Carl](https://github.com/youngyangyang04))的原创。引用本项目文章请注明出处,发现恶意抄袭或搬运,会动用法律武器维护自己的权益。让我们一起维护一个良好的技术创作环境!
|
||||
|
||||
@ -564,14 +564,14 @@
|
||||
|
||||
# 关于作者
|
||||
|
||||
大家好,我是程序员Carl,哈工大师兄,ACM 校赛、黑龙江省赛、东北四省赛金牌、亚洲区域赛铜牌获得者,先后在腾讯和百度从事后端技术研发,CSDN博客专家。对算法和C++后端技术有一定的见解,利用工作之余重新刷leetcode。
|
||||
大家好,我是程序员Carl,哈工大师兄,《代码随想录》作者,先后在腾讯和百度从事后端技术研发,CSDN博客专家。对算法和C++后端技术有一定的见解,利用工作之余重新刷leetcode。
|
||||
|
||||
加入刷题微信群,备注:「个人简单介绍」 + 组队刷题
|
||||
加入「代码随想录」刷题小分队(微信群),可以扫下方二维码加我微信。
|
||||
|
||||
也欢迎与我交流,备注:「个人简单介绍」 + 交流,围观朋友圈,做点赞之交(备注没有自我介绍不通过哦)
|
||||
如果是已工作,备注:姓名-城市-岗位-组队刷题。如果学生,备注:姓名-学校-年级-组队刷题。**备注没有自我介绍不通过哦**
|
||||
|
||||
<div align="center"><img src="https://code-thinking-1253855093.file.myqcloud.com/pics/20220102204804.png" data-img="1" width="200" height="200"></img></div>
|
||||
|
||||
<a name="微信"></a>
|
||||
<div align="center"><img src="https://code-thinking-1253855093.file.myqcloud.com/pics/20211230153955.png" data-img="1" width="200" height="200"></img></div>
|
||||
|
||||
|
||||
# 公众号
|
||||
@ -585,10 +585,3 @@
|
||||
<a name="公众号"></a>
|
||||
<div align="center"><img src="https://code-thinking-1253855093.file.myqcloud.com/pics/20211026122841.png" data-img="1" width="650" height="500"></img></div>
|
||||
|
||||
# 服务器
|
||||
|
||||
<p align="center"><strong>阿里云服务器,双11特价活动🔥🔥🔥🔥</p>
|
||||
<p align="center">
|
||||
<a href="https://www.aliyun.com/minisite/goods?taskPkg=1111ydsrwb&pkgSid=1959&recordId=962642&userCode=roof0wob" target="_blank">
|
||||
<img src="./pics/阿里云.png" width="1000"/>
|
||||
</a>
|
||||
|
@ -197,7 +197,23 @@ var removeElement = (nums, val) => {
|
||||
};
|
||||
```
|
||||
|
||||
TypeScript:
|
||||
|
||||
```typescript
|
||||
function removeElement(nums: number[], val: number): number {
|
||||
let slowIndex: number = 0, fastIndex: number = 0;
|
||||
while (fastIndex < nums.length) {
|
||||
if (nums[fastIndex] !== val) {
|
||||
nums[slowIndex++] = nums[fastIndex];
|
||||
}
|
||||
fastIndex++;
|
||||
}
|
||||
return slowIndex;
|
||||
};
|
||||
```
|
||||
|
||||
Ruby:
|
||||
|
||||
```ruby
|
||||
def remove_element(nums, val)
|
||||
i = 0
|
||||
|
@ -649,6 +649,41 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
```Java
|
||||
class Solution {
|
||||
//前缀表(不减一)Java实现
|
||||
public int strStr(String haystack, String needle) {
|
||||
if (needle.length() == 0) return 0;
|
||||
int[] next = new int[needle.length()];
|
||||
getNext(next, needle);
|
||||
|
||||
int j = 0;
|
||||
for (int i = 0; i < haystack.length(); i++) {
|
||||
while (j > 0 && needle.charAt(j) != haystack.charAt(i))
|
||||
j = next[j - 1];
|
||||
if (needle.charAt(j) == haystack.charAt(i))
|
||||
j++;
|
||||
if (j == needle.length())
|
||||
return i - needle.length() + 1;
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
private void getNext(int[] next, String s) {
|
||||
int j = 0;
|
||||
next[0] = 0;
|
||||
for (int i = 1; i < s.length(); i++) {
|
||||
while (j > 0 && s.charAt(j) != s.charAt(i))
|
||||
j = next[j - 1];
|
||||
if (s.charAt(j) == s.charAt(i))
|
||||
j++;
|
||||
next[i] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Python3:
|
||||
|
||||
```python
|
||||
|
@ -255,6 +255,7 @@ public:
|
||||
|
||||
|
||||
## Java
|
||||
**使用标记数组**
|
||||
```Java
|
||||
class Solution {
|
||||
List<List<Integer>> lists = new ArrayList<>();
|
||||
@ -292,6 +293,44 @@ class Solution {
|
||||
}
|
||||
}
|
||||
```
|
||||
**不使用标记数组**
|
||||
```Java
|
||||
class Solution {
|
||||
List<List<Integer>> res = new ArrayList<>();
|
||||
LinkedList<Integer> path = new LinkedList<>();
|
||||
int sum = 0;
|
||||
|
||||
public List<List<Integer>> combinationSum2( int[] candidates, int target ) {
|
||||
//为了将重复的数字都放到一起,所以先进行排序
|
||||
Arrays.sort( candidates );
|
||||
backTracking( candidates, target, 0 );
|
||||
return res;
|
||||
}
|
||||
|
||||
private void backTracking( int[] candidates, int target, int start ) {
|
||||
if ( sum == target ) {
|
||||
res.add( new ArrayList<>( path ) );
|
||||
return;
|
||||
}
|
||||
for ( int i = start; i < candidates.length && sum + candidates[i] <= target; i++ ) {
|
||||
//正确剔除重复解的办法
|
||||
//跳过同一树层使用过的元素
|
||||
if ( i > start && candidates[i] == candidates[i - 1] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sum += candidates[i];
|
||||
path.add( candidates[i] );
|
||||
// i+1 代表当前组内元素只选取一次
|
||||
backTracking( candidates, target, i + 1 );
|
||||
|
||||
int temp = path.getLast();
|
||||
sum -= temp;
|
||||
path.removeLast();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Python
|
||||
**回溯+巧妙去重(省去使用used**
|
||||
@ -384,6 +423,7 @@ class Solution:
|
||||
## Go
|
||||
主要在于如何在回溯中去重
|
||||
|
||||
**使用used数组**
|
||||
```go
|
||||
func combinationSum2(candidates []int, target int) [][]int {
|
||||
var trcak []int
|
||||
@ -423,7 +463,41 @@ func backtracking(startIndex,sum,target int,candidates,trcak []int,res *[][]int,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**不使用used数组**
|
||||
```go
|
||||
func combinationSum2(candidates []int, target int) [][]int {
|
||||
var trcak []int
|
||||
var res [][]int
|
||||
sort.Ints(candidates)
|
||||
backtracking(0,0,target,candidates,trcak,&res)
|
||||
return res
|
||||
}
|
||||
func backtracking(startIndex,sum,target int,candidates,trcak []int,res *[][]int){
|
||||
//终止条件
|
||||
if sum==target{
|
||||
tmp:=make([]int,len(trcak))
|
||||
//拷贝
|
||||
copy(tmp,trcak)
|
||||
//放入结果集
|
||||
*res=append(*res,tmp)
|
||||
return
|
||||
}
|
||||
//回溯
|
||||
for i:=startIndex;i<len(candidates) && sum+candidates[i]<=target;i++{
|
||||
// 若当前树层有使用过相同的元素,则跳过
|
||||
if i>startIndex&&candidates[i]==candidates[i-1]{
|
||||
continue
|
||||
}
|
||||
//更新路径集合和sum
|
||||
trcak=append(trcak,candidates[i])
|
||||
sum+=candidates[i]
|
||||
backtracking(i+1,sum,target,candidates,trcak,res)
|
||||
//回溯
|
||||
trcak=trcak[:len(trcak)-1]
|
||||
sum-=candidates[i]
|
||||
}
|
||||
}
|
||||
```
|
||||
## javaScript
|
||||
|
||||
```js
|
||||
|
@ -422,13 +422,13 @@ class Solution:
|
||||
def backtrack(n,k,startIndex):
|
||||
if len(path) == k:
|
||||
res.append(path[:])
|
||||
return
|
||||
return
|
||||
for i in range(startIndex,n - (k - len(path)) + 2): #优化的地方
|
||||
path.append(i) #处理节点
|
||||
backtrack(n,k,i+1) #递归
|
||||
path.pop() #回溯,撤销处理的节点
|
||||
backtrack(n,k,1)
|
||||
return res
|
||||
backtrack(n,k,1)
|
||||
return res
|
||||
```
|
||||
|
||||
|
||||
|
@ -182,13 +182,13 @@ class Solution:
|
||||
def backtrack(n,k,startIndex):
|
||||
if len(path) == k:
|
||||
res.append(path[:])
|
||||
return
|
||||
return
|
||||
for i in range(startIndex,n-(k-len(path))+2): #优化的地方
|
||||
path.append(i) #处理节点
|
||||
backtrack(n,k,i+1) #递归
|
||||
path.pop() #回溯,撤销处理的节点
|
||||
backtrack(n,k,1)
|
||||
return res
|
||||
backtrack(n,k,1)
|
||||
return res
|
||||
```
|
||||
Go:
|
||||
```Go
|
||||
|
@ -166,7 +166,7 @@ if (i > startIndex && nums[i] == nums[i - 1] ) {
|
||||
|
||||
|
||||
### Java
|
||||
|
||||
使用used数组
|
||||
```java
|
||||
class Solution {
|
||||
List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合
|
||||
@ -202,6 +202,37 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
不使用used数组
|
||||
```java
|
||||
class Solution {
|
||||
|
||||
List<List<Integer>> res = new ArrayList<>();
|
||||
LinkedList<Integer> path = new LinkedList<>();
|
||||
|
||||
public List<List<Integer>> subsetsWithDup( int[] nums ) {
|
||||
Arrays.sort( nums );
|
||||
subsetsWithDupHelper( nums, 0 );
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
private void subsetsWithDupHelper( int[] nums, int start ) {
|
||||
res.add( new ArrayList<>( path ) );
|
||||
|
||||
for ( int i = start; i < nums.length; i++ ) {
|
||||
// 跳过当前树层使用过的、相同的元素
|
||||
if ( i > start && nums[i - 1] == nums[i] ) {
|
||||
continue;
|
||||
}
|
||||
path.add( nums[i] );
|
||||
subsetsWithDupHelper( nums, i + 1 );
|
||||
path.removeLast();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### Python
|
||||
```python
|
||||
class Solution:
|
||||
|
@ -107,7 +107,7 @@ public:
|
||||
};
|
||||
```
|
||||
|
||||
时间复杂度:$O(n)$
|
||||
时间复杂度:$O(n)$
|
||||
空间复杂度:$O(1)$
|
||||
|
||||
**一些录友会疑惑为什么时间复杂度是$O(n)$**。
|
||||
@ -121,7 +121,6 @@ public:
|
||||
|
||||
|
||||
|
||||
|
||||
## 其他语言版本
|
||||
|
||||
|
||||
@ -214,6 +213,28 @@ var minSubArrayLen = function(target, nums) {
|
||||
};
|
||||
```
|
||||
|
||||
Typescript:
|
||||
|
||||
```typescript
|
||||
function minSubArrayLen(target: number, nums: number[]): number {
|
||||
let left: number = 0, right: number = 0;
|
||||
let res: number = nums.length + 1;
|
||||
let sum: number = 0;
|
||||
while (right < nums.length) {
|
||||
sum += nums[right];
|
||||
if (sum >= target) {
|
||||
// 不断移动左指针,直到不能再缩小为止
|
||||
while (sum - nums[left] >= target) {
|
||||
sum -= nums[left++];
|
||||
}
|
||||
res = Math.min(res, right - left + 1);
|
||||
}
|
||||
right++;
|
||||
}
|
||||
return res === nums.length + 1 ? 0 : res;
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
@ -291,5 +312,23 @@ class Solution {
|
||||
}
|
||||
```
|
||||
|
||||
Ruby:
|
||||
|
||||
```ruby
|
||||
def min_sub_array_len(target, nums)
|
||||
res = Float::INFINITY # 无穷大
|
||||
i, sum = 0, 0
|
||||
nums.length.times do |j|
|
||||
sum += nums[j]
|
||||
while sum >= target
|
||||
res = [res, j - i + 1].min
|
||||
sum -= nums[i]
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
res == Float::INFINITY ? 0 : res
|
||||
end
|
||||
```
|
||||
|
||||
-----------------------
|
||||
<div align="center"><img src=https://code-thinking.cdn.bcebos.com/pics/01二维码一.jpg width=500> </img></div>
|
||||
|
@ -323,7 +323,6 @@ class Solution:
|
||||
self.backtracking(k, n, i + 1)
|
||||
self.path.pop()
|
||||
self.sum_now -= i
|
||||
return
|
||||
```
|
||||
|
||||
## Go
|
||||
|
@ -80,7 +80,7 @@ return treeNum;
|
||||
class Solution {
|
||||
private:
|
||||
int getNodesNum(TreeNode* cur) {
|
||||
if (cur == 0) return 0;
|
||||
if (cur == NULL) return 0;
|
||||
int leftNum = getNodesNum(cur->left); // 左
|
||||
int rightNum = getNodesNum(cur->right); // 右
|
||||
int treeNum = leftNum + rightNum + 1; // 中
|
||||
|
@ -93,7 +93,7 @@ dp[i][3] = dp[i - 1][2];
|
||||
综上分析,递推代码如下:
|
||||
|
||||
```CPP
|
||||
dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][3], dp[i - 1][1]) - prices[i];
|
||||
dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][3], dp[i - 1][1]) - prices[i]);
|
||||
dp[i][1] = max(dp[i - 1][1], dp[i - 1][3]);
|
||||
dp[i][2] = dp[i - 1][0] + prices[i];
|
||||
dp[i][3] = dp[i - 1][2];
|
||||
|
@ -284,7 +284,6 @@ func search(nums []int, target int) int {
|
||||
* @param {number} target
|
||||
* @return {number}
|
||||
*/
|
||||
/**
|
||||
var search = function(nums, target) {
|
||||
let left = 0, right = nums.length - 1;
|
||||
// 使用左闭右闭区间
|
||||
@ -326,6 +325,46 @@ var search = function(nums, target) {
|
||||
};
|
||||
```
|
||||
|
||||
**TypeScript**
|
||||
|
||||
(版本一)左闭右闭区间
|
||||
|
||||
```typescript
|
||||
function search(nums: number[], target: number): number {
|
||||
let left: number = 0, right: number = nums.length - 1;
|
||||
while (left <= right) {
|
||||
let mid: number = left + Math.floor((right - left) / 2);
|
||||
if (nums[mid] > target) {
|
||||
right = mid - 1;
|
||||
} else if (nums[mid] < target) {
|
||||
left = mid + 1;
|
||||
} else {
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
```
|
||||
|
||||
(版本二)左闭右开区间
|
||||
|
||||
```typescript
|
||||
function search(nums: number[], target: number): number {
|
||||
let left: number = 0, right: number = nums.length;
|
||||
while (left < right) {
|
||||
let mid: number = left + Math.floor((right - left) / 2);
|
||||
if (nums[mid] > target) {
|
||||
right = mid;
|
||||
} else if (nums[mid] < target) {
|
||||
left = mid + 1;
|
||||
} else {
|
||||
return mid;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
```
|
||||
|
||||
**Ruby:**
|
||||
|
||||
```ruby
|
||||
|
@ -221,6 +221,35 @@ var sortedSquares = function(nums) {
|
||||
};
|
||||
```
|
||||
|
||||
Typescript:
|
||||
|
||||
双指针法:
|
||||
|
||||
```typescript
|
||||
function sortedSquares(nums: number[]): number[] {
|
||||
let left: number = 0, right: number = nums.length - 1;
|
||||
let resArr: number[] = new Array(nums.length);
|
||||
let resArrIndex: number = resArr.length - 1;
|
||||
while (left <= right) {
|
||||
if (Math.abs(nums[left]) < Math.abs(nums[right])) {
|
||||
resArr[resArrIndex] = nums[right--] ** 2;
|
||||
} else {
|
||||
resArr[resArrIndex] = nums[left++] ** 2;
|
||||
}
|
||||
resArrIndex--;
|
||||
}
|
||||
return resArr;
|
||||
};
|
||||
```
|
||||
|
||||
骚操作法(暴力思路):
|
||||
|
||||
```typescript
|
||||
function sortedSquares(nums: number[]): number[] {
|
||||
return nums.map(i => i * i).sort((a, b) => a - b);
|
||||
};
|
||||
```
|
||||
|
||||
Swift:
|
||||
|
||||
```swift
|
||||
|
Reference in New Issue
Block a user