导图社区 快速排序与归并排序
快速排序与归并排序、合并有序数列、逆序对、第K小数等详细内容,介绍详细,描述全面,希望对感兴趣的小伙伴有所帮助!
编辑于2025-01-16 13:25:32快速排序与归并排序
3.合并有序数列
题目:输入两个有序的数列,将它们合并成一个有序的数列。
输入输出描述: 输入: 第一行两个整数nn和mm,表示两个数列的长度 第二行nn个数,表示第一个数列中的数。 第二行mm个数,表示第二个数列中的数。 输出: 输出合并后的结果。
样例: 输入: 4 4 1 3 4 5 2 3 3 7 输出: 1 2 3 3 3 4 5 7
思路:当两个序列非空时,使用while循环。最后可以直接在void函数里输出。
代码演示: #include <bits/stdc++.h> using namespace std; const int N = 100010; int a[N],b[N],c[2*N]; void merge(int a[],int n,int b[],int m) { //合并函数 int i = 0,j = 0,tot = 0; while (i < n && j < m) { if (a[i] < b[j]) { c[tot++] = a[i]; i++; } else { c[tot++] = b[j]; j++; } } while (i < n) c[tot++] = a[i++]; //重新赋值 while (j < m) c[tot++] = b[j++]; for (int i = 0;i < tot;i++) printf("%d ",c[i]); //在void函数里输出 } int main() { int n,m; scanf("%d%d",&n,&m); for (int i = 0;i < n;i++) scanf("%d",&a[i]); for (int j = 0;j < m;j++) scanf("%d",&b[j]); merge(a,n,b,m); return 0; }
4.逆序对
题目:
输入输出描述:
样例:
思路:
代码演示:
2.第K小数
题目:给定一个长度为n的数组,输出从小到大的第K个数。
输入输出描述: 输入: 第一行两个整数n和K,表示数组的长度。 第二行n个元素,表示数组中的数。 输出: 从小到大的第K个数
样例: 输入: 5 3 2 2 5 4 1 输出: 4
思路:和第一题差不多,快速排序之后直接输出低K项。
代码演示: #include <bits/stdc++.h> using namespace std; const int N = 1000010; int a[N],b[N]; void merge(int l,int r) { if (l == r) return ; int mid = (l + r) / 2; merge(l,mid); merge(mid + 1,r); int i = l,j = mid + 1,tot = l; while (i <= mid && j <= r) { if (a[i] < a[j]) { b[tot++] = a[i]; i++; } else { b[tot++] = a[j]; j++; } } while (i <= mid) b[tot++] = a[i++]; while (j <= r) b[tot++] = a[j++]; for (int i = l;i <= r;i++) a[i] = b[i]; } //和第一题一样的 快速排序 int main() { int n,k; scanf("%d%d",&n,&k); for (int i = 1;i <= n;i++) scanf("%d",&a[i]); merge(1,n); printf("%d",b[k]); //直接输出第K项 return 0; }
1.快速排序
题目:给定一个长度为n的排列A,逆序的定义:(i,j)为逆序对,当i<j && A[i]>A[j] 求排列A的逆序对数量。
输入输出描述: 输入:第一行一个整数n,表示排列的长度第二行n个元素,表示A排列 输出:输出逆序对的数量
样例: 输入: 5 3 2 4 1 5 输出: 4
思路:快速排序就是要快速,所以这里使用了二分的思想。
代码演示: #include <bits/stdc++.h> using namespace std; const int N = 100010; int a[N],b[N]; long long ret = 0; void merge(int l,int r) { //排序时使用了二分的思想 if (l == r) return ; //头和尾一样 int mid = (l + r) / 2; //中间 merge(l,mid); //遍历左边 merge(mid + 1,r); //遍历右边 int i = l,j = mid + 1,tot = l; while (i <= mid && j <= r) { //二分 if (a[i] < a[j]) { b[tot++] = a[i]; i++; } else { ret += mid - i + 1; b[tot++] = a[j]; j++; } } while (i <= mid) b[tot++] = a[i++]; //重新赋值 while (j <= r) b[tot++] = a[j++]; for (int i = l;i <= r;i++) a[i] = b[i]; } int main() { int n; scanf("%d",&n); for (int i = 1;i <= n;i++) scanf("%d",&a[i]); merge(1,n); printf("%lld",ret); //注意是long long类型 return 0; }