PAT-1045-快速排序(25)-源码+思路

emmm,讲道理其实这道题感觉还是蛮简单的,但是通过率只有0.17着实把老身吓了一跳


感谢井同学的提醒,说什么没有主元元素的时候输出还要空一行,估计很多人就卡在这里了...(出题人牛逼 微笑

附上井同学的连接https://blog.csdn.net/jyfbug/article/details/80044006

哦,突然发现一个bug,好像不用快速排序的,因为主元就是排好顺序的,感谢井同学的提醒,阿里嘎多~

其实这道题目思路还是很清晰的,嗯嗯,接下来是本戏精的show time

-----------------------------------------啦啦啦,我是题目的分割线-----------------------------------------

题目:著名的快速排序算法里有一个经典的划分过程:我们通常采用某种方法取一个元素作为主元,通过交换,把比主元小的元素放到它的左边,比主元大的元素放到它的右边。给定划分后的N个互不相同的正整数的排列,请问有多少个元素可能是划分前选取的主元?

例如给定N = 5, 排列是1、3、2、4、5。则:

1的左边没有元素,右边的元素都比它大,所以它可能是主元;
尽管3的左边元素都比它小,但是它右边的2它小,所以它不能是主元;
尽管2的右边元素都比它大,但其左边的3比它大,所以它不能是主元;
类似原因,4和5都可能是主元。

因此,有3个元素可能是主元。

输入格式:

输入在第1行中给出一个正整数N(<= 105);第2行是空格分隔的N个不同的正整数,每个数不超过109

输出格式:

在第1行中输出有可能是主元的元素个数;在第2行中按递增顺序输出这些元素,其间以1个空格分隔,行末不得有多余空格。

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

---------------------------------------啦啦啦,我是思路的分割线-------------------------------------------

思路:emmm,最主要就分成四步吧,首先输入到num数组,然后找主元,整理排序,最后输出...是不是太简单了

ou,因为找主元最主要的思路就是遍历所有元素,分别与该元素左边最小的值,和该元素右边最大的值进行比较


可以看出,当前元素比左侧最大值小,所以它不是主元,主元的要求是:比左侧最大值要大,比右侧最小值要小;

并且最好时间复杂度要降到最低,就是说最好是一次循环就够了;

那么左侧最大值可以根据当前元素遍历的时候更改,但是右侧最小值不可以呀,因为就算你第一次找到了右侧最小值,当当前元素移动到右侧最小值右侧的时候,右侧最小值是要改变的,就变成了右侧第二小的值,那么怎么办呢,嗯,其实可以用一个数组存储右侧最小值:

我们在找主元这次遍历之前从右侧开始遍历数组num,设置right_min数组第一个元素为1000000000(这是题目的数值限制),然后从右往左遍历num数组,如果num数组中的元素比right_min数组前一个元素要小,就插入到right_min数组中;

整理之后得到right_min数组为(num中第一个数据不参与比较


当right_min数组建立完毕后,我们就可以开始比较啦~

要注意,right_min数组是从右往左比较的,如果num当前元素的下一个元素==right_min数组中的值,那么right_min数组往左挪一个(为什么当前元素不可能等于right_min数组中的值呢?因为num中第一个数据不参与比较,所以右侧最小值永远不可能等于当前元素的值)

嗯,可能我讲得不是很清楚,那就献上代码~~~

-----------------------------------------啦啦啦,我是代码的分割线--------------------------------------------

代码:

#include<stdio.h>
#include<stdlib.h>

int main()
{
    int N;
    int num[100000];
    int left_max=0;//记录左侧最大值
    int right_min[100000];//记录右侧最小值
    int right_count=0;//记录右侧最小值的位置

    scanf("%d",&N);
    int i=0;
    for(i;i<N;i++)
    {
        scanf("%d",&num[i]);
    }
    
    /*从num数组右侧开始找
    如果比前一个right_min小
    就插入right_min数组
    
    在遍历num数组的时候
    如果num数组中的数不等于right_min中的数
    那么right_min当前的数一定是右侧最小的数*/
    right_min[right_count]=1000000000;//每个数不超过10的9次方
    right_count++;
    for(i=N-1;i>0;i--)
    {
        //num[0]不记录进去
        if(num[i]<right_min[right_count-1])
        {
            right_min[right_count]=num[i];
            right_count++;
        }
    }

    //遍历num数组,找出主元
    int main_ele[100000];
    int main_count=0;
    int temp=right_count-1;
    for(i=0;i<N;i++)
    {
        if(num[i]>left_max&&num[i]<right_min[temp])
        {
            //整数各不相同
            left_max=num[i];
            main_ele[main_count]=num[i];
            main_count++;
        }
        else if(num[i]>left_max)
        {
            left_max=num[i];
        }
        if(num[i+1]==right_min[temp])
        {
            /*因为永远是跟当前num右侧数的最小值进行比较
            所以是num[i+1]*/
            if(temp!=0)temp--;
        }
    }

    printf("%d\n",main_count);
    for(i=0;i<main_count-1;i++) printf("%d ",main_ele[i]);
    //如果没有主元元素就输出一个空行,不要问我为什么这样QAQ
    if(main_count==0)printf("\n");
    else printf("%d",main_ele[i]);

    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
随着人口老龄化和空巢化等社会问题的日益严峻,养老问题及以及养老方式的变革成为了当前社会的发展焦点,传统的养老模式以救助型和独立型为主,社会养老的服务质量与老年人的养老需求还存在一定的差距,人们生活水平的提高以及养老多元化需求的增加都需要通过创新和灵活开放的养老模式来应对未来的养老需求,结合目前我国养老模式及养老服务问题的内容的分析,互助养老模式作为一种新型的养老模式结合自主互助的集体养老理念,帮助老年人实现了满足个性需求的养老方案,互助养老模式让老年人具备了双重角色的同时也实现可持续的发展特色。目前我国老年人的占比以每年5%的速度在飞速增长,养老问题及养老服务的提供已经无法满足当前社会养老的切实需求,在养老服务质量和养老产品的变革过程中需要集合多元化的养老模式来满足更多老人的养老需求。 鉴于我国目前人口老龄化的现状以及迅速扩张的养老服务需求,现有的养老模式已经无法应对和满足社会发展的需求,快速增长的养老人员以及养老服务供给不足造成了紧张的社会关系,本文结合当前养老服务的发展需求,利用SSM框架以及JSP技术开发设计一款正对在线互助养老的系统,通过系统平台实现养老机构信息的传递及线上预约,搭建了起了用户、养老机构以及系统管理员的三方数据平台,借助网页端实现在线的养老互助信息查询、养老机构在线预约以及求助需求等功能,通过自养互养的养老模式来帮助老年人重新发现自我价值以及丰富养老的主观能动性。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值