LeetCode—46(全排列)
方法一:跟77题(组合项)类似,解法基本相同,利用递归DFS来求解.这里我们需要用到一个visited数组来标记某个数字是否访问过,然后在DFS递归函数的循环应从头开始.
C++代码:
class Solution {
public:
vector<vector<int>> permute(vector<int>& num) {
vector<vector<int>> res;
vector<int> out, visited(num.size(), 0);
permuteDFS(num, 0, visited, out, res);
return res;
}
void permuteDFS(vector<int>& num, int level, vector<int>& visited, vector<int>& out, vector<vector<int>>& res) {
if (level == num.size()) {res.push_back(out); return;}
for (int i = 0; i < num.size(); ++i) {
if (visited[i] == 1) continue;
visited[i] = 1;
out.push_back(num[i]);
permuteDFS(num, level + 1, visited, out, res);
out.pop_back();
visited[i] = 0;
}
}
};
方法二:用了STL的内置函数 next_permutation(),专门就是用来返回下一个全排列,耳边又回响起了诸葛孔明的名言,我从未见过如此…投机取巧…的解法!
class Solution {
public:
vector<vector<int>> permute(vector<int>& num) {
vector<vector<int>> res;
sort(num.begin(), num.end());
res.push_back(num);
while (next_permutation(num.begin(), num.end())) {
res.push_back(num);
}
return res;
}
};
LeetCode—47(全排列II)
方法:一定要能弄清楚递归函数的for循环中两个if的剪枝的意思。注意看这里面的 skipped 1 表示的是第一个if剪枝起作用的地方,skipped 2 表示的是第二个if剪枝起作用的地方。我们主要关心的是第二个if剪枝,那么看上方第一个蓝色标记的那行,再上面的红色一行表示在 level = 1, i = 1 时递归调用结束后,恢复到起始状态,那么此时 out 数组中只有一个1,后面的2已经被pop_back()了,当然对应visited值也重置为0了,这种情况下我们需要剪枝,当然不能再一次把2往里加,因为这种情况在递归中已经加入到结果res中了,所以到了 level = 1, i = 2 的状态时,nums[i] == nums[i-1] && visited[i-1] == 0 的条件满足了,我们的剪枝就起作用了,这种重复的情况就被剪掉了。
level = 0, i = 0 => out: {}
level = 1, i = 0 => out: {1 } skipped 1
level = 1, i = 1 => out: {1 }
level = 2, i = 0 => out: {1 2 } skipped 1
level = 2, i = 1 => out: {1 2 } skipped 1
level = 2, i = 2 => out: {1 2 }
level = 3 => saved {1 2 2}
level = 3, i = 0 => out: {1 2 2 } skipped 1
level = 3, i = 1 => out: {1 2 2 } skipped 1
level = 3, i = 2 => out: {1 2 2 } skipped 1
level = 2, i = 2 => out: {1 2 2 } -> {1 2 } recovered
level = 1, i = 1 => out: {1 2 } -> {1 } recovered
level = 1, i = 2 => out: {1 } skipped 2
level = 0, i = 0 => out: {1 } -> {} recovered
level = 0, i = 1 => out: {}
level = 1, i = 0 => out: {2 }
level = 2, i = 0 => out: {2 1 } skipped 1
level = 2, i = 1 => out: {2 1 } skipped 1
level = 2, i = 2 => out: {2 1 }
level = 3 => saved {1 2 2}
level = 3, i = 0 => out: {2 1 2 } skipped 1
level = 3, i = 1 => out: {2 1 2 } skipped 1
level = 3, i = 2 => out: {2 1 2 } skipped 1
level = 2, i = 2 => out: {2 1 2 } -> {2 1 } recovered
level = 1, i = 0 => out: {2 1 } -> {2 } recovered
level = 1, i = 1 => out: {2 } skipped 1
level = 1, i = 2 => out: {2 }
level = 2, i = 0 => out: {2 2 }
level = 3 => saved {1 2 2}
level = 3, i = 0 => out: {2 2 1 } skipped 1
level = 3, i = 1 => out: {2 2 1 } skipped 1
level = 3, i = 2 => out: {2 2 1 } skipped 1
level = 2, i = 0 => out: {2 2 1 } -> {2 2 } recovered
level = 2, i = 1 => out: {2 2 } skipped 1
level = 2, i = 2 => out: {2 2 } skipped 1
level = 1, i = 2 => out: {2 2 } -> {2 } recovered
level = 0, i = 1 => out: {2 } -> {} recovered
level = 0, i = 2 => out: {} skipped 2
C++代码:
class Solution {
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<vector<int>> res;
vector<int> out, visited(nums.size(), 0);
sort(nums.begin(), nums.end());
permuteUniqueDFS(nums, 0, visited, out, res);
return res;
}
void permuteUniqueDFS(vector<int>& nums, int level, vector<int>& visited, vector<int>& out, vector<vector<int>>& res) {
if (level >= nums.size()) {res.push_back(out); return;}
for (int i = 0; i < nums.size(); ++i) {
if (visited[i] == 1) continue;
if (i > 0 && nums[i] == nums[i - 1] && visited[i - 1] == 0) continue;
visited[i] = 1;
out.push_back(nums[i]);
permuteUniqueDFS(nums, level + 1, visited, out, res);
out.pop_back();
visited[i] = 0;
}
}
};
LeetCode—48(旋转图像)
方法:首先从对角线/的方向进行翻转,然后再以x轴中先上下翻转即可得到结果.
C++代码:
class Solution {
public:
void rotate(vector<vector<int> > &matrix) {
int n = matrix.size();
for (int i = 0; i < n - 1; ++i) {
for (int j = 0; j < n - i; ++j) {
swap(matrix[i][j], matrix[n - 1- j][n - 1 - i]);
}
}
for (int i = 0; i < n / 2; ++i) {
for (int j = 0; j < n; ++j) {
swap(matrix[i][j], matrix[n - 1 - i][j]);
}
}
}
};
LeetCode—49(字母异位分组)
方法:如何判断两者是错位词呢,我们发现如果把错位词的字符顺序重新排列,那么会得到相同的结果,所以重新排序是判断是否互为错位词的方法,由于错位词重新排序后都会得到相同的字符串,我们以此作为key,将所有错位词都保存到字符串数组中,建立key和字符串数组之间的映射,最后再存入结果res中即可.
C++代码:
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
vector<vector<string>> res;
unordered_map<string,vector<string>> m;
for(string str : strs){
string t = str;
sort(t.begin(),t.end());
m[t].push_back(str);
}
for(auto a : m){
res.push_back(a.second);//second没懂 应该是a的字符串数组.
}
return res;
}
};
LeetCode—50(Pow(x,n))
方法:我们让i初始化为n,然后看i是否是2的倍数,是的话x乘以自己,否则res乘以x,i每次循环缩小一半,直到为0停止循环。最后看n的正负,如果为负,返回其倒数.
C++代码:
class Solution {
public:
double myPow(double x, int n) {
double res = 1.0;
for (int i = n; i != 0; i /= 2) {
if (i % 2 != 0) res *= x;
x *= x;
}
return n < 0 ? 1 / res : res;
}
};