基础算法1

1.快速排序

(此处步骤是一个大佬的)

1.i =L; j = R; 将基准数挖出形成第一个坑a[i]。

2.j–由后向前找比它小的数,找到后挖出此数填前一个坑a[i]中。

3.i++由前向后找比它大的数,找到后也挖出此数填到前一个坑a[j]中。

4.再重复执行2,3二步,直到i==j,将基准数填入a[i]中。
————————————————
原文链接:https://blog.csdn.net/code_AC/article/details/74158681

#include<iostream>
using namespace std;

const int N=1e6+10;

int n;
int a[N];

void qs(int a[],int l,int r)  //
{
	
	if(l>=r) return;
	
	int x=a[l],i=l-1,j=r+1;   //i,j需要各自先往两边偏移1
	while(i<j)
	{
		do(i++) ;while(a[i]<x);
		do(j--) ;while(a[j]>x);
		if(i<j) swap(a[i],a[j]);  //
	}
	
	qs(a,l,j);
	qs(a,j+1,r);
	
}

int main()
{
	scanf("%d",&n);

	 for(int i=0;i<n;i++) scanf("%d",&a[i]);
	 
	qs(a,0,n-1);
	
	for(int i=0;i<n;i++) printf("%d",a[i]);

	return 0;
 } 
 
 

例题:ACWing 1591. 快速排序

在著名的快速排序中,有一个经典的过程叫做划分。

在此过程中,我们通常选取其中一个元素作为分界值。

将小于分界值的元素移到其左侧,将大于分界值的元素移到其右侧。

给定 NN 个不同的正整数进行过一次划分后的排列情况。

请你判断,共有多少元素可能是此次划分的分界值。

例如,N=5N=5,各元素排列为 1,3,2,4,51,3,2,4,5,则:

  • 11 可能是分界值,因为它的左侧没有元素,而右侧的元素都比它大。
  • 33 一定不是分界值,因为尽管它的左侧的元素都比它小,但是它右侧的 22 也小于它。
  • 22 一定不是分界值,因为尽管它的右侧的元素都比它大,但是它左侧的 33 也大于它。
  • 出于类似判断可知 4,54,5 也可能是分界值。

因此,在此样例中,共有 33 个可能的分界值。

输入格式

第一行包含整数 NN。

第二行包含 NN 个不同的正整数。

输出格式

第一行输出可能的分界值数量。

第二行按升序顺序输出所有可能的分界值。

如果分界值数量为 00,则在输出分界值数量后,输出一个空行即可。

数据范围

1≤N≤10^5,
1≤1≤ 给定元素 ≤10^9。

输入样例:

5
1 3 2 4 5

输出样例:

3
1 4 5
难度:简单
时/空限制:0.2s / 64MB
总通过数:537
总尝试数:2090
来源:PAT甲级真题1101
算法标签
#include<bits/stdc++.h>
using namespace std;

const int N = 1e5+20;
const int INF = 1e9+10;
int a[N], leftMax[N], rightMin[N];
int b[N], s;//记录主元 num是主元个数

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

    leftMax[0] = 0;
    for (int i = 1; i < n; i ++ ) leftMax[i] = max(leftMax[i - 1], a[i - 1]);

    rightMin[n - 1] = INF;
    for(int i = n - 2; i >= 0; i -- ) rightMin [i] = min(rightMin[i + 1], a[i + 1]);

    for(int i = 0; i < n; i ++ )
    {
        if(leftMax[i] < a[i] && rightMin[i] > a[i]) 
            b[s++] = a[i];//记录主元
    }

    printf("%d\n", s);

    for(int i = 0; i < s; i ++ )
    {
        printf("%d", b[i]);
        if(i < s - 1) printf(" ");
    }

    printf("\n");

    return 0;
}

2.归并排序

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+10;
int a[N],tmp[N];

void ms(int a[],int l,int r)
{
	if(l>=r) return;
	int x=(l+r)/2;
	
	ms(a,l,x);
	ms(a,x+1,r);
	
	int k=0,i=l,j=x+1;
	while(i<=x&&j<=r)
	{
		if(a[i]<=a[j]) tmp[k++]=a[i++];
		else tmp[k++]=a[j++];
	}
	while(i<=x) tmp[k++]=a[i++];
	while(j<=r) tmp[k++]=a[j++];
	
	for(int k=l,q=0;k<=r;k++,q++)
	a[k]=tmp[q];
	
}

int main()
{
	int n;
	scanf("%d",&n);
	
	for(int i=0;i<n;i++) scanf("%d",&a[i]);
	
	ms(a,0,n-1);
	
	for(int i=0;i<n;i++)  printf("%d ",a[i]);
	
	return 0;
}

例题:ACWing 逆序对的数量

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

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

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

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

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

数据范围
1 <= n <= 100000

输入样例:
6
2 3 4 5 6 1
1
2
输出样例:
5
1

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+10;
int a[N],tmp[N];
int s=0;

int ms(int a[],int l,int r)
{
	if(l>=r) return 0;
	int x=(l+r)/2;
	ms(a,l,x);
	ms(a,x+1,r);
	
	int i=l,j=x+1,k=0;
	
	while(i<=x&&j<=r)
	{
		if(a[i]<a[j]) tmp[k++]=a[i++];
		else{
			tmp[k++]=a[j++];
			s=s+x-i+1;          //
		}
	}
	while(i<=x) tmp[k++]=a[i++];
	while(j<=r) tmp[k++]=a[j++];
	
	
	for(int k=l,q=0;k<=r;k++,q++)
	a[k]=tmp[q];
	
	return s;
}

int main()
{
	int n;
	scanf("%d",&n);
	
	for(int i=0;i<n;i++) scanf("%d",&a[i]);
	
	cout<<ms(a,0,n-1);
	
	//for(int i=0;i<n;i++)  printf("%d ",a[i]);
	
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值