【面试算法题总结06】排序算法

排序算法:

 

例题1:排序数组

解法1:冒泡排序

时间复杂度:O(n^2)

class Solution {
   
    public int[] sort(int[] nums){
         //其实不需要返回int[],因为是在原地进行修改
        if(nums==null){
            //边界条件null
            return null;
        }
        for(int i=0;i<nums.length-1;++i){
   		//进行nums.length-1轮
            boolean isSwap=false;       //优化:如果已经有序了,就直接跳出
            for(int j=0;j<nums.length-i-1;++j){
   
                if(nums[j]>nums[j+1]){
   
                    int temp=nums[j];
                    nums[j]=nums[j+1];
                    nums[j+1]=temp;
                    isSwap=true;
                }
            }
            if(isSwap==false){
   
                break;
            }
        }
        return nums;
    }
}

解法2:选择排序

时间复杂度:O(n^2)

    public void chooseSort(int[] array){
   
        if(array==null){
            //边界条件null
            return null;
        }
        for(int i=0; i<length-1; i++){
   
            int minIndex = i;
            for(int j=minIndex+1;j<length;j++){
   
                if(array[j]<array[minIndex]){
   
                    minIndex = j;
                }
            }
            int temp = array[i];
            array[i] = array[minIndex];
            array[minIndex] = temp; 
        }
    }

解法3:插入排序

时间复杂度:O(n^2)

    public void doInsertSort(int[] array){
   
        if(array==null){
            //边界条件null
            return null;
        }
        for(int index = 1; index<length; index++){
   //外层向右的index,即作为比较对象的数据的index
            int temp = array[index];//用作比较的数据
            int leftindex = index-1;
            while(leftindex>=0 && array[leftindex]>temp){
   //当比到最左边或者遇到比temp小的数据时,结束循环
                array[leftindex+1] = array[leftindex];
                leftindex--;
            }
            array[leftindex+1] = temp;//把temp放到空位上
        }
    }

解法4:快速排序

最坏时间复杂度:O(n^2)
平均时间复杂度:O(n*log2n),且系数很小
如果每次规模为 n的问题我们都划分成 1和 n - 1,每次递归的时候又向 n - 1的集合中递归,这种情况是最坏的,时间代价是 O(n ^ 2)。我们可以引入随机化来加速这个过程,它的时间代价的期望是 O(n)

class Solution {
   
    Random random=new Random();
    public int[] sortArray(int[] nums) {
   
        quickSort(nums,0,(nums.length-1));
        return nums;
    }

    public void quickSort(int[] nums,int start,int end){
   
        if(start>=end){
   
            return;
        }
        //随机化,防止最坏情况(即找一个数组中随机数交换到a[start])
        int ran=random.nextInt(end-start+1)+start;
        swap(nums,ran,start);
        //将nums[start]数字放到正确的位置,返回此位置的下标i
        int i=partition(nums,start,end);
        
        quickSort(nums,start,i-1);
        quickSort(nums,i+1,end);
    }

    //将nums[start]的数字放到正确的位置
    public int partition(int[] nums,int start,int end){
   
        int temp=nums[start];
        int i=start,j=end;
        while(i<j){
   
            while(temp<=nums[j]&&i<j){
        //必须先动右边,否则输入[1,2]就错了
                --j;
            }
            while(nums[i]<=temp&&i<j){
      //一定是<=,而不是<。不然i就不动了
                ++i;
            }
            if(i<j){
   
                swap(nums,i,j);
            }
        }
        swap(nums,start,i);
        return i;
    }

    public void swap(int[] nums,int index1,int index2){
   
        int temp=nums[index1];
        nums[index1]=nums[index2];
        nums[index2]=temp;
    }
}


解法5:堆排序

用PriorityQueue实现:

class Solution {
   
    Random random=new Random();
    public int[] sortArray(int[] nums) {
   
        Queue<Integer> pq=new PriorityQueue<>();
        for(int i=0;i<nums.length;++i){
   
                pq.offer(nums[i]);
        }
        // 返回堆中的元素
        int[] res = new int[pq.size()];
        int idx = 0;
        for(int i=0;i<nums.length;++i) {
   
            res[idx++] =pq.poll();
        }
        return res;
    }
}

手工实现:

class Solution {
   
    public int[] sortArray(int[] nums) {
   
        int heapSize=nums.length;
        buildMaxHeap(nums,heapSize);
        for(int i=heapSize-1;i>=1;--i){
   
            swap(nums,i,0);
            //这里的i应该理解为当前节点下标碰巧为其前面所有节点的个数
            
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值