[leetcode]Next Permutation

本文介绍了一种改进的NextPermutation算法实现,通过从后往前遍历找到临界点,进而找到后驱数字并进行排序。此算法解决了如何在给定数字字符串中找到排列的后驱问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

怎么说呢,这篇博文的算法还是很不错的,新博文采用的还是这篇博文的就算法,只不过代码更简洁,可能读可能更好一点,有兴趣请移步,新博文地址:[leetcode]Next Permutation

Next Permutation

Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order).

The replacement must be in-place, do not allocate extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column.
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

 给你一个数字组成的字符串,这组数字可以排列成大概n!个数字(当有重复数字的时候,排列数< n!)结果要求你返回排列中原字符串的后驱数字。

例如123可以组成123,132,213,231,312,321,其中132是123的后驱,同理213是132的后驱,当321达到最大时,则返回最小的排列情况123,最为其后驱。

这道题比较折腾,做了很长时间。

我的算法首先必须从后往前遍历。原因很明显,请往下看:

1. 从后往前遍历,找到临界点

1.1 如果发现某个位置,前面的数字变小了。比如132中,1比3小,则1就是临界点。

1. 2 如果数字越来越大,比如321。2比1,3比2大,则这个数是最大的。这是显然的。标记之。

 

2.从1后面的3开始往后遍历,找到比1大的最小的数字,本例中是2。然后将2与1交换。这时数字变成了231

3.对2后面的所有数字做排序,即对31做排序,得到13,最终结果是213。

这下大家就很明显的看出来为什么必须从后往前遍历。

代码如下:

    public void nextPermutation(int[] num) {
        if(num == null || num.length <= 1){
        	return;
        }
        boolean tag = true;
        for(int i = num.length - 1; i > 0 ; i--){
        	if(num[i] > num[i - 1]){
        		for(int j = i ; j < num.length; j++){
        			if(num[j] > num[i - 1] && (j == num.length - 1 || num[j + 1] <= num[i - 1]  )){
        				int tem = num[j];
        				num[j] = num[i - 1] ;
        				num[i - 1] = tem;
        				break;
        			}
        		}
        		int[] copy = Arrays.copyOfRange(num, i ,num.length);
        		Arrays.sort(copy);
        		for(int j = i; j < num.length; num[j] = copy[j - i],j++);
        		tag = false;//标记找到了临界点
        		break;
        	}
        }    
        if(tag){//如果没有找到临界点,则该排列数是最大的,变为最小的即可
        	for(int i = 0; i < num.length / 2; i++){
        		int temp = num[i];
        		num[i] = num[num.length - 1 - i];
        		num[num.length - 1 - i] = temp;
        	}
        }
    }

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值