快速排序
思路及其作用
快排就是在数列中随便选择一个数, 经过操作让左面的数小于这个数, 右面的数大于这个数时间复杂度(在一般情况下是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算法基础课