快排中的思路(快速排序)-912题目

LeetCode905:偶数在前,奇数在后的排序算法解析
文章详细分析了LeetCode第905题的解决方案,该题要求将数组中的偶数移到前面,奇数移到后面。这个方法与快速排序的思路类似,但只有一个while循环,通过赋值而非交换实现。文中对比了赋值和交换的区别,以及与二分查找的不同,并解释了为何不能直接应用快排的逻辑。此外,文章还讨论了处理奇数个数时的特殊情况。

下面的是leetcode的905 ,是吧偶数放在前面,奇数放在后面,这个和快排的大于target 放在前面,小于的放在后面是类似的,但是while 少了很多,只有1个while,但是快排用这个我试了下不对,因为有顺序要求,而这个没有?

. - 力扣(LeetCode)

    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;

}

### 快速排序算法的实现与原理 快速排序是一种基于分治思想的高效排序算法,其核心思想是通过一个划分操作将待排序的数组分为两个子数组,使得左侧子数组中的所有元素均小于或等于右侧子数组中的所有元素。然后递归地对这两个子数组进行排序,最终得到一个有序数组[^1]。 快速排序的主要步骤如下: 1. **选择基准值(Pivot)**:从数组中选取一个元素作为基准值,通常可以选择第一个元素、最后一个元素或中间元素。 2. **分区操作(Partition)**:重新排列数组,使得所有小于基准值的元素位于其左侧,所有大于基准值的元素位于其右侧。 3. **递归排序**:分别对左右两个子数组递归地应用上述两步操作,直到子数组的长度为0或1时停止递归。 以下是快速排序的Python实现代码: ```python def quick_sort(arr): if len(arr) <= 1: return arr else: # 选择基准值 pivot = arr[len(arr) // 2] # 分别存放比基准小和大的元素 left = [x for x in arr if x < pivot] middle = [x for x in arr if x == pivot] right = [x for x in arr if x > pivot] # 递归地对左右两边进行快排,并合并结果 return quick_sort(left) + middle + quick_sort(right) ``` 快速排序的时间复杂度在平均情况下为 \(O(n \log n)\),但在最坏情况下(例如输入数组已经是有序的),时间复杂度会退化到 \(O(n^2)\)。然而,由于基准值的选择策略可以优化(如随机选择基准值),实际运行中快速排序的表现通常优于其他稳定 \(O(n \log n)\) 的排序算法,如归并排序。 对于7-2题解,如果该题目涉及计算逆序对数量的问题,则可以参考归并排序的修改版本来解决。尽管快速排序本身不直接用于计算逆序对,但其分治思想与归并排序类似,因此可以借鉴归并排序的思路[^3]。 ### 注意事项 快速排序的性能依赖于基准值的选择。在实际应用中,可以通过随机化基准值的方式避免最坏情况的发生。此外,快速排序是非稳定的排序算法,即相等元素的相对顺序可能会改变。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值