Skip to content

Commit 7e6fb19

Browse files
authored
Merge pull request algorithm004-01#373 from xuyusong37/master
651-Week02
2 parents 3aaf574 + 419af15 commit 7e6fb19

File tree

3 files changed

+184
-1
lines changed

3 files changed

+184
-1
lines changed

Week 02/id_651/LeetCode_46_651.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
给定一个没有重复数字的序列,返回其所有可能的全排列。
3+
4+
示例:
5+
6+
输入: [1,2,3]
7+
输出:
8+
[
9+
[1,2,3],
10+
[1,3,2],
11+
[2,1,3],
12+
[2,3,1],
13+
[3,1,2],
14+
[3,2,1]
15+
]
16+
*/
17+
18+
/*
19+
解法: 递归,回溯,
20+
移动索引, 通过交换位置来去重
21+
*/
22+
# include <iostream>
23+
# include <vector>
24+
using namespace std;
25+
class Solution {
26+
private:
27+
vector<vector<int>> answers;
28+
public:
29+
vector<vector<int>> permute(vector<int>& nums) {
30+
recursion(nums, 0);
31+
return answers;
32+
};
33+
void recursion(vector<int> nums, int pos){
34+
if (pos == nums.size()){
35+
answers.push_back(nums);
36+
return;
37+
}
38+
for(int j=pos;j<nums.size();j++){
39+
if (pos != j) swap(nums[pos], nums[j]);
40+
recursion(nums, pos + 1);
41+
if (pos != j) swap(nums[pos], nums[j]);
42+
}
43+
}
44+
45+
};
46+
47+
int main(){
48+
Solution sol;
49+
vector<int> n(4,0);
50+
for(int i=0; i<n.size();i++) n[i] = i;
51+
vector<vector<int>> answers;
52+
answers = sol.permute(n);
53+
return 0;
54+
}

Week 02/id_651/LeetCode_77_651.cpp

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。
3+
输入: n = 4, k = 2
4+
输出:
5+
[
6+
[2,4],
7+
[3,4],
8+
[2,3],
9+
[1,2],
10+
[1,3],
11+
[1,4],
12+
]
13+
*/
14+
15+
/* 解法1: 回溯+剪枝
16+
-> 先生成对应数量的初始key-value对, 将生成的对象vector丢入递归函数中
17+
-> 递归的跳出条件为: vector的大小等于k的时候。 将结果插入结果vector中
18+
-> 遍历vector, 先将当前的vector存储一份(便于回溯), 然后通过剪枝的方式,从中抽取掉迭代值位置的值
19+
-> 每次递归完当前层的数据之后, 需要回复状态,进行下一层的循环
20+
21+
解法2: 维护栈
22+
-> 初始化一个长度为k,每个值为0的vector, 初始化一个指针i=0
23+
-> 指针在0和1位置移动
24+
-> 每次循环
25+
判断vector[i]的值是否大于长度n, 大于则左移
26+
判断i的值是否等于k-1, 是则将结果插入到结果vector中
27+
剩余的情况则需要继续增加值,将1位置的值持续的加1
28+
-> eg:n=3,k=2
29+
(1,1,0,0)
30+
(1,2,0,0)
31+
(1,3,0,0)->准备指针左移
32+
(2,1,0,0)
33+
(2,2,0,0)
34+
(2,3,0,0)
35+
(3,1,0,0)
36+
(3,2,0,0)
37+
(3,3,0,0)
38+
一直到指针i的值小于0则跳出循环,返回结果
39+
*/
40+
# include <iostream>
41+
# include <vector>
42+
using namespace std;
43+
44+
class Solution {
45+
private:
46+
vector<vector<int>> answers;
47+
public:
48+
// 递归
49+
vector<vector<int>> combine(int n, int k) {
50+
vector<int> nums(n, {(1,n)});
51+
for(int i=0; i<nums.size();i++){
52+
nums[i] = i+1;
53+
}
54+
recursion(nums, k, 0);
55+
return answers;
56+
};
57+
void recursion(vector<int> nums, int k, int pos){
58+
if(nums.size() == k){answers.push_back(nums);return;};
59+
for(int i=pos;i<nums.size();i++){
60+
vector<int> temp(nums);
61+
nums.erase(nums.begin() + i);
62+
recursion(nums, k, i);
63+
nums = temp;
64+
}
65+
}
66+
67+
68+
// 利用栈
69+
vector<vector<int>> combine2(int n, int k) {
70+
vector<vector<int>> result;
71+
int i = 0;
72+
vector<int> temp(k, 0);
73+
while(i >= 0){
74+
temp[i]++;
75+
if (temp[i] > n) --i;
76+
else if (i == k-1) result.push_back(temp);
77+
else{
78+
++i;
79+
temp[i] = temp[i-1];
80+
}
81+
}
82+
return result;
83+
};
84+
};
85+
86+
int main(){
87+
Solution sol;
88+
vector<vector<int>> result;
89+
result = sol.combine(10, 2);
90+
for(int i=0; i< result.size(); i++){
91+
for(int j=0;j< result[i].size();j++){
92+
cout << result[i][j] << " ";
93+
}
94+
cout << endl;
95+
}
96+
return 0;
97+
}

Week 02/id_651/NOTE.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,36 @@
11
# NOTE
2+
Week 2 总结
23

3-
4+
1. 哈希表: 散列表, 时间复杂度为O(1), 找到一个key即可映射到对应的存储空间,获取到值
5+
哈希函数: 通过函数的设计, 可以对key进行计算操作, 达到快速定位内存中key所对应的value
6+
映射: 和内存空间地址差不多, 一个key对应一个或多个value。
7+
集合: 有序的去重散列表, 内部会进行排序,去重。
48

9+
10+
2. 树: 链表的一种变形, 有根节点,左节点,右节点
11+
常见的数排序(主要是看根节点的位置判断是属于哪一种类型)
12+
-> 前序排序 : 根左右
13+
-> 中序排序 : 左根右 -> 二叉搜索树(有序的中序排序, 结果一定是按大小排好序的)
14+
-> 后序排序 : 左右根
15+
图:在树的基础上,加上有环链表的一种变形
16+
17+
3. 递归 : 自己调用自己, 本质上是维护一个栈, 将不需要先执行的推到栈底,需要先执行的推到栈顶。
18+
递归函数的模板:
19+
1. 结束条件 -> 即是准备开始弹出栈顶元素的时候
20+
2. 当前层逻辑 -> 处理当前层的逻辑
21+
3. 下一层的逻辑 -> 处理下一层的逻辑
22+
4. 清理 -> 相关的有影响因子的变量需要重置或者其他操作
23+
def recursion():
24+
if () return
25+
deal_current_level()
26+
deal_next_level()
27+
clear_param()
28+
29+
4. 分治 : 将任务拆分成多个小任务, 按照这个操作执行,
30+
到不能再分, 就可以开始将小任务处理掉,最后汇总到一起得出结果
31+
回溯 : 多层结构, 向下移动的,会保存当前层的状态, 等下一层的执行结果返回
32+
若是不符合, 则当前层可以恢复原先的状态。
33+
34+
35+
总结:
36+
捡回了一些大学的知识点,并且巩固加深了。 看了视频,做了题, 有些知识点就是那种感觉: 哦, 原来是这样/ 还能这么想。 尤其是树,递归,分支,回溯。 基本原理不是很难理解, 但是实际应用确实需要经验,需要培养起那种思维, 我觉得这两块地方的知识, 如果掌握了, 对我的技能提升是很大的。

0 commit comments

Comments
 (0)