题目描述:

实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。

如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。

必须原地修改,只允许使用额外常数空间。

以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

题目解析

先找出最大的索引 k 满足 nums[k] < nums[k+1],如果不存在,就翻转整个数组;
再找出另一个最大索引 l 满足 nums[l] > nums[k];
交换 nums[l] 和 nums[k];
最后翻转 nums[k+1:]。

比如 nums = [1,2,7,4,3,1],下一个排列是什么?

我们找到第一个最大索引是 nums[1] = 2

再找到第二个最大索引是 nums[4] = 3

交换,nums = [1,3,7,4,2,1];

翻转,nums = [1,3,1,2,4,7]

代码实现:

class Solution {

      public static void nextPermutation(int[] nums) {

        //寻找满足nums[i]<nums[i+1]的最大索引
int firstIndex = -1;
for (int i = 0; i < nums.length - 1; i++) {
if (nums[i] < nums[i + 1]) {
firstIndex = i;
}
}
//没有找到这样的firstIndex,则翻转整个数组,变成最小的字典序排列
if (firstIndex == -1) {
//sort函数将nums进行升序排列,即翻转了整个数组
Arrays.sort(nums);
} else {
//寻找满足nums[l]>nums[k]的最大索引
int secondIndex = firstIndex + 1;
for (int j = firstIndex + 1; j < nums.length; j++) {
if (nums[j] > nums[firstIndex]) {
secondIndex = j;
}
}
//交换两个位置的元素
swap(nums, firstIndex, secondIndex);
//翻转从k+1到n的所有元素的位置
reverse(nums, firstIndex + 1, nums.length - 1); } } private static void reverse(int[] nums, int begin, int length) { for (int i = begin, j = length; i <= begin + (length - begin) / 2; i++, j--) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
} private static void swap(int[] nums, int firstIndex, int secondIndex) { int temp = nums[firstIndex];
nums[firstIndex] = nums[secondIndex];
nums[secondIndex] = temp;
}
}

时间复杂度:O(n)

空间复杂度:O(1)

最新文章

  1. Android自定义控件(二)
  2. JAVA反编工具件安装 JD-eclipse
  3. 谢欣伦 - OpenDev原创教程 - 串口类CxSerial
  4. Struts 2.3.24源码解析+Struts2拦截参数,处理请求,返回到前台过程详析
  5. linux C 管道
  6. 《机器学习实战》——K近邻算法
  7. bzoj 2829 信用卡凸包(凸包)
  8. heartbeat集群安装配置
  9. IOS 程序运行过程
  10. 极化码的matlab仿真(1)——参数设置
  11. 《C程序设计语言》【PDF】下载链接:
  12. curl 查看一个web站点的响应时间
  13. Tomcat 配置文件server.xml详解
  14. [angularjs] angularjs系列笔记(五)Service
  15. qml: 模块定义与使用
  16. Python全栈之路----递归
  17. HDU3038 How Many Answers Are Wrong 并查集
  18. vue router 跳转到新的窗口方法
  19. D. Monitor Educational Codeforces Round 28
  20. java-自动登录 与 记住用户名

热门文章

  1. vue-过滤器-时间戳转换
  2. 始终让footer在底部
  3. mysql之使用json
  4. 制作linux云主机镜像
  5. 利用协程和socket实现并发
  6. spket IDE插件更新地址
  7. netty-1.从一个最简单的例子开始
  8. 第六章 组件 63 组件传值-父组件向子组件传值和data与props的区别
  9. solr 数据库关联,表数据添加不进solr,一直indexing
  10. Tomcat管理页面