文章目录
-
- [60. 第k个排列](https://leetcode-cn.com/problems/permutation-sequence/)(找规律计数)
- [46. 全排列](https://leetcode-cn.com/problems/permutations/)(递归 + 回溯)
- [47. 全排列 II](https://leetcode-cn.com/problems/permutations-ii/)(递归 + 回溯)
- [剑指 Offer 38. 字符串的排列](https://leetcode-cn.com/problems/zi-fu-chuan-de-pai-lie-lcof/)(递归 + 回溯)
- [剑指 Offer 10- I. 斐波那契数列](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/)(递推)
- [剑指 Offer 59 - II. 队列的最大值](https://leetcode-cn.com/problems/dui-lie-de-zui-da-zhi-lcof/)(队列 + 双端队列)
60. 第k个排列(找规律计数)
计数。求每一位时,直接计算落在哪一组。例如求第一位,每一组都有(n - 1)!种可能。第一位选好,求第二位时,又有(n - 2)!种可能 … 以此类推求出拼接每一位数。详细题解地址
class Solution {
public:
string getPermutation(int n, int k) {
string res;
vector<bool> st(n);
for(int i=0;i<n;i++)
{
int f = 1;
for(int j = 1;j <= n - i - 1;j ++ ) f *= j; // 计算每一组的个数
// 比如选第一个数,每一组都有(n-1)!种
for(int j = 0;j < n;j ++ ){
if(!st[j]){
if(k <= f){
res += to_string(j + 1);
st[j] = true;
break;
}
k -= f;
}
}
}
return res;
}
};
46. 全排列(递归 + 回溯)
递归 + 回溯,经典题。只需要判断当前这一位有没有用过,没有用过则选中递归下一层。
class Solution {
public:
vector<vector<int>> res;
vector<bool> st;
int n;
vector<vector<int>> permute(vector<int>& nums) {
n = nums.size();
vector<int> s;
st = vector<bool>(n);
dfs(0,nums,s);
return res;
}
void dfs(int u,vector<int>& nums,vector<int> &s)
{
if(u == n)
{
res.push_back(s);
return;
}
for(int i=0;i<n;i++)
{
if(!st[i])
{
st[i] = true;
s.push_back(nums[i]);
dfs(u + 1,nums,s);
s.pop_back();
st[i] = false;
}
}
}
};
47. 全排列 II(递归 + 回溯)
算法1:
sort + unique ,去重,当然算法是低效的。但可以学习一下
sort(res.begin(),res.end()); res.erase(unique(res.begin(), res.end()), res.end());
class Solution {
public:
vector<vector<int>> res;
vector<bool> st;
vector<int> path;
vector<vector<int>> permuteUnique(vector<int>& nums) {
st = vector<bool>(nums.size());
dfs(0,nums);
// 去重
sort(res.begin(),res.end());
res.erase(unique(res.begin(), res.end()), res.end());
return res;
}
void dfs(int u,vector<int>& nums)
{
if(u == nums.size())
{
res.push_back(path);
return;
}
for(int i=0;i<nums.size();i++)
{
if(!st[i])
{
st[i] = true;
path.push_back(nums[i]);
dfs(u + 1,nums);
path.pop_back();
st[i] = false;
}
}
}
};
算法2:
将原数组排序,只需要在递归的时候跳过重复元素即可
class Solution {
public:
vector<vector<int>> res;
vector<bool> st;
vector<int> path;
int n;
vector<vector<int>> permuteUnique(vector<int>& nums) {
n = nums.size();
st = vector<bool>(n);
sort(nums.begin(),nums.end());
dfs(0,nums);
return res;
}
void dfs(int u,vector<int>& nums)
{
if(u == nums.size())
{
res.push_back(path);
return;
}
for(int i=0;i<nums.size();i++)
{
if(!st[i])
{
st[i] = true;
path.push_back(nums[i]);
dfs(u + 1,nums);
path.pop_back();
st[i] = false;
while(i + 1 < n && nums[i + 1] == nums[i]) i ++ ; // 跳过重复元素
}
}
}
};
剑指 Offer 38. 字符串的排列(递归 + 回溯)
同上。
但里面不能有重复元素
剑指 Offer 10- I. 斐波那契数列(递推)
递推法求斐波那契数列,只有n>=2时才计算,其它边界当作特殊情况直接返回
class Solution {
public:
int mod = 1e9 + 7;
int fib(int n) {
int a = 0, b = 1, c ;
if(n == 0) return 0;
else if(n == 1) return 1;
else{
n -= 1;
while(n --)
{
c = (a + b) % mod;
a = b;
b = c;
}
}
return c;
}
};
剑指 Offer 59 - II. 队列的最大值(队列 + 双端队列)
用双端队列deque来维护最大值-------详细题解地址
class MaxQueue {
public:
queue<int> q;
deque<int> d;
MaxQueue() {
}
int max_value() {
if(d.empty()) return -1;
return d.front();
}
void push_back(int value) {
while(!d.empty() && d.back() < value) d.pop_back(); // 排在双端队列队头的一定是最大值!
d.push_back(value);
q.push(value);
}
int pop_front() {
if(q.empty()) return -1;
int ans = q.front();
if(ans == d.front()) d.pop_front();
q.pop();
return ans;
}
};
/**
* Your MaxQueue object will be instantiated and called as such:
* MaxQueue* obj = new MaxQueue();
* int param_1 = obj->max_value();
* obj->push_back(value);
* int param_3 = obj->pop_front();
*/