Articles Catalogue
 Input does not indicate how many Input, with EOF as the closing flag
 Input does not indicate how many Input, ending with a special input
 Indicates N Input
 Indicates that there are N groups of inputs and exits with a particular input
 The input is a whole line (including spaces)
 Input is multiline (including spaces)
 Read from a file
 Arithmetic Arrangement
 array
 Next permutation
 The last permutation
 Implementation provided by STL (next permutation, last permutation) TODO
 Kth permutation
 Full Arrangement (No Repetition)
 Full permutation (repetition)
 [Note] Time Complexity of Full Sorting
 combination
 Combination (n chooses k, no repetition)
 Combination (n select k, repeat)
 Combination summation (numbers are not duplicated but reusable)
 Combination sum and 2 (there are duplicate numbers but each number can only be used once)
 Combination sum and 3 (number not repeated and specified number)
 [Note]
Input does not indicate how many Input, with EOF as the closing flag
C
int a, b; // Scnf returns the number of variables. If no  1 is returned, EOF is a predefined constant  1. while (scanf("%d %d", &a, &b) != EOF) { // ... }
C++
int a, b; while (cin >> a >> b) { // ... }
Input does not indicate how many Input, ending with a special input
C
// Example 1 int a, b; while (scanf("%d %d", &a, &b) != EOF && (a != 0 && b != 0)) { // ... } // perhaps while (scanf("%d %d", &a, &b) != EOF && (a  b)) { // ... } // Example 2 int n; while (scanf("%d", &n) != EOF && n != 0) { // ... }
C++
// Example 1 int a, b; while (cin >> a >> b) { if (a == 0 && b == 0) break; // ... } // Example 2 int n; while (cin >> n && n != 0) { // ... }
Indicates N Input
C
int n; scanf("%d", &n); int a, b; for (int i = 0; i < n; i++) { scanf("%d %d", &a, &b); // ... }
C++
int n; cin >> n; int a, b; while(n) { cin >> a >> b; }
Python3
n = int(input()) for _ in range(n): # ...
Indicates that there are N groups of inputs and exits with a particular input
C/C++
int n; while (cin >> n && n != 0) { int a, b; for (int i = 0; i < n; i++) { cin >> a >> b; // ... } }
The input is a whole line (including spaces)
Receiving (C/C++) with char []
const int MAXN = 1000; char buff[MAXN]; // C gets(buff); puts(buff); // output // C++ cin.getline(buff, MAXN); // The third parameter defaults to'n' cin.getline(buff, MAXN, '\n');
Receiving (C++) with string
string s; getline(cin, s); // The third parameter defaults to'n' getline(cin, s, '\n');
Input is multiline (including spaces)
C++
int n; cin >> n; cin.get(); // Otherwise, n is counted in the following getline(), resulting in a smaller set of data while (n) { string s; getline(cin, s); }
Read from a file
C
FILE *cfin = fopen("in.txt", "r"); FILE *cfout = fopen("out.txt", "w"); int a, b; // Note to pass in the file pointer while (fscanf(cfin, "%d %d", &a, &b) != EOF) { // Similarly, replace scanf with fscanf fprintf(cfout, "%d\n", a + b); // Replace printf with fprintf } fclose(cfin); fclose(cfout);
C++
ifstream fin("in.txt"); ofstream fout("out.txt"); int a, b; while (fin >> a >> b) { fout << a + b << endl; } fin.close(); fout.close();
Arithmetic Arrangement
array
Next permutation
LeetCode  31. Next permutation
Topic Description
To achieve the next permutation function, the algorithm needs to rearrange the given number sequence into the next larger permutation in the dictionary order. If there is no next larger arrangement, the numbers are rearranged into the smallest (ascending) arrangement. It must be modified in situ, allowing only extra constant space. Here are some examples where the input is in the left column and the corresponding output is in the right column. 1,2,3 → 1,3,2 3,2,1 → 1,2,3 1,1,5 → 1,5,1
thinking
 The two adjacent permutations have the longest common prefix, and then find the high and low positions that need to be exchanged.
 According to the definition of dictionary order, follow the following steps to find the next permutation
 Look back and forth for the high hi that needs to be changed, that is, the position of the first descending element
1 5 8 4 7 6 5 3 1 ↑ hi
 Look back and forth for the low lo that needs to be swapped, that is, the first location larger than nums[hi]
1 5 8 4 7 6 5 3 1 ↑ ↑ hi lo
 Exchange nums[lo] and nums[hi]
1 5 8 4 7 6 5 3 1 ↓ ↓ 1 5 8 5 7 6 4 3 1 ↑ ↑ Hi lo (hi position unchanged)

The sequence after inversion of hi, i.e. nums [hi+1:n)
1 5 8 5 7 6 4 3 1 ↓ ↓ ↓ ↓ ↓ 1 5 8 5 1 3 4 6 7 ↑ ↑ Hi lo (hi position unchanged)
C++
class Solution { public: void nextPermutation(vector<int>& nums) { int n = nums.size(); if (n <= 1) return; int hi = n  2; // 1. Look back and forth for the ** high ** hi that needs to be changed, that is, the position of the first descending element. while (hi >= 0 && nums[hi + 1] <= nums[hi]) hi; if (hi >= 0) { // 2. Look back and forth for the ** low ** lo that needs to be exchanged, that is, the first position larger than nums[hi] int lo = n  1; while (lo >= 0 && nums[lo] <= nums[hi]) lo; // 3. Exchange nums[lo] and nums[hi] swap(nums[hi], nums[lo]); } // 4. Sequence after inversion of hi, i.e. nums [hi+1:n) reverse(nums.begin() + hi + 1, nums.end()); // When i==1, this operation changes the sequence from the dictionary maximum to the minimum, which is slightly different from the next_permutation provided in STL. } };
The last permutation
LintCode  51. The last permutation
Problem Description
Given an array of integers to represent permutations, find the last permutation on it. Arrangements may contain duplicate integers Example Give the permutation [1,3,2,3], on which the last permutation is [1,2,3,3] Give the permutation [1,2,3,4], on which the last permutation is [4,3,2,1]
thinking
 In fact, it is. Next permutation The inverse process
 Look for the first ascending position hi from right to left
 Look for the first location lo less than nums[hi] from right to left
 Exchange nums[lo] and nums[hi]
 Position after inversion of hi
C++
class Solution { public: /* * @param nums: A list of integers * @return: A list of integers that's previous permuation */ vector<int> previousPermuation(vector<int> &nums) { int n = nums.size(); if (n <= 1) return nums; int hi = n  2; // 1. Look for the location hi of the first ascending order ** from right to left while (hi >= 0 && nums[hi] <= nums[hi + 1]) hi; if (hi >= 0) { int lo = n  1; // 2. Look from right to left for the first location lo less than ** nums[hi] while (lo >= 0 && nums[lo] >= nums[hi]) lo; // 3. Exchange nums[lo] and nums[hi] swap(nums[lo], nums[hi]); } // 4. Position after inversion of hi reverse(nums.begin() + hi + 1, nums.end()); return nums; // Note that you are asked to return a value here. } };
Implementation provided by STL (next permutation, last permutation) TODO
 STL provides two functions for generating permutations
bool next_permutation (BidirectionalIterator first, BidirectionalIterator last); bool prev_permutation (BidirectionalIterator first, BidirectionalIterator last );
 These two functions are based on lexicographical_compare() to generate the next or last permutation.
 So before using these two functions, you need to sort the original sequence first.
C++
Kth permutation
LeetCode  60. The k th permutation
Problem Description
Give the set [1,2,3,... N], all its elements have n! Species arrangement. List all permutations in order of size and mark them one by one. When n = 3, all permutations are as follows: "123" "132" "213" "231" "312" "321" Given n n n and k, return the kth permutation. Explain: The range of given n is [1, 9]. The range of given k is [1, n!]. Example 1: Input: n = 3, k = 3 Output: "213" Example 2: Input: n = 4, k = 9 Output: "2314"
thinking
 Because of the nature of dictionary order, it is not necessary to find the first k1 sequence.
 The whole idea is a bit like bucket sorting.
 Taking {1 234 5} as an example, the fourteenth sequence is found out.
First, the ordered columns can be placed in the corresponding buckets according to the elements in the first position. Before you start, k, because the computer counts start from zero, and then k=13. (Here's why you need to subtract 1.) Round 1: 5 remaining elements, 5 barrels Bucket 0: Beginning with 1, the remaining element {2345} Bucket 1: Beginning with 2, the remaining element {1345} Bucket 2: Beginning with 3, the remaining element {1 245} Bucket 3: Starting with 4, the remaining element {1 235} Bucket 4: Starting with 5, the remaining element {1 234} There are 4! = 24 sequences in each bucket, because they are ordered. Obviously, k=13 elements must be in `13/(4!) = 0 `buckets. In other words, the fourteenth element must begin with one. Remove 1 from the sequence, change the remaining sequence to {2345}, k = 13%, 24 = 13 Round 2: 4 remaining elements, 4 barrels Bucket 0: Beginning with 2, the remaining element {345} Bucket 1: Starting with 3, the remaining element {245} Bucket 2: Starting with 4, the remaining element {235} Bucket 3: Starting with 5, the remaining element {234} There are 3! = 6 elements in each bucket. Obviously, the k=13 element should be in the `13/(3!) = 2 `bucket. That is, the prefix of the 14th element is 14. Remove 4 from the sequence, change the remaining sequence to {235}, k = 13% 6 = 1 Round 3: The remaining three elements, three barrels Bucket 0: Beginning with 2, the remaining element {35} Bucket 1: Starting with 3, the remaining element {25} Bucket 2: Starting with 5, the remaining element {35} At this point, there are 2! = 2 elements in each bucket. k=1 element should be in `1/(2!) = 0 `bucket. (If k does not decrease 1 at the beginning, there will be a problem.) That is, the prefix of the fourteenth element is 142 Remove 2 from the sequence, change the remaining sequence to {35}, k = 1% 2 = 1 Round 4: 2 remaining elements, 2 barrels Bucket 0: Beginning with 3, the remaining element {5} Bucket 1: Starting with 5, the remaining element {3} At this point, there is 1! = 1 element in each bucket. The k=1 element should be in the `1/(1!)= 1 `bucket. That is, the prefix of the fourteenth element is 1425 Remove 5 from the sequence, change the remaining sequence to {3}, k = 1%  1 = 0 Round 5: 1 element remaining, 1 barrel Bucket 0: Beginning with 3, no residual elements At this point, there is 0! = 1 element in each bucket (in fact, there is no element in the bucket at this time). The k=0 element should be in the `0/(0!) = 0 `barrel (the last round using the property of 0!= 1 does not require special treatment) The 14th element is 14253.
C++
class Solution { public: string getPermutation(int n, int k) { // nums: {1, 2, 3, ..., n} // Change into other characters and store them in the corresponding position in dictionary order. vector<int> nums(n + 1, 0); for (int i = 0; i < n; i++) // Note: Bucket subscriptions start at 0. nums[i] = i + 1; // dp: {0!=1, 1!, 2!, ..., n!} vector<int> dp(n + 1, 1); // According to the above deduction, dp[0]=1 can just handle the last round. for (int i = 1; i <= n; i++) dp[i] = dp[i  1] * i; k; stringstream ss; for (int i = 1; i <= n; i++) { // Starting from 1 int index = k / dp[n  i]; // Actually, dp[n] = n is not used! ss << nums[index]; nums.erase(nums.begin() + index); // Note that the processed elements are deleted in each round k = k % dp[n  i]; } return ss.str(); } };
Full Arrangement (No Repetition)
LeetCode 46. Full Arrangement
Topic Description
Given a sequence without duplicate numbers, all possible permutations are returned. Examples: Input: [1, 2, 3] Output: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
Thought 1
 Using the next permutation, sort the arrays first, and then generate the next permutation continuously.
Idea 2
 Depthfirst search
 It is easy to know that when the elements in the sequence do not repeat, there are different kinds of arrangement of n!
 Considering the first position, there are n possibilities
 When the first position is selected, the second position has n1 possibilities.
 Because the number of states per search decreases, dfs here is a recursive process
Insertbased Writing
 More code, but better understanding
class Solution { vector<vector<int> > ret; vector<int> tmp; vector<bool> used; int n = 0; void dfs(vector<int>& nums, int step) { if (tmp.size() == n) { ret.push_back(tmp); return; } for (int i = 0; i < n; i++) { // i starts at 0 each time, because elements can be reused if (used[i]) continue; // But in each round, if you use it, you need to skip it. // Each round refers to the process of generating an arrangement. used[i] = 1; // Markup usage tmp.push_back(nums[i]); dfs(nums, step + 1); tmp.pop_back(); // To flash back used[i] = 0; } } public: vector<vector<int> > permute(vector<int>& nums) { n = nums.size(); used.resize(n, 0); dfs(nums, 0); return ret; } };
Writing Based on Exchange
 Exchangebased writing makes the code concise, but I think it's a little hard to understand.
class Solution { vector<vector<int> > ret; //Void DFS (vector < int > nums, int step) {// value transfer void dfs(vector<int>& nums, int step) { // Reference passing if (step >= nums.size()) { ret.push_back(nums); return; } for (int i = step; i < nums.size(); i++) { // Note: Here i start with step swap(nums[step], nums[i]); dfs(nums, step + 1); swap(nums[step], nums[i]); // If nums is a value input, this step is not required; otherwise, it cannot be omitted. } } public: vector<vector<int> > permute(vector<int>& nums) { dfs(nums, 0); return ret; } };
Full permutation (repetition)
LeetCode  47. Full Rank II
Topic Description
Given a sequence of repetitive numbers, all nonrepetitive permutations are returned. Examples: Input: [1, 1, 2] Output: [ [1,1,2], [1,2,1], [2,1,1] ]
Thought 1
 Remove duplication (not recommended) with set by using the method without duplication
Idea 2
 First, the original sequence is sorted so that the same elements are adjacent; at this time, only the first same element is processed, and the rest are skipped.
Insertbased Writing
class Solution { vector<vector<int> > ret; vector<int> tmp; vector<bool> used; int n = 0; void dfs(vector<int>& nums, int step) { if (tmp.size() == n) { ret.push_back(tmp); return; } for (int i = 0; i < n; i++) { if (used[i]  (i > 0 && nums[i] == nums[i  1] && !used[i  1])) continue; // Here! used[i  1] is a little hard to understand, it can cooperate with IDE or push the whole process by hand. used[i] = 1; tmp.push_back(nums[i]); dfs(nums, step + 1); tmp.pop_back(); used[i] = 0; } } public: vector<vector<int> > permuteUnique(vector<int>& nums) { n = nums.size(); used.resize(n, 0); sort(nums.begin(), nums.end()); dfs(nums, 0); return ret; } };
Writing Based on Exchange
class Solution { vector<vector<int> > ret; //Void DFS (vector < int > & nums, int step) {// pass reference can not get the correct result void dfs(vector<int> nums, int step) { // Note that ** value transfer ** should be used here int n = nums.size(); if (step >= n  1) { ret.push_back(nums); return; } for (int i = step; i < n; i++) { if (i != step && nums[i] == nums[step]) continue; swap(nums[i], nums[step]); dfs(nums, step + 1); //swap(nums[i], nums[step]); / / referencing with backtracking can not get the correct results. // The reason for this is that it destroys the order of the remaining arrays. } } public: vector<vector<int> > permuteUnique(vector<int>& nums) { sort(nums.begin(), nums.end()); dfs(nums, 0); return ret; } };
[Note] Time Complexity of Full Sorting
 In the case of no repetition, the different full arrangement of n elements is n!, so the time complexity of the algorithm is at least O(N!).
 Therefore, the full permutation algorithm is not able to process large data.
combination
Combination (n chooses k, no repetition)
LeetCode  77. Combination
Problem Description
Given two integers n and k, a combination of all possible K numbers in 1... n is returned. Examples: Input: n = 4, k = 2 Output: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ]
thinking
 Depthfirst search with backtracking, similar Full Arrangement (No Repetition)
C++
class Solution { vector<vector<int> > ret; vector<int> tmp; // Save intermediate results int K; void dfs(vector<int>& nums, int step) { if (tmp.size() >= K) { ret.push_back(tmp); return; } for (int i = step; i < nums.size(); i++) { tmp.push_back(nums[i]); // Nums [i]== i, so direct push(i) here is OK dfs(nums, i + 1); tmp.pop_back(); } } public: vector<vector<int> > combine(int n, int k) { K = k; vector<int> nums; for (int i = 0; i < n; i++) nums.push_back(i + 1); dfs(nums, 0); return ret; } };
Combination (n select k, repeat)
(Unverified)
 If no duplication is required in each combination, the duplication can be removed first and then followed by the nonduplication approach.
 If you don't need to weigh, just follow the nonrepetitive approach.
Combination summation (numbers are not duplicated but reusable)
LeetCode  39. Combination summation
thinking
 Depthfirst search
 The key is that each number can be reused.
C++
class Solution { vector<vector<int> > ret; vector<int> tmp; int cur = 0; int target = 0; void dfs(vector<int>& nums, int step) { if (cur >= target) { if (cur == target) ret.push_back(tmp); return; } for (int i = step; i < nums.size(); i++) { cur += nums[i]; tmp.push_back(nums[i]); dfs(nums, i); // Because each array can be reused, it's dfs(i) instead of dfs(i+1) cur = nums[i]; tmp.pop_back(); } } public: vector<vector<int> > combinationSum(vector<int>& candidates, int target) { this>target = target; //Sort (candidates. begin (), candidates. end (); // No dfs(candidates, 0); return ret; } };
Combination sum and 2 (there are duplicate numbers but each number can only be used once)
LeetCode  40. Combination summation II
thinking
 DFS, the key is how to remove duplication
C++
class Solution { vector<vector<int> > ret; vector<int> tmp; int cur = 0; int target; void dfs(vector<int>& nums, int step) { if (cur >= target) { if (cur == target) ret.push_back(tmp); return; } for (int i = step; i < nums.size(); i++) { if (i > step && nums[i] == nums[i  1]) // Code Note 1 continue; cur += nums[i]; tmp.push_back(nums[i]); dfs(nums, i + 1); // i+1 instead of i, because it can't be reused tmp.pop_back(); cur = nums[i]; } } public: vector<vector<int> > combinationSum2(vector<int>& candidates, int target) { this>target = target; sort(candidates.begin(), candidates.end()); // Because there is duplication, you need to sort first dfs(candidates, 0); return ret; } };
Code Note 1
if (i > step && nums[i] == nums[i  1])
 Failed to save pictures by external chain (imgALhj2Fjq1567509435788)(... / assets/Formula _20180905213339.png]
 This code does not actually filter [External Link Picture Transfer Failure (imgNPDvI0lz1567509435789)(... / assets/Formula _20180905213323.png)]  The case of I = step
 The real duplication is the failure of the external link image transfer (img2omS85CI1567509435790)(____________). / assets/Formula _20180905213258.png] and [External Link Picture Transfer Failure (imgROSXCPSQ1567509435790)(... / assets/Formula _20180905213158.png], and the purpose of this code is to filter [External Link Picture Transfer Failure (imgrHr5Fpr71567509435791)(... / assets/Formula _20180905213158.png]  I > Step
Combination sum and 3 (number not repeated and specified number)
LeetCode  216. Combination summation III
Problem Description
Find out all combinations of k numbers that add up to n. Only positive integers containing 1  9 are allowed in combinations, and there are no duplicate numbers in each combination. Explain: All numbers are positive integers. Unset cannot contain duplicate combinations. Example 1: Input: k = 3, n = 7 Output: [[1, 2, 4]] Example 2: Input: k = 3, n = 9 Output: [[1,2,6], [1,3,5], [2,3,4]]
thinking
 stay Combination summation (numbers are not duplicated but reusable) A slight modification is enough.
C++
class Solution { vector<vector<int> > ret; vector<int> tmp; int cur = 0; int K; void dfs(int n, int step) { if (cur >= n) { if (cur == n && tmp.size() == K) // Join the result set only when satisfied at the same time ret.push_back(tmp); return; } for (int i = step; i <= 9; i++) { cur += i; tmp.push_back(i); dfs(n, i + 1); // Because the number can't be reused, it's dfs(i+1) tmp.pop_back(); cur = i; } } public: vector<vector<int> > combinationSum3(int k, int n) { K = k; dfs(n, 1); return ret; } };
[Note]
Dictionary Preface
 When dealing with permutation, the next permutation is usually generated according to dictionary order.
 In a dictionary order, the ascending order of a sequence is the first, and the descending order is the last.
High and Low Positions
 For any two positions in the sequence, the upper position is near the left and the lower position is near the right.
 The process of generating permutation is the process of increasing the high position and decreasing the low position.
1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1
Notes on for(i=0;...) and for(i=step;...)
 for(i=0;.) to be used with the use tag

for(i=step;..)
 All combinatorial problems
 Simply put, take {1,234} as an example

for(i=0;.) for
1 + {2 3 4} 2 + {1 3 4} ...
 Used is used to mark the beginning of 1, 2, etc.

for(i=step;.) for
1 + {2 3 4} 2 + {3 4} ...
 Usually no use tag is required

for(i=0;.) for
[Note] Notes on dfs(step+1), dfs(i+1), dfs(i)
(The following are personal summaries, which are not strictly validated)
dfs(step+1) and dfs(i+1)
 Simply put, dfs(step+1) refers to the step+1 position in the generated tmp sequence; dfs(i+1) refers to the use of the i+1 element in nums
 stay Arrangement (no repetition) In the problem, dfs(step+1) is used.
 stay Combination (no duplication) In the problem, dfs(i+1) is used.
 Relevant code snippets
// array for (int i = step; i < nums.size(); i++) { // ... dfs(nums, step + 1); // ... } // combination for (int i = step; i < nums.size(); i++) { // ... dfs(nums, i + 1); // ... }
 Taking the nonrepetitive set {1 234} as an example, this paper illustrates that:
 Elements used in permutation problems may also be reused.
When step = 0, the first position is 1 All permutations are 1 + {234} When step = 1, the first position is 2 All permutations of 2 + {134} # 1 appear again in the sequential elements ...
 The elements used in combinatorial problems are not used anymore.
When step = 0, the first position is 1 All combinations are 1 + {234} When step = 1, the first position is 2 All combinations 2 + {34}# 1 are no longer used
 It is precisely because of this difference that dfs(step+1) should be used in permutation and dfs(i+1) should be used in combination.
 Elements used in permutation problems may also be reused.
dfs(i+1) and dfs(i)
 stay Combination summation dfs(i) is also used in the problem.
for (int i = step; i < nums.size(); i++) { // ... dfs(nums, i); // ... }
 On the one hand, it is similar to combinatorial problems, where used numbers are no longer used; therefore, i is used instead of step.
 On the other hand, each number can be reused, so dfs(i) is used instead of dfs(i+1)