Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 3ee636e

Browse files
Update
1 parent 8e3f6e8 commit 3ee636e

File tree

9 files changed

+390
-6
lines changed

9 files changed

+390
-6
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,10 +349,14 @@ int countNodes(TreeNode* root) {
349349
|[0027.移除元素](https://github.com/youngyangyang04/leetcode/blob/master/problems/0027.移除元素.md) |数组 |简单| **暴力** **双指针/快慢指针/双指针**|
350350
|[0028.实现strStr()](https://github.com/youngyangyang04/leetcode/blob/master/problems/0028.实现strStr().md) |字符串 |简单| **KMP** |
351351
|[0035.搜索插入位置](https://github.com/youngyangyang04/leetcode/blob/master/problems/0035.搜索插入位置.md) |数组 |简单| **暴力** **二分**|
352+
|[0039.组合总和](https://github.com/youngyangyang04/leetcode/blob/master/problems/0039.组合总和.md) |数组/回溯 |中等| **回溯**|
353+
|[0040.组合总和II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0040.组合总和II.md) |数组/回溯 |中等| **回溯**|
352354
|[0046.全排列](https://github.com/youngyangyang04/leetcode/blob/master/problems/0046.全排列.md) |回溯|中等| **回溯**|
353355
|[0047.全排列II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0047.全排列II.md) |回溯|中等| **回溯**|
354356
|[0053.最大子序和](https://github.com/youngyangyang04/leetcode/blob/master/problems/0053.最大子序和.md) |数组 |简单|**暴力** **贪心** 动态规划 分治|
355357
|[0059.螺旋矩阵II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0059.螺旋矩阵II.md) |数组 |中等|**模拟**|
358+
|[0077.组合](https://github.com/youngyangyang04/leetcode/blob/master/problems/0077.组合.md) |回溯 |中等|**回溯**|
359+
|[0078.子集](https://github.com/youngyangyang04/leetcode/blob/master/problems/0078.子集.md) |回溯/数组 |中等|**回溯**|
356360
|[0083.删除排序链表中的重复元素](https://github.com/youngyangyang04/leetcode/blob/master/problems/0083.删除排序链表中的重复元素.md) |链表 |简单|**模拟**|
357361
|[0093.复原IP地址](https://github.com/youngyangyang04/leetcode/blob/master/problems/0093.复原IP地址) |回溯 |中等|**回溯**|
358362
|[0094.二叉树的中序遍历](https://github.com/youngyangyang04/leetcode/blob/master/problems/0094.二叉树的中序遍历.md) ||中等|**递归** **迭代/栈**|
@@ -375,6 +379,7 @@ int countNodes(TreeNode* root) {
375379
|[0205.同构字符串](https://github.com/youngyangyang04/leetcode/blob/master/problems/0205.同构字符串.md) |哈希表 |简单| **哈希**|
376380
|[0206.翻转链表](https://github.com/youngyangyang04/leetcode/blob/master/problems/0206.翻转链表.md) |链表 |简单| **双指针法** **递归**|
377381
|[0209.长度最小的子数组](https://github.com/youngyangyang04/leetcode/blob/master/problems/0209.长度最小的子数组.md) |数组 |中等| **暴力** **滑动窗口**|
382+
|[0216.组合总和III](https://github.com/youngyangyang04/leetcode/blob/master/problems/0216.组合总和III.md) |数组/回溯 |中等| **回溯**|
378383
|[0219.存在重复元素II](https://github.com/youngyangyang04/leetcode/blob/master/problems/0219.存在重复元素II.md) | 哈希表 |简单| **哈希** |
379384
|[0222.完全二叉树的节点个数](https://github.com/youngyangyang04/leetcode/blob/master/problems/0222.完全二叉树的节点个数.md) ||简单| **递归** |
380385
|[0225.用队列实现栈](https://github.com/youngyangyang04/leetcode/blob/master/problems/0225.用队列实现栈.md) | 队列 |简单| **队列** |

pics/90_子集 II.png

43.6 KB
Loading

problems/0001.两数之和.md

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,67 @@
1-
## 题目地址
1+
# 题目地址
22
https://leetcode-cn.com/problems/two-sum/
33

4-
## 思路
4+
> 只用数组和set还是不够的!
5+
6+
# 第1题. 两数之和
7+
8+
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
9+
10+
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
11+
12+
**示例:**
13+
14+
给定 nums = [2, 7, 11, 15], target = 9
15+
16+
因为 nums[0] + nums[1] = 2 + 7 = 9
17+
18+
所以返回 [0, 1]
19+
20+
21+
# 思路
522

623
很明显暴力的解法是两层for循环查找,时间复杂度是O(n^2)。
7-
我们来看一下使用数组和set来做哈希法的局限。
24+
25+
使用哈希法最为合适,之前已经介绍过,数组和set在哈希法中的应用,那么来看一下使用数组和set来做哈希法的局限。
826

927
* 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
10-
* set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下表位置,因为我们要返回x 和 y的下表。所以set 也不能用。
28+
* set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下表位置,因为要返回x 和 y的下表。所以set 也不能用。
29+
30+
此时就要选择另一种数据结构:map ,map是一种key value的存储结构,可以用key保存数值,用value在保存数值所在的下表。
31+
32+
C++中map,有三种类型:
33+
34+
|映射 |底层实现 | 是否有序 |数值是否可以重复 | 能否更改数值|查询效率 |增删效率|
35+
|---|---| --- |---| --- | --- | ---|
36+
|std::map |红黑树 |key有序 |key不可重复 |key不可修改 | O(logn)|O(logn) |
37+
|std::multimap | 红黑树|key有序 | key可重复 | key不可修改|O(logn) |O(logn) |
38+
|std::unordered_map |哈希表 | key无序 |key不可重复 |key不可修改 |O(1) | O(1)|
39+
40+
std::unordered_map 底层实现为哈希表,std::map 和std::multimap 的底层实现是红黑树。
41+
42+
同理,std::map 和std::multimap 的key也是有序的(这个问题也经常作为面试题,考察对语言容器底层的理解)。 更多哈希表的理论知识请看[关于哈希表,你该了解这些!](https://mp.weixin.qq.com/s/g8N6WmoQmsCUw3_BaWxHZA)
43+
44+
**这道题目中并不需要key有序,选择std::unordered_map 效率更高!**
1145

12-
此时我们就要选择一种数据结构 map ,map是一种key value的存储结构,我们可以用key保存数值,用value在保存数值所在的下表。
13-
这道题目是map在哈希法中的经典应用
46+
# C++代码
1447

48+
```
49+
class Solution {
50+
public:
51+
vector<int> twoSum(vector<int>& nums, int target) {
52+
std::unordered_map <int,int> map;
53+
for(int i = 0; i < nums.size(); i++) {
54+
auto iter = map.find(target - nums[i]);
55+
if(iter != map.end()) {
56+
return {iter->second, i};
57+
break;
58+
}
59+
map.insert(nums[i], i);
60+
}
61+
return {};
62+
}
63+
};
64+
```
1565

1666
## 一般解法
1767

problems/0039.组合总和.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# 第39题. 组合总和
2+
3+
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
4+
5+
candidates 中的数字可以无限制重复被选取。
6+
7+
**说明:**
8+
9+
所有数字(包括 target)都是正整数。
10+
解集不能包含重复的组合。 
11+
12+
示例 1:
13+
14+
输入:candidates = [2,3,6,7], target = 7,
15+
所求解集为:
16+
[
17+
[7],
18+
[2,2,3]
19+
]
20+
21+
示例 2:
22+
23+
输入:candidates = [2,3,5], target = 8,
24+
所求解集为:
25+
[
26+
  [2,2,2,2],
27+
  [2,3,3],
28+
  [3,5]
29+
]
30+
31+
# 思路
32+
33+
# C++代码
34+
35+
```
36+
// 无限制重复被选取。 吓得我赶紧想想 0 可咋办
37+
class Solution {
38+
private:
39+
vector<vector<int>> result;
40+
void backtracking(vector<int>& candidates, int target, vector<int>& vec, int sum, int startIndex) {
41+
if (sum > target) {
42+
return;
43+
}
44+
if (sum == target) {
45+
result.push_back(vec);
46+
return;
47+
}
48+
49+
// 因为可重复,所以我们从0开始, 这道题目感觉像是47.全排列II,其实不是
50+
for (int i = startIndex; i < candidates.size(); i++) {
51+
sum += candidates[i];
52+
vec.push_back(candidates[i]);
53+
backtracking(candidates, target, vec, sum, i); // 关键点在这里,不用i+1了
54+
sum -= candidates[i];
55+
vec.pop_back();
56+
57+
}
58+
}
59+
public:
60+
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
61+
vector<int> vec;
62+
backtracking(candidates, target, vec, 0, 0);
63+
return result;
64+
}
65+
};
66+
```

problems/0040.组合总和II.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# 第40题. 组合总和
2+
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
3+
4+
candidates 中的每个数字在每个组合中只能使用一次。
5+
6+
说明:
7+
8+
所有数字(包括目标数)都是正整数。
9+
解集不能包含重复的组合。 
10+
11+
示例 1:
12+
13+
输入: candidates = [10,1,2,7,6,1,5], target = 8,
14+
所求解集为:
15+
[
16+
[1, 7],
17+
[1, 2, 5],
18+
[2, 6],
19+
[1, 1, 6]
20+
]
21+
22+
示例 2:
23+
24+
输入: candidates = [2,5,2,1,2], target = 5,
25+
所求解集为:
26+
[
27+
  [1,2,2],
28+
  [5]
29+
]
30+
31+
# 思想
32+
33+
# C++代码
34+
35+
```
36+
class Solution {
37+
private:
38+
vector<vector<int>> result;
39+
void backtracking(vector<int>& candidates, int target, vector<int>& vec, int sum, int startIndex, vector<bool>& used) {
40+
if (sum > target) {
41+
return;
42+
}
43+
if (sum == target) {
44+
result.push_back(vec);
45+
return;
46+
}
47+
48+
// 每个组合中只能使用一次 所以用 startindex
49+
// 给定一个数组 candidates 默认有重复项,解集不能包含重复的组合。 所以使用if这一套
50+
for (int i = startIndex; i < candidates.size(); i++) {
51+
if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) {
52+
continue;
53+
}
54+
sum += candidates[i];
55+
vec.push_back(candidates[i]);
56+
used[i] = true;
57+
backtracking(candidates, target, vec, sum, i + 1, used); // 关键点在这里,不用i+1了
58+
used[i] = false;
59+
sum -= candidates[i];
60+
vec.pop_back();
61+
}
62+
}
63+
64+
public:
65+
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
66+
vector<int> vec;
67+
vector<bool> used(candidates.size(), false);
68+
sort(candidates.begin(), candidates.end());
69+
backtracking(candidates, target, vec, 0, 0, used);
70+
return result;
71+
72+
}
73+
};
74+
```

problems/0077.组合.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# 第77题. 组合
2+
给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。
3+
示例:
4+
5+
输入: n = 4, k = 2
6+
输出:
7+
[
8+
[2,4],
9+
[3,4],
10+
[2,3],
11+
[1,2],
12+
[1,3],
13+
[1,4],
14+
]
15+
16+
# 思路
17+
18+
19+
# C++ 代码
20+
21+
```
22+
class Solution {
23+
private:
24+
vector<vector<int>> result;
25+
void backtracking(int n, int k, vector<int>& vec, int startIndex) {
26+
if (vec.size() == k) {
27+
result.push_back(vec);
28+
return;
29+
}
30+
// 这个for循环有讲究,组合的时候 要用startIndex,排列的时候就要从0开始
31+
// 这个过程好难理解,需要画图
32+
for (int i = startIndex; i <= n; i++) {
33+
vec.push_back(i);
34+
backtracking(n, k, vec, i + 1);
35+
vec.pop_back();
36+
}
37+
}
38+
public:
39+
40+
vector<vector<int>> combine(int n, int k) {
41+
vector<int> vec;
42+
backtracking(n, k, vec, 1);
43+
return result;
44+
}
45+
};
46+
```

problems/0078.子集.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# 题目地址
2+
3+
# 第78题. 子集
4+
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
5+
6+
说明:解集不能包含重复的子集。
7+
8+
示例:
9+
10+
输入: nums = [1,2,3]
11+
输出:
12+
[
13+
[3],
14+
  [1],
15+
  [2],
16+
  [1,2,3],
17+
  [1,3],
18+
  [2,3],
19+
  [1,2],
20+
  []
21+
]
22+
23+
24+
# 思路
25+
26+
27+
# C++代码
28+
29+
```
30+
31+
class Solution {
32+
private:
33+
void backtracking(vector<int>& nums, vector<vector<int>>& result, vector<int>& vec, int startIndex) {
34+
result.push_back(vec);
35+
for (int i = startIndex; i < nums.size(); i++) {
36+
vec.push_back(nums[i]);
37+
backtracking(nums, result, vec, i + 1);
38+
vec.pop_back();
39+
}
40+
}
41+
public:
42+
vector<vector<int>> subsets(vector<int>& nums) {
43+
vector<vector<int>> result;
44+
vector<int> vec;
45+
backtracking(nums, result, vec, 0);
46+
return result;
47+
}
48+
};
49+
```

problems/0090.子集II.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# 题目地址
2+
https://leetcode-cn.com/problems/subsets-ii/
3+
# 第90题. 子集II
4+
5+
6+
# 思路
7+
8+
9+
# C++代码
10+
11+
```
12+
class Solution {
13+
private:
14+
void backtracking(vector<int>& nums, vector<vector<int>>& result, vector<int>& vec, int startIndex, vector<bool>& used) {
15+
result.push_back(vec);
16+
for (int i = startIndex; i < nums.size(); i++) {
17+
if (i > 0 && nums[i] == nums[i - 1] && used[i-1] == false) { // 果然去重都是一个逻辑啊
18+
continue;
19+
}
20+
vec.push_back(nums[i]);
21+
used[i] = true;
22+
backtracking(nums, result, vec, i + 1, used);
23+
used[i] = false;
24+
vec.pop_back();
25+
}
26+
}
27+
28+
public:
29+
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
30+
vector<bool> used(nums.size(), false);
31+
vector<vector<int>> result;
32+
vector<int> vec;
33+
sort(nums.begin(), nums.end());
34+
backtracking(nums, result, vec, 0, used);
35+
return result;
36+
}
37+
};
38+
```

0 commit comments

Comments
 (0)