一、问题描述
给出一个数组,按照字典顺序找出下一个排列。如果给出是最大的,则返回最小
例子:123,下一个比123大的排列是132
321,这是最大的数,返回最小的数123
115,下一个比112大的数是152
二、问题解决
最终要的是这个寻找下一个排列数的思路。
举一个例子,假设有如下数组:
第一步:我们从后往前遍历,寻找第一个位置i,其中i满足nums[i]<nums[i+1],即前项数比后项数小。因为下一个排列数一定比当前数大,当数组从后往前依次递增的时候表示数是最大的,在i处数突然变小了,说明使用后面的一位比i更大的数来替换i能获得更大的排列数。
第二步:从i处向后寻找,找到一个比i处数更大,但是和i处数之差最小的位置j。要得到下一个排列数,一定要使换到u处的数尽可能小,但是要大于i处的数。
第三步:调换i和j处的数。这样确保了i处的数是最合适的。
第四部:对i+1到末尾的数据进行从小到大排序。最高位替换成了更大的数,故后面的数要尽可能的小,大的数要往后排。
代码如下:
void nextPermutation(vector<int>& nums) { int last = INT_MIN; int i; for (i = nums.size() - 1; i >= 0; i--) { if (nums.at(i) < last) break; last = nums.at(i); } //判断数据是否是最大排列数,如果是,返回最小排列数 if (i == -1) { sort(nums.begin(), nums.end()); return; } int min_pos = i; int min = INT_MAX; for (int j = i; j < nums.size(); j++) { if (nums.at(j) - nums.at(i)>0&& nums.at(j) - nums.at(i)< min) min_pos = j; } swap(nums.at(i), nums.at(min_pos)); sort(nums.begin()+i+1,nums.end()); } int main() { vector<int> v = {2,3,1}; nextPermutation(v); for (auto k : v) { cout << k << endl; } system("pause"); return 0; }