【leetcode刷题】第k个数,全排列I,全排列II,斐波那契数列

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();
 */

猜你喜欢

转载自blog.csdn.net/weixin_43154149/article/details/108420472