java排序代码总结-快排、归并

一.快速排序

快速排序(Quicksort)是对冒泡排序的一种改进。基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

方法一:韩顺平讲解

public static void quickSort(int[] arr,int left, int right) {
		int l = left; //左下标
		int r = right; //右下标,这里起始传参数时要,输入数组最后一个下标。
		//pivot 中轴值
		int pivot = arr[(left + right) / 2];
		int temp = 0; //临时变量,作为交换时使用
		//while循环的目的是让比pivot 值小放到左边
		//比pivot 值大放到右边
		while( l < r) { 
			//在pivot的左边一直找,找到大于等于pivot值,才退出
			while( arr[l] < pivot) {
				l += 1;
			}
			//在pivot的右边一直找,找到小于等于pivot值,才退出
			while(arr[r] > pivot) {
				r -= 1;
			}
			//如果l >= r说明pivot 的左右两的值,已经按照左边全部是
			//小于等于pivot值,右边全部是大于等于pivot值
			if( l >= r) {
				break;
			}
			
			//交换
			temp = arr[l];
			arr[l] = arr[r];
			arr[r] = temp;
			
			//如果交换完后,发现这个arr[l] == pivot值 相等 r--, 前移
			if(arr[l] == pivot) {
				r -= 1;
			}
			//如果交换完后,发现这个arr[r] == pivot值 相等 l++, 后移
			if(arr[r] == pivot) {
				l += 1;
			}
		}
		
		// 如果 l == r, 必须l++, r--, 否则为出现栈溢出
		if (l == r) {
			l += 1;
			r -= 1;
		}
		//向左递归
		if(left < r) {
			quickSort(arr, left, r);
		}
		//向右递归
		if(right > l) {
			quickSort(arr, l, right);
		}
		
		
	}
//方法二:递归的另一种写法,这里的划分的选取的最左边的值做参考;剑指offer-取第k小的值

 private int[] quickSort(int[] arr, int l, int r) {
        // 子数组长度为 1 时终止递归
        if (l >= r) return;
        // 哨兵划分操作(以 arr[l] 作为基准数)
        int i = l, j = r;
        while (i < j) {
            while (i < j && arr[j] >= arr[l]) j--;
            while (i < j && arr[i] <= arr[l]) i++;
            swap(arr, i, j);
        }
        swap(arr, i, l);
        // 递归左(右)子数组执行哨兵划分
        quickSort(arr, l, i - 1);
        quickSort(arr, i + 1, r);
    }


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

1.快排变形:求数组的k个小值

题目链接:力扣

2.快排:比较值字符变形

输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。

题目链接:力扣

class Solution {
    public String minNumber(int[] nums) {
        //1.将数组转为字符数组
        String[] strs = new String[nums.length];
        for(int i =0;i<nums.length;i++){
            strs[i]=String.valueOf(nums[i]);
        }
        //2.快排
        quickSort(strs,0,strs.length-1);
        //3.将字符数组转为字符串,此时借助stringbuffer
        StringBuilder res = new StringBuilder();
        for(String num:strs){
            res.append(num);
        }
        return res.toString();

    }
    //根据本题特定的规则进行快排
    public void quickSort(String[] strs,int l,int r){
        //跳出递归的条件
        if(l>=r) return;
        int i = l;
        int j = r;
        String tem=strs[i];
        while(i<j){
            
            while(i<j && (strs[j]+strs[l]).compareTo(strs[l]+strs[j])>=0) j--;
            while(i<j && (strs[i]+strs[l]).compareTo(strs[l]+strs[i])<=0) i++;
            //交换两个值
            tem = strs[i];
            strs[i]=strs[j];
            strs[j]=tem;
            
        }
        //交换l,i值
        strs[i]=strs[l];
        strs[l]=tem;
        //向左右递归
        quickSort(strs,l,i-1);
        quickSort(strs,i+1,r);
        
    }
}

二、归并排序

1、归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治divide-and-conquer)策略(分治法将问题(divide)成一些小的问题然后递归求解,而(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)

public static void mergeSort(int[] arr, int left, int right, int[] temp) {
    if (left < right) {
        int mid = (left + right) / 2;
        mergeSort(arr, left, mid, temp);
        mergeSort(arr, mid + 1, right, temp);
        merge(arr, left, mid, right, temp);
    }
}

public static void merge(int[] arr,int left,int mid,int right,int[] temp){
    int i = left; 
    int j = mid+1;
    int t = 0; 
    while (i<=mid && j<=right){
      if(arr[i]<=arr[j]){
        temp[t] = arr[i];
        t += 1;
        i += 1;
      }else {
        temp[t] = arr[j];
        t += 1;
        j += 1;
      }
    }
    while(i<=mid){//将左边剩余元素填充进temp中
      temp[t] = arr[i];
      t += 1;
      i += 1;
    }
    while(j<=right){//将右序列剩余元素填充进temp中
      temp[t] = arr[j];
      t += 1;
      j += 1;
    }
    t = 0;
    int tempLeft = left;
    while(tempLeft <= right){
      arr[tempLeft] = temp[t];
      t += 1;
      tempLeft += 1;
    }
 }

1.在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

题目链接:力扣

class Solution {
    int count=0;
    public int reversePairs(int[] nums) {
        //逆序对可以使用归并排序时,进行并时,进行统计
        //数组按照从小到大排序
       
        mergeSort(nums,0,nums.length-1);
        return count;

    }
    //temp是用来临时储存数组的
    public void mergeSort(int[] nums,int left,int right){
        int mid = left +(right-left)/2; //这里求的是中间值,不是平均值
        if(left<right){
            mergeSort(nums,left,mid);//分
            mergeSort(nums,mid+1,right);//分
            merge(nums,left,mid,right);//治
        }
        
    }

    //进行合并
    public void merge(int[] nums,int left,int mid,int right){
       int[] temp = new int[right-left+1];
       //i,j表示两个数组的起始位置
       int i = left;
       int j = mid+1;
       int t=0;
       while(i<=mid && j <= right ){
           if(nums[i] > nums[j]){
               count += (mid -i +1);//这里逆序对,i右边的值都是大的
               temp[t++]=nums[j];
               j++;
           }else{
               temp[t++]=nums[i];
               i++;
           }
       }
       //将左边数组填充到temp中
       while(i<=mid){
           temp[t]=nums[i];
           t += 1;
           i +=1;
       }
       //将右边数组填充到temp中
       while(j<=right){
           temp[t]=nums[j];
           t +=1;
           j +=1;
       }

       //将数组拷贝到nums数组中
       t =0;
       int templeft = left;//原来数组的起始位置
       while(templeft<=right){
           nums[templeft] = temp[t];
           t += 1;
           templeft +=1;
       }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值