算法|5.快速排序相关

算法|5.快速排序相关

1.荷兰国旗问题

题意:给定一个数组arr,以arr[R]为划分值,请把arr[R]的数放在数组的左边,等于arr[R]的数放在数组的中间,大于arr[R]的数放在数组的右边,返回等于arr[R]的区间。要求额外空间复杂度为O(1),时间复杂度为O(n)

解题思路:

  • 根据L和R的关系分三种情况讨论:L>R;L==R;L<R
  • L>R==>{-1,-1} LR>{L,R}
  • L<R: <区域右边界——less,>区域左边界——more,遍历指针index
  • 循环条件index<more(小于>区域右边界):若arr[index]和arr[R]相等,index++;若arr[index]<arr[R],index位置和++less位置交换<区域右扩,指针加加;若arr[index]>arr[R],index位置和–more位置交换
  • 注意:<时index–和++less(已经检验过了,等于的或者当前的),>时–more和index交换

核心代码:

public static int[] netherlandsFlag(int[] arr,int L,int R){
    if(L>R){
        return new int[]{-1,-1};
    }
    if(L==R){
        return new int[]{L,R};
    }
    int less=L-1;
    int more=R;
    int index=L;
    while(index<more){
        if(arr[index]==arr[R]){
            index++;
        }else if(arr[index]<arr[R]){
            swap(arr,index++,++less);
        }else{
            swap(arr,index,--more);
        }
    }
    swap(arr,R,more);
    return new int[]{less+1,more};
}

private static void swap(int[] arr, int i, int j) {
    int tmp=arr[i];
    arr[i]=arr[j];
    arr[j]=tmp;
}

测试代码:

//for test
public static void main(String[] args) {
    int[] arr={100,2,37,8,96,4,2,6,7,9,3,45};
    int[] partition=netherlandsFlag(arr,0,arr.length-1);
    System.out.println("划分:"+ Arrays.toString(partition));
    System.out.println(Arrays.toString(arr));
}

测试结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z6GMDgu6-1685106795384)(F:\typora插图\image-20230526203747202.png)]

2.快速排序3.0

经典版本:小于指定值的放在左边,大于的放右边

递归实现:

//递归方式
public static void quickSort1(int[] arr){
    if(arr==null||arr.length<2){
        return ;
    }
    process(arr,0,arr.length-1);
}

private static void process(int[] arr, int L, int R) {
    if(L>=R){
        return ;
    }
    //快速排序的优化手段之一——破坏可能存在的完全逆序
    swap(arr, (int) (L+Math.random()*(R-L+1)),R);//L~(R-L)-1
    int[] equalArea=netherlandsFlag(arr,L,R);
    process(arr,L,equalArea[0]-1);
    process(arr,equalArea[1]+1,R );
}

public static int[] netherlandsFlag(int[] arr,int L,int R){
    if(L>R){
        return new int[]{-1,-1};
    }
    if(L==R){
        return new int[]{L,R};
    }
    int less=L-1;
    int more=R;
    int index=L;
    while(index<more){
        if(arr[index]==arr[R]){
            index++;
        }else if(arr[index]<arr[R]){
            swap(arr,index++,++less);
        }else{
            swap(arr,index,--more);
        }
    }
    swap(arr,R,more);
    return new int[]{less+1,more};
}

private static void swap(int[] arr, int i, int j) {
    int tmp=arr[i];
    arr[i]=arr[j];
    arr[j]=tmp;
}

非递归实现:

//非递归方式
public static class Op{
    public int l;
    public int r;

    public Op(int l, int r) {
        this.l = l;
        this.r = r;
    }
}
//顺序调整过程在荷兰国旗内部
public static void quickSort2(int[] arr){
    if(arr==null||arr.length<2){
        return ;
    }
    int N=arr.length;
    swap(arr, (int) (Math.random()*N),N-1);//L~(R-L)-1
    int[] equalArea=netherlandsFlag(arr,0,N-1);
    Stack<Op> stack=new Stack<>();
    stack.push(new Op(0,equalArea[0]-1));
    stack.push(new Op(equalArea[1]+1,N-1));
    while(!stack.isEmpty()){
        Op op=stack.pop();
        if(op.l<op.r){
            swap(arr,op.l+ (int) (Math.random() * (op.r - op.l + 1)), op.r);
            equalArea=netherlandsFlag(arr,op.l, op.r);
            stack.push(new Op(op.l,equalArea[0]-1));
            stack.push(new Op(equalArea[1]+1,op.r ));
        }
    }
}

//荷兰国旗
public static int[] netherlandsFlag(int[] arr,int L,int R){
    if(L>R){
        return new int[]{-1,-1};
    }
    if(L==R){
        return new int[]{L,R};
    }
    int less=L-1;
    int more=R;
    int index=L;
    while(index<more){
        if(arr[index]==arr[R]){
            index++;
        }else if(arr[index]<arr[R]){
            swap(arr,index++,++less);
        }else{
            swap(arr,index,--more);
        }
    }
    swap(arr,R,more);
    return new int[]{less+1,more};
}

private static void swap(int[] arr, int i, int j) {
    int tmp=arr[i];
    arr[i]=arr[j];
    arr[j]=tmp;
}

测试代码:

​ isEqual

测试结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4oiDoLUt-1685106795385)(F:\typora插图\image-20230526205807883.png)]

快速排序算法总结

算法描述:

复杂度分析及评价指标:

  • 时间复杂度:平均/最好:O(nlogn)
  • 空间复杂度:平均最好:O(nlogn)
  • 证明忽略
  • 不稳定

划分:

  • 荷兰国旗——大于区左扩,小于区右扩,三个index调整

例题总结:

  • 荷兰国旗总结:大于区左扩,小于区右扩,index<more,swap(arr,index++,++less),swap(arr,index,--more);
  • 快速排序递归实现:荷兰国旗替代M;优化破坏完全逆序结构: swap(arr, (int) (L+Math.random()*(R-L+1)),R);//L~(R-L)-1
    process(arr,L,equalArea[0]-1); process(arr,equalArea[1]+1,R );
  • 快速排序非递归实现:new Op(op.l,op.r); if(op.l<op.r){ swap(arr,op.l+ (int) (Math.random() * (op.r - op.l + 1)), op.r); equalArea=netherlandsFlag(arr,op.l, op.r); stack.push(new Op(op.l,equalArea[0]-1)); stack.push(new Op(equalArea[1]+1,op.r )); th.random() * (op.r - op.l + 1)), op.r);
    equalArea=netherlandsFlag(arr,op.l, op.r);
    stack.push(new Op(op.l,equalArea[0]-1));
    stack.push(new Op(equalArea[1]+1,op.r ));
    }`
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值