题目链接: 31. 下一个排列 - 力扣(LeetCode)
简单来说,这道题的意思是给定一个数组,按这个数组数字的顺序组成一个整数,让我们找到以这个数组中的数字组成的比当前这个数字大的第一个数,能组成的比当前数更大的数字有很多个,要求找到最小的一个,如果找不出比当前数字更大的,即这个数就是当前数字组合的最大值,就把这个数组按升序排序,取最小的。例如[1,2,3]的下一个比123更大的数是132。[3,2,1]已经是这三个数字能组成的整数中的最大值,找不到更大的组合,那就把[3,2,1]按升序排序得到[1,2,3]就是答案。
解题思路:
参考代码如下,已经附上详细的解释,相信聪明的各位小伙伴都能看懂并学会这道题的哈
class Solution { public: void nextPermutation(vector<int>& nums) { //利用i和j下标从后往前查找能组成比所给nums组合更大的数 int i = nums.size() - 2; int j = nums.size() - 1; //由于i是前一个元素的下标,j是后一个元素的下标,所以i是大于等于0的 //j是大于0的 while (i >= 0 && j > 0) { //由于我们是从后往前找的,所以如果前一个元素大于等于后一个元素, //说明从nums[i]开始往后的元素都是升序的,即最大的,所以i--,j-- // 继续往前找,直到找到nums[i]<nums[j]的时候,则从nums[i]开始 //往后的数字组合才能找到比当前组合更大的 if (nums[i] >= nums[j]) { i--; j--; } else { break; } } //如果i<0,说明给定的这个组合就是这个数组元素所能组成的最大值, //找不到比这个数更大的组合了,将数组排成升序,返回最小值 if (i < 0) { sort(nums.begin(), nums.end()); return; } //找到的nums[i]<nums[j],先用tmp保存下来 int tmp = nums[i]; //mini用来记录比nums[i]大的最小的数字的下标,可以初始化为j,因为 //nums[j]就是其中一个比nums[i]的数,不影响后面的更新,不能给mini //随意赋值 int mini = j; //min用来记录nums[i]往后的数与nums[i]的最小差距 int min = nums[i+1] - nums[i]; //由于j位置的数据已经被上面记录过了,所以我们可以从j+1的位置开始往后找出 //与nums[i]最接近的并且最小的数,即与tmp最接近的并且最小的数 for (int m = j + 1 ; m < nums.size(); m++) { //如果往后找到比tmp大并且与tmp差距值更小的数,就记录更新mini if (nums[m] > tmp && nums[m] - tmp < min) { mini = m; } } //mini就是从i开始往后找到的比nums[i]大并且最小的数的下标,使nums[i]和 //nums[mini]交换,具体实例可以结合上面例题的图片解释 swap(nums[i], nums[mini]); //最后把nums[i]后面的数进行升序排序即可 sort(nums.begin() + i +1, nums.end()); } };