LeetCode进阶之路(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

题目:通过这道题目发现英语真的是渣,要是用例很少,根本看不懂题目,针对这道题目的用例,也是踩了好几个坑,修改了好几次。题目意思是给定一个排列好的数字,找出下一个比它的数列(如果它是最大的,那倒序输出最小的)。一开始的思路是从后往前遍历,遇到后一个比前一个大的就行了,把他们交换位置,就比前一个大(这里有bug,因为前面已经遍历过的数字也有可能比前一个大,所以还需要往后面找)。提交后有错误,发现剩下的还需要从小到大排序。

另外,关于这类数组的题目,都有一个要求,不能创建新的数组。

既然这样,那我们就还是按照一开是的思路,遇到后一个num[i]比前一个大num[i-1]的,达到目标点,就往后遍历,直到遇到一个num[j]比num[i-1]大,且num[j+1]比num[i-1]小,或者num[j是最后一个。再把剩下的按升序排列。

<span style="font-size:18px;">public void nextPermutation(int[] nums){
		boolean change = false;
		for(int i = nums.length-1; i > 0; i--) {
			boolean flag = false;
			if(nums[i] > nums[i-1]) {//找到临界点
				if(i == nums.length-1) {//如果临界点是最后一个,那直接交换顺序,结束
					int tmp = nums[i];
					nums[i] = nums[i-1];
					nums[i-1] = tmp;
					flag = true;
					change = true;
					break;
				}
				for(int j = i; j < nums.length-1;j++) {//找到临界点后往后遍历,找下一个临界点
					if((nums[j] > nums[i-1] && nums[j+1] <= nums[i-1])){
						int tmp = nums[j];//下一个临界点是中间某个位置,交换位置,后面的排序
						nums[j] = nums[i-1];
						nums[i-1] = tmp;
						sort(nums, i);
						flag = true;
						change = true;
						break;
					} else if(j+1 == nums.length-1 && nums[j+1] > nums[i-1]) {如果
						int tmp = nums[j+1];//临界点是最后一个位置,交换位置,后面的排序。
						nums[j+1] = nums[i-1];
						nums[i-1] = tmp;
						sort(nums, i);
						flag = true;
						change = true;
						break;
					}
				}
			}
			if(flag) {
				break;
			}
		}
		if(!change){
			Arrays.sort(nums);
		}
	}
	
	public void sort(int[] nums, int start){//yo冒泡给后面的数列排序
		if(start >= nums.length) {
			return;
		}
		for(int i = start; i < nums.length; i++) {
			for (int j = nums.length - 1; j >= i + 1; j--) {
				if (nums[j] < nums[j - 1]) {
					int tmp = nums[j - 1];
					nums[j - 1] = nums[j];
					nums[j] = tmp;
				}
			}
		}
	}</span>

用到冒泡排序都思考了半天,更不用说快速排序了,下面把这两种排序整理一下。

冒泡排序:原理就是把最小的往上浮,若干躺之后即为有序。

public void bubbleSort(int[] nums) {
		for(int i = 0; i < nums.length;i++) {
			for(int j = nums.length-1; j > i;j-- ){//遍历一遍,把最小的往第一位移
				if(nums[j] < nums[j-1]) {
					int tmp = nums[j];
					nums[j] = nums[j-1];
					nums[j-1] = tmp;
				}
			}
		}
	}


快速排序:原理是先找一个基准数,小于基准数的放左边,大于基础数的放右边。基准数两边的数组继续这个动作,直到完成为止。

交换数字掌握一个词:挖坑填数

public void quickSort(int[] nums, int left, int right ) {//先找一个基准数,小于基准数的放,大于基础数的放左边。继续这个动作,直到完成为止。
		if(left < right){
			int i = left, j = right, key = nums[left];//left位置的坑已挖好
			while(i < j) {
				while(i < j && nums[j] >= key) {//从左边开始遍历,寻找第一个比key小的数。
					j--;
				}
				if(i < j) {
					nums[i] = nums[j];//用num[j]来填left位置的坑,同时j位置的坑已挖好。
					i++;
				}
				while(i < j && nums[i] <= key) {//从右边开始遍历,寻找第一个比key大的数。
					i++;
				}
				if(i < j) {
					nums[j] = nums[i];//用num[i]来天j位置的坑,同时i位置的坑也已填好。
					j--;
				}
			}
			nums[i] = key;//最后一个坑用key来填。
			quickSort(nums, left, i-1);//i左边的数组重复快排。
			quickSort(nums, i+1, right);//i右边的数组重复快排。
		}
	}

种一棵树最好的时间是十年前,其次是现在!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值