Question:
Give a set of non-negative integers and rearrange them to form the largest integer.
Example:
Given [1, 20, 23, 4, 8], the integer with the largest return combination should be 8423201.
Challenge:
Time complexity: O(nlogn)
Sources of the problem:
http://www.lintcode.com/zh-cn/problem/largest-number/
Train of thought:
Two ideas:
1:
1. Store all bits of all elements in vector in two-dimensional array in element order; //O(Cn)
2. Compare the size of the first place of all elements in vecotr. Take an example, that is, compare the size of 1, 2, 2, 4 and 8, and sort and record their positions. Binary sort can be used for ranking; / Time complexity is O(nlogn)
3. Based on the previous step, do the second ranking, do not participate in the ranking without the second ranking, record the position after the ranking; / Time complexity is O(nlogn)
4. Repeat the above process until no element exists and no bit is involved in the sorting; //Total time complexity is O(nlogn)
5. Output based on recorded location.
Two:
1. Find the maximum value of all elements of vector, confirm whether it is in the same order of magnitude as the int limit, proceed step 2 if not, and proceed step 3 if it is in; //O(n)
2. If the maximum value and the int limit are not in the same order of magnitude, then all the remaining numbers are raised to the order of magnitude where the maximum value is located, and then directly binary sorting is performed to record their positions and output them according to their positions; //O(nlogn)
3. If the maximum value and the int limit are in the same order of magnitude, then the elements of the order of magnitude in all the elements of vector are counted, and their positions are recorded by binary sorting; //O(nlogn)
4. Divide the elements sorted in the previous step by 10 and decrease in order; //O(n)
5. Raise the remaining elements in vector to the order of magnitude of the previous step, sort all elements, record their positions, and output them according to their positions; //O(nlogn)
In fact, the above two ideas can be summed up as the same idea, all elements in the same order of magnitude, but the difference is that one is the descending operation, the other is the ascending operation.
Degradation operations require sorting of each element, so the relative constant C is larger. And because additional element bit information needs to be recorded, the spatial complexity will be relatively large.
So this paper adopts the incremental operation. One of the most notable points of incremental operation is that it can not exceed the int limit, so when the existing elements and the int limit are in the same order of magnitude, we first need to operate on these elements, and then upgrade the rest of the elements.
Code:
1 class Solution { 2 public: 3 /* 4 * @param nums: A list of non negative integers 5 * @return: A string 6 */ 7 string largestNumber(vector<int> &nums) { 8 // write your code here 9 vector<int> order_nums = nums; 10 vector<int> sort_nums = nums; 11 vector<int> sitea = nums; 12 vector<int> siteb = nums; 13 vector<int> overnum, oversite; 14 int MaxN = nums.size(); 15 int IntMax = 1 << 31;//Achieve the int limit 16 int NumMax = 0; 17 int Nlevel = 0; 18 int gain = 1; 19 int Ilevel = 0; 20 int Tmp = -1; 21 string out = ""; 22 if (MaxN <= 1) {//Simple exception and case handling 23 if (MaxN){ 24 return to_string(nums[0]); 25 } 26 return ""; 27 } 28 for (int i = 0; i < MaxN; i++) {//Finding the Maximum, Time Complexity O(n) 29 sitea[i] = 0; 30 if (NumMax < nums[i]) { 31 NumMax = nums[i]; 32 } 33 }// O(n) 34 Tmp = NumMax / 10;//Reduced magnitude of maximum recorded value 35 if (!NumMax) {//Simple case handling 36 return "0"; 37 } 38 while (NumMax) {//Get the maximum magnitude 39 Nlevel++; 40 NumMax /= 10; 41 }// O(c) 42 while(IntMax) {//Getting the limit order of int 43 Ilevel++; 44 IntMax /= 10; 45 } 46 if (Nlevel == Ilevel) {//Is the maximum magnitude consistent with the int limit magnitude 47 gain *= pow(10, Nlevel - 2);//Minimum value after escalation 48 for (int i = 0; i < MaxN; i++) {//Get all numbers in the same order of magnitude as the maximum magnitude 49 if(order_nums[i] >= gain) { 50 overnum.insert(overnum.end(), order_nums[i]); 51 oversite.insert(oversite.end(), i); 52 } 53 } 54 vector<int> oversort = overnum; 55 vector<int> sortsite = oversite; 56 vector<int> storesite = oversite; 57 twosort(oversort, overnum, sortsite, oversite, 0, overnum.size() - 1, (overnum.size() - 1) / 2);//Sort all numbers in the same order of magnitude as the maximum magnitude and record their positions 58 for (int i = 0; i < oversort.size(); i++) {//All the numbers in the same order of magnitude as the maximum magnitudeDegradation operation 59 nums[storesite[i]] = oversort[i]; 60 order_nums[storesite[i]] = sort_nums[storesite[i]] = Tmp--; 61 } 62 } 63 else { 64 gain *= pow(10, Nlevel - 1);//Minimum value after escalation 65 } 66 for (int i = 0; i < MaxN; i++) {//Incremental operation based on gain value 67 siteb[i] = i; 68 order_nums[i] = gainnum(order_nums[i], gain, order_nums[i]); 69 //cout << order_nums[i] << " " << gain << endl; 70 }// O(cn) 71 twosort(order_nums, sort_nums, sitea, siteb, 0, MaxN - 1, (MaxN - 1) / 2);//Sort all numbers and record their positions 72 for (int i = 0 ;i < MaxN; i++) {//Output all values according to location 73 out += to_string(nums[sitea[i]]); 74 } 75 return out; 76 } 77 78 int gainnum(int num, const int gain,const int ori) {//The incremental function judges whether num has reached the corresponding magnitude according to the incoming gain value, and judges whether num is zero. 79 if (num >= gain || !num) { 80 //cout << num << endl; 81 return num; 82 } 83 //cout << num << endl; 84 return gainnum(num * 10 + ori, gain, ori);//Ensure that the num number after the escalation operation is 1... 1 times the original num number 85 } 86 87 int twosort(vector<int> &nums, vector<int> &sort, vector<int> &sitea, vector<int> &siteb, const int start, const int end, int mid) {//Binary sorting algorithm and record location at the same time 88 if (start >= end) {//When the starting position of an array is greater than or equal to the end position, it can be considered sorted 89 return 0; 90 } 91 int fr = start, bc = end, MidNum = nums[mid], tmp =start; 92 for (int i = start; i <= end; i++) { 93 if (nums[i] > MidNum) {//In general, the value is placed in the front segment of the array. 94 sort[fr] = nums[i]; 95 sitea[fr] = siteb[i]; 96 fr++; 97 } 98 else if (nums[i] < MidNum) {//Small puts the value behind the array 99 sort[bc] = nums[i]; 100 sitea[bc] = siteb[i]; 101 bc--; 102 } 103 else {//Equal to skip 104 continue; 105 } 106 }//O(n) 107 tmp = fr; 108 for(int i = start; i <= end; i++) {//Parallel placement of equivalence in the middle of the front and rear segments 109 if (nums[i] == MidNum) { 110 sort[tmp] = nums[i]; 111 sitea[tmp] = siteb[i]; 112 tmp++; 113 } 114 }//O(n) 115 if ((bc == end && tmp <= bc)) {//When all elements are larger than the last value of the array and the size of the preceding + equivalence case is within the range of the array, the sorting is considered complete. 116 nums = sort; 117 siteb = sitea; 118 return 0; 119 } 120 nums = sort; 121 siteb = sitea;//Assign arrays and positions to another array and location for the next round of sorting 122 twosort(nums, sort, sitea, siteb, start, fr - 1, (start + fr - 1) / 2);//Preceding sorting 123 twosort(nums, sort, sitea, siteb, tmp, end, (tmp + end) / 2);//Backend sorting 124 return 0; 125 }//O(nlogn) 126 };
Greedy Law:
This topic is a very simple application of greedy method. If the first method is used, it can be clearly seen that each step is looking for the maximum of the current position until it reaches the peak (that is, there is no next position). Although the second method has only two-step sorting at most, it also adopts the same idea: find the maximum of the same order of magnitude, and then sort the output.
Binary Sort & Pointer:
The main idea of binary sorting is to arrange the number of values larger than the middle position on the front/back segment of the array and smaller than the other segment. When there are multiple values equal to the middle position value, it is recommended to insert the confirmed middle position in the front and back segments in parallel without changing its order.
Repetition of the call itself completes the arrangement of the entire array.
However, it should be noted that when a function passes a parameter, it is a copy of the parameter, not the parameter itself, so when twosort passes out the sorted value and its corresponding location, it needs to take its address to pass in.
That is, int twosort (vector < int > & nums, vector < int > & sort, vector < int > & sitea, vector < int > & siteb, const int start, const int end, int mid)
In this paper, vector vectors are used instead of arrays because the array passes in the first address of the array, but to assign, the assignment operation such as siteb=sitea can not be carried out directly, which will only point the siteb's pointer to the location of the sitea's pointer, i.e. & Sitea [0].
If you want to use arrays and assign arrays, you need to use the for loop to assign them. Although the time complexity is unchanged in the case of n, the code will be redundant.
This problem can be avoided by using vector vectors. Although the address of vectors is the same as that of twosort, when it is operated, it is not for the address, but only for the value to be changed, and the vectors can be operated (vector < int >) a = b, so the code will be concise and clear.
Although the title is not difficult, the recognition of greed and binary sorting is a step, no longer just reading books and reading code.