【Java】浅谈排序

快速排序

思路及其作用

快排就是在数列中随便选择一个数, 经过操作让左面的数小于这个数, 右面的数大于这个数时间复杂度(在一般情况下是O(nlogn), 在特殊情况下为O(n^2)。快排的作用是排序,而Java中Arrays.sort而也是排序,且复杂度稳定为nlogn,那应该在什么情况下使用?快排的特点就是让我们可以有操作内部的空间,从而利用其部分规律的特点用更少的复杂度完成题目,列如:第k个数

acwing785快速排序

给定你一个长度为 n的整数数列。

请你使用快速排序对这个数列按照从小到大进行排序。

并将排好序的数列按顺序输出。

输入格式

输入共两行,第一行包含整数 n。

第二行包含 n个整数(所有整数均在 1∼1091∼109 范围内),表示整个数列。

输出格式

输出共一行,包含 n 个整数,表示排好序的数列。

数据范围

1≤n≤100000

输入样例:
5
3 1 2 4 5
输出样例:
1 2 3 4 5
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String[] s1 = in.readLine().split(" ");
        int n = Integer.parseInt(s1[0]);
        int[] q = new int[n];
        String[] s2 = in.readLine().split(" ");
        for(int i = 0; i < n; i ++) q[i] = Integer.parseInt(s2[i]);
        quickSort(q, 0, n - 1);
        for(int i = 0; i < n; i ++) System.out.print(q[i] + " ");
    }
    public static void quickSort(int[] q, int l, int r){
        if(l >= r) return;
        int x = q[l + r >> 1], i = l - 1, j = r + 1;
        while(i < j){
            while( q[++i] < x );
            while( q[--j] > x) ;
            if(i < j){
                int t = q[i];
                q[i] = q[j];
                q[j] = t;
            }
        }
        quickSort(q, l, j);
        quickSort(q, j + 1, r);
    }
}
[acwing786第k个数](786. 第k个数 - AcWing题库)
输入格式

第一行包含两个整数 n 和 k。

第二行包含 n个整数(所有整数均在 1∼10^9 范围内),表示整数数列。

输出格式

输出一个整数,表示数列的第 k 小数。

数据范围

1≤n≤100000
1≤k≤n

输入样例:
5 3
2 4 1 5 3
输出样例:
3
import java.io.*;
public class Main {

    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        String[] strings = reader.readLine().split(" ");
        int n = Integer.parseInt(strings[0]);
        int k = Integer.parseInt(strings[1]);
        int q[] = new int[n];
        String[] str = reader.readLine().split(" ");
        for (int i = 0; i < str.length; i++)  q[i] = Integer.parseInt(str[i]);
        System.out.print(quickSort(q, 0, n - 1, k));
    }

    public static int quickSort(int q[], int l, int r, int k) {
        //边界条件
        if (l >= r)
            return q[l];
        int i = l - 1, j = r + 1, x = q[l + r >> 1];
        //按照快排规则将数组分为两部分,左边的数全部小于x,右边的数全部大于x,
        while (i < j) {
            while (q[++i] < x);
            while (q[--j] > x);
            if (i < j) {
                int t = q[i];
                q[i] = q[j];
                q[j] = t;
            }
        }
        //sl为左边的长度
        int sl = j - l + 1;
        //第k小的数在左边,继续在左边找第k小的数
        if (sl >= k)
            return quickSort(q, l, j, k);
        //第k小的数在右边,则在右边找第 k-sl的数
        return quickSort(q, j + 1, r, k - sl);
    }
}
//时间复杂度:1/2n+1/3n+1/4n... = O(n)

归并排序

思路及其作用

与快排类似, 不过快排是先操作再递归,而归并则是先递归到不能递归(递归到两个数或一个数停下),然后在回溯中操作使其有序。作用当然也是可以对过程进行操作。列如:逆序对的数量。

这里逆序对分为三种情况:

1.一个在左面,一个在右面

2.两个都在左面

3.两个都在右面

直接可以使用归并,将2,3类情况直接递归成1这种情况(也就是只剩下两个数),然后回溯处理2, 3;并加在一,就可以得出答案

787. 归并排序 - AcWing题库

给定你一个长度为 n 的整数数列。

请你使用归并排序对这个数列按照从小到大进行排序。

并将排好序的数列按顺序输出。

输入格式

输入共两行,第一行包含整数 n。

第二行包含 n个整数(所有整数均在 1∼10^9 范围内),表示整个数列。

输出格式

输出共一行,包含 n个整数,表示排好序的数列。

数据范围

1≤n≤100000

输入样例:
5
3 1 2 4 5
输出样例:
1 2 3 4 5
import java.io.*;
import java.util.*;

public class Main {
    static int N=100010;
    static int[] q=new int[N];
    static int[] tmp = new int[N];
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String[] s1 = in.readLine().split(" ");
        int n = Integer.parseInt(s1[0]);
        String[] s2 = in.readLine().split(" ");
        for(int i = 0; i < n; i ++) q[i] = Integer.parseInt(s2[i]);
        mergeSort(q, 0, n - 1);
        for(int i = 0; i < n; i ++) System.out.print(q[i] + " ");
    }
    public static void mergeSort(int[] q, int l, int r){
        if (l >= r) return;
        int mid = l + r >> 1;
        mergeSort(q, l, mid);
        mergeSort(q, mid + 1, r);
        int k = 0, i = l, j = mid + 1;
        while (i <= mid && j <= r)
            if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
            else tmp[k ++ ] = q[j ++ ];
        while (i <= mid) tmp[k ++ ] = q[i ++ ];
        while (j <= r) tmp[k ++ ] = q[j ++ ];
    
        for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
    }
}
788. 逆序对的数量 - AcWing题库

给定一个长度为 n 的整数数列,请你计算数列中的逆序对的数量。

逆序对的定义如下:对于数列的第 i 个和第 j 个元素,如果满足 i<j且 a[i]>a[j],则其为一个逆序对;否则不是。

输入格式

第一行包含整数 n,表示数列的长度。

第二行包含 n 个整数,表示整个数列。

输出格式

输出一个整数,表示逆序对的个数。

数据范围

1≤n≤100000
数列中的元素的取值范围 [1,10^9]

输入样例:
6
2 3 4 5 6 1
输出样例:
5
import java.io.*;
import java.util.*;

public class Main {
    static int N=100010;
    static int[] q=new int[N];
    static int[] tmp = new int[N];
    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String[] s1 = in.readLine().split(" ");
        int n = Integer.parseInt(s1[0]);
        String[] s2 = in.readLine().split(" ");
        for(int i = 0; i < n; i ++) q[i] = Integer.parseInt(s2[i]);
        System.out.print(mergeSort(q, 0, n - 1));
    }
 public static long mergeSort(int[] a, int l, int r) {
        if (l >= r) return 0;
        int mid = l + r >> 1;
        long res = mergeSort(a, l, mid) + mergeSort(a, mid + 1, r);
        int tmp[] = new int[r-l+1];
        int k = 0, i = l, j = mid + 1;
        while (i <= mid && j <= r) {
            if (a[i] <= a[j]) tmp[k++] = a[i++];
            else {
                res += mid - i + 1;
                tmp[k++] = a[j++];
            }
        }
        while (i <= mid) tmp[k++] = a[i++];
        while (j <= r) tmp[k++] = a[j++];
        for(i = l,j = 0;i <= r;i ++,j ++)a[i] = tmp[j];
        return res;
    }
}

最后:

刚学Java的菜鸡(语法都没学完),以上皆为本人理解,如有错误,还请指正

参考:acwing算法基础课

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值