[Leetcode] 31, 60, 36

31. Next Permutation

Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).

The replacement must be in-place, do not allocate extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

Solution: 从后往前数,找到第一个比下一个数小的数x(n),将x(n)与x(n+1) - x(end)中比x(n)大的最小数交换后,将新的x(n+1) - x(end)排序。
Code: 
class Solution {
public:
    void nextPermutation(vector<int>& nums) {
        bool ifchange = false;
        for(auto i = prev(nums.end(),2); i>=nums.begin(); i=prev(i)){
            if(*i < *(i+1)){
                
                auto j = next(i);
                //找到第一个小于等于*i的数,前一个就是需要用于交换的数
                for(; j<nums.end() ; j++){
                    if(*j<=*i) break;
                }
                j = prev(j);
                
                int tmp = *i;
                *i = *j;
                *j = tmp;
                sort(next(i),nums.end());
                ifchange = true;
                break;
            }
        }
        //cout<<ifchange<<endl;
        if(!ifchange) sort(nums.begin(), nums.end());
    }
};


60. Permutation Sequence

The set [1,2,3,…,n] contains a total of n! unique permutations.

By listing and labeling all of the permutations in order,
We get the following sequence (ie, for n = 3):

  1. "123"
  2. "132"
  3. "213"
  4. "231"
  5. "312"
  6. "321"

Given n and k, return the kth permutation sequence.

Note: Given n will be between 1 and 9 inclusive.

Solution(1): 暴力求解,从最小的开始,调用k-1次nextPermutation函数。

Code:

class Solution {
public:
    string getPermutation(int n, int k) {
        vector<int> nums;
        for(int i=1; i<=n; i++) nums.push_back(i);
        for(int i=2; i<=k; i++){
            nextPermutation(nums);
        }
        
        string s = "";
        for(int i=0; i<nums.size(); i++){
            s.push_back(nums[i]+'0');
        }
            
        return s;
    }
}

Solution(2):前一种方式求出了第1至第k的所有情况,实际不需要进行那么多运算。可以直接求出第k中情况,时间复杂度O(n)。

当n=4时,已知数1423,可知其前面有0*3!+2*2!+0*1!+0*0! = 4种情况,因此它是第5个。因此,可以得知公式,k-1 = an*(n-1)! + an-1*(n-2)! + ... + a2 * 1! + a1 * 0!,此外,因为ax表示剩下的x个数中比该位数还要小的数的个数,因此可知ax < x,因此ax*(x-1) > ax-1。由此可得:

 

即可得:

an 等于 k-1 整除 (n-1)!

Code:

class Solution {
public:
    string getPermutation(int n, int k) {
        string s;
        int a;
        k = k-1;
        
        vector<int> fac;//计算阶乘
        fac.push_back(0);
        fac.push_back(1);
        for(int i=2; i<n; i++){
            fac.push_back(*prev(fac.end()) * i);
        }
        
        vector<int> nums;
        for(int i=1; i<=n; i++) nums.push_back(i);
        
        for(int i=n-1; i>0; i--){
            a = k / fac[i];
            k = k % fac[i];
            s.push_back(nums[a]+'0');
            nums.erase(nums.begin()+a);
        }
        s.push_back(nums[k]+'0');
        return s;
    }
};

36. Valid Sudoku

Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules.

The Sudoku board could be partially filled, where empty cells are filled with the character '.'.


A partially filled sudoku which is valid.

Note:
A valid Sudoku board (partially filled) is not necessarily solvable. Only the filled cells need to be validated.

注意审题!这里说明了valid的意思不是要求数独能解,而是数独中已经存在的数不违反数独规则!

Code:

class Solution {
public:
    bool isValidSudoku(vector<vector<char>>& board) {
        map<char,bool> use;
        //检查行
        for(int i=0; i<9; i++){
            for(int t=1; t<=9; t++) use[t+'0'] = false;
            for(int t=0; t<9; t++){
                if(board[i][t]!='.'){
                    if(use[board[i][t]]) return false;
                    else use[board[i][t]] = true;
                }
            }
        }
        //检查列
        for(int i=0; i<9; i++){
            for(int t=1; t<=9; t++) use[t+'0'] = false;
            for(int t=0; t<9; t++){
                if(board[t][i]!='.'){
                    if(use[board[t][i]]) return false;
                    else use[board[t][i]] = true;
                }
            }
        }
        //检查9宫格
        for(int i=0; i<9; i+=3){
            for(int t=0; t<9; t+=3){
                for(int t=1; t<=9; t++) use[t+'0'] = false;
                for(int j=i; j<i+3; j++){
                    for(int q=t; q<t+3; q++)
                        if(board[j][q]!='.'){
                            if(use[board[j][q]]) return false;
                            else use[board[j][q]] = true;
                        }
                }
            }
        }
        return true;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值