快速排序
【题目描述】
【思路】
- 确定分界点x,x可取 x[l],x[r]或者x[(l+r)/2]
- 根据分界点调整区间,以分界点为轴,左边的都不大于x,右边的都不小于x。
- 递归处理
模板
public static void quick_sort(int l, int r, int q[]){
//区间为空时返回
if( l > r) return;
int j = partition(l, r, q);
//3、递归处理 划分为[l,j-1]和[j+1,r]两个区间
quick_sort(l, j - 1 , q);
quick_sort(j + 1, r, q);
}
//返回分界点元素应该放置的位置
public static int partition(int l, int r, int q[]){
//1、确定分界点x
int i = l, j = r, x = q[l];
//2、根据分界点调整区间
while( i < j){
while( i < j && q[j] >= x) j --;
while( i < j && q[i] <= x) i ++;
if( i < j){//交换
int tmp = q[i];
q[i] = q[j];
q[j] = tmp;
}
}
//i指针的位置即为分界点元素应该放置的位置
a[l] = a[i];
a[i] = x;
return i;
}
第k个数
【题目描述】
【思路】
应用快排思想
/**
* l 区间左端点
* r 区间右端点
* k [l,r]区间第k小
*/
public static int selectK(int l, int r, int q[], int k){
if( l == r) return q[l];
int i = partition(l, r, q);
int j = i - l + 1; //j为q[i]元素在新划定区间[l,r]的排名
if( j >= k) return selectK(l, i, q, k);
else return selectK(i + 1 , r, q, k - j);
}
public static int partition(int l, int r, int []q){
int i = l, j = r, x = q[l];
while( i < j){
while( i < j && q[j] >= x ) j--;
while( i < j && q[i] <= x ) i++;
if( i < j){
int tmp = q[i];
q[i] = q[j];
q[j] = tmp;
}
}
q[l] = q[i];
q[i] = x;
return i;
}
归并排序
【题目描述】
【思路】
1 、确定分界下标,mid = (l+r)/2
2、递归求解子问题
3、 合并子问题
public static void mergeSort(int l, int r , int [] q){
//一个元素时自然有序
if( l >= r ) return;
int mid = l + r >> 1;
mergeSort(l, mid, q); //[l, mid]
mergeSort(mid + 1, r, q); //[mid + 1, r]
//合并有序区间
merge(l, mid, r, q);
}
public static void merge(int l, int mid, int r, int [] q){
int i = l, j = mid + 1, k = 0;
//辅助数组
int b[] = new int[ r - l + 1];
while( i <= mid && j <= r){
while( i <= mid && q[i] <= q[j] ) b[k++] = q[i++];
while( j <= r && q[j] <q[i] ) b[k++] = q[j++];
}
while( i <= mid ) b[k++] = q[i++];
while( j <= r ) b[k++] = q[j++];
for(int p = l,m = 0; p <= r; p ++, m ++) q[p] = b[m];
}
逆序对的数量
【题目描述】
【思路】
归并排序思想
import java.io.*;
public class Main{
static int N = 100010;
static int q[] =new int[N];
static long cnt ;
public static void mergeSort(int l, int r, int []q){
if( l >= r) return;
int mid = (l+r)>>1;
mergeSort(l, mid, q);
mergeSort(mid + 1, r, q);
merge(l, mid, r, q);
}
public static void merge(int l, int mid, int r, int []q){
int i = l, j = mid + 1, k = 0;
int b [] = new int[ r - l + 1];
while( i <= mid && j <= r){
while( i <= mid && q[i] <= q[j]) b[k++] = q[i++];
//前大后小即为逆序对
while( j <= r && q[i] > q[j] ) {
b[k++] = q[j++];
cnt += mid - i + 1;
}
}
while( i <= mid) b[k++] = q[i++];
while( j <= r) b[k++] =q[j++];
for(int t = 0; l <= r; l++, t++) q[l] = b[t];
}
public static void main(String args[]) throws Exception{
BufferedReader bf =new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(bf.readLine());
String strArr [] = bf.readLine().split(" ");
for(int i = 0; i < n; i++) q[i] = Integer.parseInt(strArr[i]);
mergeSort(0, n-1, q);
System.out.println(cnt);
}
}
Java中排序结构的定义
// 快速排序
import java.util.Scanner;
import java.util.Arrays;
class Cmp implements Comparable<Cmp>{
int num, sum;
public Cmp(int n, int s){
num = n;
sum = s;
}
public int compareTo(Cmp o){
if(this.sum == o.sum){
return Integer.compare(this.num, o.num);
}
return Integer.compare(this.sum, o.sum);
}
}
class Main{
static int N = 1000010;
static Cmp f[] = new Cmp[N];
public static void main(String args[]){
Scanner reader = new Scanner(System.in);
int n = reader.nextInt(), m = reader.nextInt();
// 数位分解
for(int i = 1; i <= n; i ++){
int x = i, res = 0;
while(x > 0){
res += x % 10;
x /= 10;
}
f[i] = new Cmp(i, res);
}
// 返回值为int类型,大于0表示正序,小于0表示逆序
Arrays.sort(f, 1, n + 1);
System.out.println(f[m].num);
}
}
差分
4655. 重新排序
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static int N = 100010;
static long[] arr = new long[N];
static long[] cnt = new long[N];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for (int i = 1; i <= n; ++i) {
arr[i] = sc.nextLong();
}
int m = sc.nextInt();
while (m-- > 0) {
int l = sc.nextInt();
int r = sc.nextInt();
// 构造一维差分数组
cnt[l]++;
cnt[r + 1]--;
}
// 差分数组恢复为统计次数
for (int i = 1; i <= n; ++i) {
cnt[i] += cnt[i - 1];
}
// 排序前数组的和
long sumA = 0;
for (int i = 1; i <= n; ++i) {
sumA += cnt[i] * arr[i];
}
long sumB = 0;
Arrays.sort(arr, 1, n + 1);
Arrays.sort(cnt, 1, n + 1);
// 排序后数组的和
for (int i = 1; i <= n; ++i) {
sumB += cnt[i] * arr[i];
}
System.out.println(sumB - sumA);
}
}
多路归并
1262. 鱼塘钓鱼
import java.util.Scanner;
import java.util.PriorityQueue;
class Main{
static int N = 110;
static int []f = new int[N], df = new int[N], mt = new int[N];
public static void main(String agrs[]){
Scanner reader = new Scanner(System.in);
int n = reader.nextInt();
for(int i = 1; i <= n; i ++){
f[i] = reader.nextInt();
}
for(int i = 1; i <= n; i ++){
df[i] = reader.nextInt();
}
for(int i = 1; i < n; i ++){
mt[i] = reader.nextInt();
}
int T = reader.nextInt();
int ans = 0;
// 优先队列维护一个大根堆
PriorityQueue<Integer> pd = new PriorityQueue<>((o1, o2)->o2 - o1);
for(int i = 1; i <= n; i ++){ // 枚举最远能到到的鱼塘
int t = T, res = 0;
for(int j = 0; j < i; j ++){ // 减去转移的时间,得到完全用于钓鱼的时间
t -= mt[j];
}
for(int j = 1; j <= i; j ++){
for(int k = f[j]; k > 0; k -= df[j]){
pd.add(k);
}
}
// 获取不超过t个的前几个数
while(t > 0&& !pd.isEmpty()){
res += pd.poll();
t --;
}
ans = Math.max(res, ans);
// 新的一轮比较
pd.clear();
}
System.out.println(ans);
}
}
4656. 技能升级
朴素做法
每个技能构成一个等差数列,对所有的等差数列进行排序选择前m大的数即可。
只能过一半的数据。
/*
A较大 B较小
A 10 9 8
B -5 -2 -1
cnt 2 5 8
1 10
5 9 8
2 9
5 7 8
3 8
5 7 7
4 7
5 7 6
5 7
5 5 6
6 6
5 5 5
10 + 9 + 8 + 7 + 7 + 6
10 5 0
9 7 5 3 1 0
8 7 6 5 4 3 2 1
A - B*t
*/
import java.util.Scanner;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Collections;
class Main{
static int N = 100010;
static int C = 10000010;
static int []A = new int[N];
static int []B = new int[N];
static Integer []s = new Integer[C];
public static void main(String agrs[]){
Scanner reader = new Scanner(System.in);
long n = reader.nextLong(), m = reader.nextLong();
for(int i = 1; i <= n; i ++){
A[i] = reader.nextInt();
B[i] = reader.nextInt();
}
int p = 0;
for(int i = 1; i <= n; i ++){
int j = A[i];
for(; j> B[i]; j -= B[i]){
s[++p] = j;
}
if(j > 0){
s[++p] = j;
}
}
// for(int i = 1; i <= p; i ++){
// System.out.print(s[i] + " ");
// }
// System.out.println(p);
// Arrays.sort(s, 1, p + 1, Collections.reverseOrder());
// // 使用自定义比较器对象进行降序排序
Arrays.sort(s, 1, p + 1, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1); // 降序排序
}
});
long ans = 0;
for(int i = 1; i <= m; i ++){
ans += s[i];
}
System.out.println(ans);
}
}