下面的是leetcode的905 ,是吧偶数放在前面,奇数放在后面,这个和快排的大于target 放在前面,小于的放在后面是类似的,但是while 少了很多,只有1个while,但是快排用这个我试了下不对,因为有顺序要求,而这个没有?
public int[] sortArrayByParity1(int[] nums) {
int length = nums.length;
int left=0;
int right=length-1;
while (left<right){
if(nums[left]%2==0){
left=left+1;
}
else {
if(nums[right]%2==1){
right=right-1;
}else {
int tmp=nums[left];
nums[left]=nums[right];
nums[right]=tmp;
left=left+1;
right=right-1;
}
}
}
return nums;
}
1:他这个和偶数放在前面的是不同的(这个是left 和right 互相交换,交换的时候借助tmp 变量),
这个其实是 “赋值的思想”, 赋值后,一方就是空的了,下一次就是给这个空的赋值了
下面是赋值的代码,交换的话有3行,而赋值只有1行
2:而且他这个和二分查找的区别是虽然都是left, right ,二分查找因为是递增的数组,每次变化都是一半的, left=middle+1, 而这个是每次只变化一个。 left=left+1
3: 因为我们默认选取的排序的数据是target=left, 从left开始的,(也就是说 第一个洞其实是left), 所以我们需要从右边开始遍历找到数据填补left的, 所以第一个while 循环是从右边开始的
4: 其实下面第二个while 是从右边找到一个符合条件的,第三个是从左边找到符合条件的
而最外层的while执行一次后,是 找到1对符合条件的(所有最外层的可能执行1次,或者2次等)
4: while1(){
while2(){}
赋值
while3(){}
赋值
}
5:因为逻辑是右边的填充左边的洞,左边的填充右边的洞, 看起来是 偶数个,但是万一只有奇数个,因为推出循环的时候left=right, 所以target 直接放在left 或者right 位置都是可以的。
下面是随机选择的target,不再是最左边了,但是不知道为啥报错,
int target=nums[left]; int randomIndex = left + (int)(Math.random() * (right - left + 1)); System.out.println(randomIndex+" left is "+left+" right is "+right); target=nums[randomIndex];
public int[] sortArray(int[] nums) {
return ss(nums,0,nums.length-1);
}
public static int[] ss(int[] nums,int left, int right){
if(left<right){
int paixyss = paixyss(nums, left, right);
ss(nums,left,paixyss-1);
ss(nums,paixyss+1,right);
}
return nums;
}
public static int paixyss(int[] nums, int left, int right){
// 小 大
int target=nums[left];
while (left<right){
/*
*
*
* */
/*
* 因为target 不能放在left, 所以右边的是可以=target,
* 而left的是不行的nums[right]>=target
*
*
* */
while (left<right && nums[right]>=target){
right=right-1;
}
/* 从右边找到第一个大于的值,然后和left的交换 , 此时右边是个洞了。 所以下面从左边开始找,找个数据填充右边的洞
*
* */
if(nums[right]<target){
nums[left]=nums[right];
}
while (left<right && nums[left]<target){
left=left+1;
}
if(nums[left]>=target){
nums[right]= nums[left];
}
}
nums[right]=target;
return right;
}