洛谷P1177题解

题目传送门

这个题目是一个排序的模板题,可以使用O(n)O(nlog_{n})的算法通过,我这里讲三种方法(sort,归并和桶)。

sort:

没啥好讲的,直接调用就行了。

桶排序:

思路:

用普通的数组做桶肯定会爆,但是别忘了,c++里有一个叫STL的东西,而STL里又有一个叫map的东西,而map有非常适合做桶,map在第一次使用一个下标的时候才会生成这个下标对应的数,而且默认为零,这样,就不用担心会爆的问题啦。

代码:

要开c++11呦,否则会报错······

#include<iostream>
#include<map>
using namespace std;
map<int,int> a;
int n;
int main() {
    cin>>n;
    int lin=0;
    for(int i=1;i<=n;i++){
        cin>>lin;
        a[lin]++;
    }for(auto i=a.begin();i!=a.end();i++){
        if(i->second!=0){
            for(auto j=1;j<=i->second;j++){
                cout<<i->first<<" ";
            }
        }
    }
    return 0;
}

归并排序:

 归并排序是个啥?

(以下这段话由AI小助手生成)

归并排序是一种分治法,它的基本思想是将一个大数组分割成两个较小的子数组,然后递归地对每个子数组进行排序,最后再将这两个有序子数组合并为一个有序的大数组。归并排序的优点是稳定性好、时间复杂度低,但空间复杂度较高。

归并排序的步骤:

(以下这段话由AI小助手生成)

  1. 将待排序的数组分割成两个较小的子数组,其中一个包含元素a[0...n/2],另一个包含元素a[n/2+1...n]。

  2. 递归地对每个子数组进行排序,其中排序的方法是使用归并排序的思想:将子数组分割成更小的子数组,直到每个子数组只包含一个元素为止;然后再将这些子数组合并起来,形成一个新的有序数组。

  3. 最后将两个已排序的子数组合并为一个有序的大数组。这个过程是通过比较两个子数组中的元素大小,然后选择其中较小的一个元素添加到新的大数组中,重复此过程,直到所有的元素都被添加到新的大数组中。

     (后面的话都是我自己说的)

        前两部都很好理解,我来说说第三步。我们已经分成了两个长度相等或接近的有序的子序列,我们可以用两个变量表示两个子序列的第一个元素,之后进行比较,将小的放到新的数组里,这个变量++,以此类推,直到有一个放完,最后,在用while循环来处理剩下的数,最后再用for循环导到原来的数组里。

代码:

#include<iostream>
using namespace std;
int yuan[114514],xin[114514];
void merge_fix(int l,int r){
	int mid=(l+r)/2;
	int ll=l,lr=mid,rl=mid+1,rr=r;
	int cnt=l-1;
	while(ll<=lr&&rl<=rr){
		if(yuan[ll]<yuan[rl]){
			xin[++cnt]=yuan[ll++];
		}else{
			xin[++cnt]=yuan[rl++];
		}
	}while(rl<=rr)xin[++cnt]=yuan[rl++];
	while(ll<=lr)xin[++cnt]=yuan[ll++];
	for(int i=l;i<=r;i++)yuan[i]=xin[i];
}
void merge_sort(int l,int r){
	if(l>=r)return;
	int mid=(l+r)/2;
	merge_sort(l,mid);
	merge_sort(mid+1,r);
	merge_fix(l,r);
	return;
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>yuan[i];
	}merge_sort(1,n);
	for(int i=1;i<=n;i++){
		cout<<yuan[i]<<" ";
	}
	return 0;
}

AC记录 

彩蛋:

点个关注,点这里 查看彩蛋!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值