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
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):
"123"
"132"
"213"
"231"
"312"
"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;
}
};