leetcode31——下一个排列
思路
令待交换的两个数为“小数”和“大数”
1. 从后往前找第一个升序对i,j使得nums[i]<nums[j]。“小数”就是nums[i]。此时[j,end)必然是降序
2. 再从后往前找一个比“小数”大的数作为“大数”,交换二者
3. 交换后将“大数”后的所有数重新排为升序:此时[j,end]仍必为降序,所以逆置即可
疑难点:
- 为什么从后往前找:尽可能让交换后的排列更小
比如1243 ,交换2和3为1342肯定比交换1和2为2143好
- 为什么是第一个升序对:降序对交换后的排列比原来更小
比如321,交换21为312
- 为什么还要再往前找一次:(j,end]之间是降序,想让待交换的大数尽可能小的同时又比待交换的小数要大
比如5764,此时i=0,j=1,直接交换为7564,而选比7小的又比5大的数交换比如6为6754就会更小
总结:
- 从后往前找第一个升序对i,j。nums[i]就是小数
- 再在[j,end]从后往前找一个比小数大的作为大数,交换二者
- 把大数后的所以数逆置reverse
代码
class Solution {
public:
void nextPermutation(vector<int>& nums) {
// 从后往前找第一个升序对
int i = nums.size() - 2;
while(i >=0 && nums[i] >= nums[i+1]){
i--;
}
// 如果nums是321这种则i=-1,直接reverse
// 否则再从后往前找真正的大数
if(i>=0){
int j = nums.size()-1;
while(j >= i+1 && nums[j] <= nums[i]){ // >= i+1更好理解
j--;
}
swap(nums[i],nums[j]);
}
reverse(nums.begin() + i + 1,nums.end());
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架