- Solution independence
Write a program to solve Sudoku problem through filled space.
This problem is mainly solved by backtracking. Select the row, column and block with the least space, and then fill in them. If there is a problem, backtracking is needed
class Solution { public: // Line, column and block store the available numbers in each row, column and palace respectively vector<set<int>> line, column, block; //Hash updates the number available in each row / column / Palace void update( vector<vector<char>>& board){ set<int> compare = {1,2,3,4,5,6,7,8,9}; //Row a; column b; house c for( int i = 0; i < 9; i++) line.push_back( compare), column.push_back( compare), block.push_back( compare); for( int i = 0; i < 9; i++) for( int j = 0; j < 9; j++) if( board[i][j] != '.'){ int t = board[i][j] - '0'; line[i].erase( t), column[j].erase(t), block[i / 3 + j / 3 * 3].erase(t); } return ; } //Check whether the characters in this position can be put there bool check( vector<vector<char>>& board, const int& i, const int& j, int num){ if( line[i].find( num) != line[i].end() && column[j].find( num) != column[j].end() && block[i/3 + j/3*3].find( num) != block[i/3 + j/3*3].end()) return true; return false; } //sign int flag = 0; //dfs + backtracking void dfs( vector<vector<char>>& board, int count){ if( count == 81){ flag = 1; return ; } int i = count / 9, j = count % 9; if( board[i][j] == '.'){ //Check which number in 1-9 can be put in this position for( int k = 1; k < 10; k++) if( check( board, i, j, k)){ line[i].erase( k), column[j].erase( k), block[ i /3 + j/3*3].erase( k); board[i][j] = k + '0'; dfs( board, count + 1); if( !flag){ line[i].insert( k), column[j].insert( k), block[ i /3 + j/3*3].insert( k); board[i][j] = '.'; } else return ; } } else dfs( board, count + 1); return ; } void solveSudoku(vector<vector<char>>& board) { update( board); //show( line, column, block); dfs(board, 0); } };
- Look-and-say sequence
Appearance sequence is a sequence of integers. Starting from the number 1, each item in the sequence is a description of the previous item.
This problem can be solved recursively: each answer is the last cnt + val
class Solution { public: string countAndSay(int n) { if (n == 1) return "1"; string s = countAndSay(n - 1); string ret; int size = s.size(); for (int i = 0; i < size;) { int cnt = 1; char val = s[i]; i++; while (i < size && s[i] == val) { i++; cnt++; } char count = cnt + '0'; ret = ret + count + val; } return ret; } };
- Combinatorial summation
Given an array of candidates without repeating elements and a target number target, find out all combinations of candidates that can make the number and target.
The numbers in candidates can be selected repeatedly without limit.
This problem can be solved by dynamic programming: target can be decomposed into some elements in the array and traversed from the first element, that is, DP [target] = DP [candidates [0] + DP [target - candidates [0]], so it can be solved
class Solution { public: vector<vector<int>> combinationSum(vector<int>& candidates, int target) { unordered_map<int, set<vector<int>>>dict; for (int i = 1; i <= target; i++) { for (int it : candidates) { if (i == it) dict[i].insert(vector<int>{it}); else if (i > it) { for (auto ivec : dict[i - it]) { ivec.push_back(it); sort(ivec.begin(), ivec.end()); if(dict[i].count(ivec)==0) dict[i].insert(ivec); } } } } vector<vector<int>>ans; for (auto it : dict[target]) ans.push_back(it); return ans; } };
The code after adding pruning operation is as follows
class Solution { private: vector<int> candidates; vector<vector<int>> res; vector<int> path; public: void DFS(int start, int target) { if (target == 0) { res.push_back(path); return; } for (int i = start; i < candidates.size() && target - candidates[i] >= 0; i++) { path.push_back(candidates[i]); DFS(i, target - candidates[i]); path.pop_back(); } } vector<vector<int>> combinationSum(vector<int> &candidates, int target) { std::sort(candidates.begin(), candidates.end()); this->candidates = candidates; DFS(0, target); return res; } };
- Combination sum 2
Given an array candidates and a target number target, find out all combinations of candidates that can make numbers and targets.
Each number in candidates can only be used once in each combination.
This question is essentially the same thing as the previous one, only a little modification of the conditions. The same backtracking + paper cutting can be solved
class Solution { public: vector<int> input; int target; vector<vector<int>> result; vector<int> vc; void dfs(int index, int sum) { // Index > = input. Size(), write index == input.size() // Because every time + 1, prune at index == input.size() if (sum >= target || index == input.size()) { if (sum == target) { result.push_back(vc); } return; } for (int i = index; i < input.size(); i++) { if (input[i] > target) { continue; } // [here is the code I added]: // 1. I > index indicates that the pruning branch must not be the first branch of the current layer // 2. input[i - 1] == input[i] indicates that the number of currently selected branches is equal to that of the previous branch of the current layer // Because the candidate set of the former branch must be larger than that of the latter branch // Therefore, the branches appearing later must contain the results of the branches appearing earlier, so pruning // The premise of pruning is sorting, ascending or descending if (i > index && input[i - 1] == input[i]) { continue; } vc.push_back(input[i]); sum += input[i]; dfs(i + 1, sum); vc.pop_back(); sum -= input[i]; } } vector<vector<int>> combinationSum2(vector<int> &candidates, int target) { // The premise of pruning is sorting, ascending or descending sort(candidates.begin(), candidates.end()); this->input = candidates; this->target = target; dfs(0, 0); return result; } };
- First positive number missing
Given an array of unsorted integers, find the smallest positive integer that does not appear.
There is a hidden conclusion in this question: if the array length is n, then the minimum positive integer must be less than or equal to N+1. In this case, we can use the array as the hash table to store the state, and then traverse it again
class Solution { public: int firstMissingPositive(vector<int>& nums) { int ret = 1; int size = nums.size(); int mapNums[size + 2] = {0}; for (int i = 0; i < nums.size(); i++) { int tmp = nums[i]; if (tmp < size + 2 && tmp > 0) mapNums[tmp] = 1; } while (1) { if (mapNums[ret] == 1) ret++; else return ret; } } };
- Rainwater collection
Given that n non negative integers represent the height map of each column with a width of 1, calculate how much rainwater can be received by columns arranged in this way after rain.
The main difficulty is how to calculate the design. The core idea of this question is: if the left side is higher than the right side, the grid will be calculated from the right side; if the right side is higher than the left side, the grid will be calculated from the left side
class Solution { public: int trap(vector<int>& height) { int begin = 0, end = height.size() - 1, ret = 0; int leftMax = 0, rightMax = 0; while (begin < end) { if (height[begin] < height[end]) { if (height[begin] < leftMax) ret += leftMax - height[begin]; else leftMax = height[begin]; begin++; } else { if (height[end] < rightMax) ret += rightMax - height[end]; else rightMax = height[end]; end--; } } return ret; } };