题目内容:
题目解析:也就是说,用一个数组来表示一个数,数组最右边是个位。找到大于这个数的另一个数b,这个数b不仅要大于给出的数,还要尽可能小。
方法:
1.题目是找出大于当前数的最小的那个数。假如从左到右,数字按降序走,则一定不可能有更大的数。因为从左到右降序的话,数字一定是最大的。
2.所以说,应该从右往左找,第一个满足(左到右升序)nums[i-1]<nums[i]的下标i-1,令mark=i-1。此时nums[mark]<nums[mark+1],nums[mark+1]到数组结尾是降序。
3.mark右侧(不包括mark)应该是一个从左到右的递减序列,在这个序列里,找大于nums[mark]的最小的数的下标mark1。交换nums[mark]和nums[mark1]。
4.交换之后,因为mark处的数字已经比原来的大了,[0,mark]处的数字不变,所以当前数一定大于原来的数,但是不一定是最小的那个,怎样找到最小的那个数呢?把mark右侧,不包括mark的所有的数变成从左到右的升序即可。
class Solution {//看笔记 public void nextPermutation(int[] nums) { if(nums.length==2&&nums[0]>nums[1]) { swap(nums,0,1); return ; } else if(nums.length==2&&nums[0]<=nums[1]) { swap(nums,0,1); return; } int length=nums.length; int mark=-1; int mark1=-1;//大于nums[mark]的第一个数 int i=length-1; int j=nums.length-1; for(;i>0;i--)//从右到左找nums[i-1]<nums[i]的数i-1 { if(nums[i-1]>=nums[i]) continue;//这里会错,要找递增的数,递增的反面就是>= else { break; } } int biaoji=i;//用一个数标记i if(biaoji>0)//假如biaoji==0,说明从左到右所有数字依次递减,无更大的数,直接反转所有数字即可 { mark=biaoji-1;//要找的那个数,mark右侧的数组是递减的,但是nums[mark]<nums[mark+1] for(;j>mark;j--)//找大于nums[mark]的最小的数 { if(nums[j]>nums[mark])//mark是下标,不是数字,这里别写错 { break; } } mark1=j; swap(nums,mark,mark1); reverse(nums,mark+1); } if(biaoji==0)//此时,从左到右,序列递减,没有更大的数,按照题意,整个数组变成升序即可 { reverse(nums,0); } } public void swap(int[] nums,int a,int b)//交换两个数 { int temp=nums[a]; nums[a]=nums[b]; nums[b]=temp; } private void reverse(int[] nums, int start) {//如果对一个降序数组用这个函数,从start开始,包括start,变成升序 int i = start, j = nums.length - 1; while (i < j) { swap(nums, i, j); i++; j--; } } }
结束。