快速排序:

ACWing785. 快速排序

题目:

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

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

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

输入格式

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

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

输出格式

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

数据范围

1≤n≤100000

输入样例:

5

3 1 2 4 5

输出样例:

1 2 3 4 5

我先给出代码: 

#include

using namespace std;

const int N = 1e6 + 10;

int n;

int q[N];

void quick_sort(int q[], int l, int r)

{

if (l >= r) return;

int i = l - 1, j = r + 1, x = q[l + r >> 1];

while (i < j)

{

do i ++ ; while (q[i] < x);

do j -- ; while (q[j] > x);

if (i < j) swap(q[i], q[j]);

}

quick_sort(q, l, j);

quick_sort(q, j + 1, r);

}

int main()

{

scanf("%d", &n);

for (int i = 0; i < n; i++) scanf("%d", &q[i]);

quick_sort(q, 0, n - 1);

for (int i = 0; i < n; i++) printf("%d ", q[i]);

return 0;

}

做题时需要注意几点:

1. l + r >> 1的意思

 l+r的值右移1位,相当l+r的值除以2取整;另外<<就是左移,相当于乘以2.

2.quick_sort(q, l, j);quick_sort(q, j + 1, r);的含义

说实在的,我理解这句话看了不下20篇文章,因为我本人对C++还不太熟悉,主要是用的C,但最后我在看了一篇博客后茅塞顿开,我简单附一张图解释

 3.快排模板:

void quick_sort(int q[], int l, int r)

{

if(l >= r) return;

int i = l - 1, j = r + 1, x = q[l + r >> 1];

while (i < j)

{

do i++; while (q[i] < x);

do j--; while (q[j] > x);

if (i < j) swap(q[i],q[j]);

}

quick_sort(q, l, j);

quick_sort(q, j + 1, r);

}

 ACWing786.第k个数

题目:

给定一个长度为 n 的整数数列,以及一个整数 k,请用快速选择算法求出数列从小到大排序后的第 k 个数。

输入格式

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

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

输出格式

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

数据范围

1≤n≤100000, 1≤k≤n

输入样例:

5 3

2 4 1 5 3

输出样例:

3

 先给出代码:

#include

using namespace std;

const int N = 1e5 + 10;

int n, k;

int q[N];

int quick_select(int l, int r, int k)

{

if (l >= r) return q[l];

int i = l - 1, j = r + 1, x = q[l + r >> 1];

while (i < j)

{

do i++; while (q[i] < x);

do j--; while (q[j] > x);

if (i < j) swap(q[i], q[j]);

}

int sl = j - l + 1;

if (k <= sl) return quick_select(l, j, k);

return quick_select(j + 1, r, k - sl);

}

int main()

{

scanf("%d %d", &n, &k);

for (int i = 0; i < n; i++) scanf("%d", &q[i]);

cout << quick_select(0, n - 1, k) << endl;

return 0;

}

这一题倒没什么注意的,主要还是用的上一篇文章的快排模板。我简单解释几个点:

1.cin >> n >> k可以代替scanf,但是scanf运行更快

2.cout << ……<< endl表示输出结束

3.利用快排不断切分,递归切分效率更快

归并排序:

ACWing787.归并排序

题目:

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

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

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

输入格式

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

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

输出格式

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

数据范围

1≤n≤100000

输入样例:

5

3 1 2 4 5

输出样例:

1 2 3 4 5

先给出答案:

#include

using namespace std;

const int N = 1e5 + 10;

int n;

int q[N], tmp[N];

void merge_sort(int l, int r, int q[])

{

if (l >= r) return;

int mid = l + r >> 1;

merge_sort(l, mid, q);

merge_sort(mid + 1, r, q);

int i = l, j = mid + 1, k = 0;

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];

}

int main()

{

scanf("%d", &n);

for (int i = 0; i < n; i++) scanf("%d", &q[i]);

merge_sort(0, n - 1, q);

for (int i = 0; i < n; i++) printf("%d ", q[i]);

return 0;

}

这一题熟记模板即可

归并排序模板:

void merge_sort(int l, int r, int q[])

{

if (l >= r) return;

int mid = l + r >> 1;

merge_sort(l, mid, q);

merge_sort(mid + 1, r, q);

int i = l, j = mid + 1, k = 0;

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];

}

 ACWing788.求逆序对的数量

题目:

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

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

输入格式

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

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

输出格式

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

数据范围

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

输入样例:

6

2 3 4 5 6 1

输出样例:

5

 先给代码:

#include

using namespace std;

typedef long long LL;

const int N = 1e5 + 10;

int n;

int q[N], tmp[N];

LL merge_sort(int l, int r)

{

if (l >= r) return 0;

int mid = l + r >> 1;

LL res = merge_sort(l, mid) + merge_sort(mid + 1, r);

int i = l, j = mid + 1, k = 0;

while (i <= mid && j <= r)

{

if (q[i] <= q[j]) tmp[k++] = q[i++];

else

{

tmp[k++] = q[j++];

res += mid - i + 1;

}

}

while (i <= mid) tmp[k++] = q[i++];

while (j <= r) tmp[k++] = q[j++];

for (int i = l, j = 0; i <= r; i++, j++) q[i] = tmp[j];

return res;

}

int main()

{

scanf("%d", &n);

for (int i = 0; i < n; i++) scanf("%d", &q[i]);

cout << merge_sort(0, n - 1) << endl;

return 0;

}

 注意事项:

1.这题逆序对的数量可能远远多于int所包含的数,用typedef long long LL;定义一个long long型函数LL。

而LL res = merge_sort(l, mid) + merge_sort(mid + 1, r);相当于int a,就是定义了一个类型为long long的函数res来存逆序对的个数

(long long 是C语言中的一个整数数据类型,它具有比标准整型 int 更大的整数表示能力。)

2.这一题划分后分三种情况,一是两数同在左边,二是同右,三是一左一右

3.记得返回的值是res

相关文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: