pat1030题解注意事项完美数组

pat1030完美数组题解注意事项(c语言题解)以及避坑点


题的地址兄弟们也可以进行尝试一下,如果有什么问题在阅读注意事项和代码后不理解的话可以评论区留言会尽快回复 在这里插入图片描述

https://pintia.cn/problem-sets/994805260223102976/problems/994805291311284224

这一道题的注意事项:

这里先大致讲一下思路:
首先我们应该把这个数组进行排序,第一层循环由前向后走用i来进行指向第二层循环由后向前进行走由q来进行指判断 指针i指向的值乘以p的值和q指向的值进行比较

用的markdown没法给读者们弄一点颜色标记兄弟们下面的这一点真的很重要 有会用markdown设置颜色的小伙伴也可以评论区教我一些Thanks♪(・ω・)ノ

  1. 首先看这个题目给的数组范围为<10^9但是 int的最大储存长度可以粗略的记忆2X10^10(这里那个乘号打不出来,编辑器会把他变为斜体就用X代替乘号了) 两个数相乘的话返回的类型为最大长度的类型,所以下面判断不加 1.0num[i]*p 如果我们把p除过去就会出现小数也得考虑数据类型的问题一定要切记 (如果不这样干,最后一个测试点过不了) 。

  2. 一定要注意题目中给的为N个数,N(≤10^5) 这是相当恐怖的数字了如果我们用两层循环来解题而不排除其他特殊情况的话最坏的时间复杂度为N^2。这里最好想到的几个简化方法,

    1. 我的第二层循环q何必每次回到N-1我每次就呆在哪里就好了只需要判断下一次向哪里就可以了。
    2. 如果q小于i了当然要进行弹出。
    3. 下一个就是当我们i指向的值如果大于num[n-1]的时候结束就好,因为再向后遍历他的值也绝对不会比她大了。
  3. 在进行循环的时候如果用N作为N判断循环结束的条件的时候一定要进行注意,循环结束后变量会等于N 会领数组越界,如果直接在pat网站上去编译,他也不会给你任何警告。

  4. 负数完美数组中不可能有负数,因为一旦有负数负数一定为最小值,而p一定大于0,会越乘越小可以在排序后用一个计数器把负数排除

代码

排序:在代码开始前我需要讲解一些qsort函数的使用在我们写算法题的时候可以快速进行排序,锻炼我们的代码实现,没必要花大量的时间在排序这一方面,考试比赛的时候我们等不起

qsort:quick sort 快速排序 包含在头文件c库 #include<stdlib.h>中 首先介绍他的4个参数

qsort(指针(数组名),数组有多少个元素,数组中元素类型所占的字节大小sizeof(type),函数指针如果不会可以理解为一个函数的名字入 compare)
int compare(const void*a,const void* b)//函数名可以边更改,但是函数里面参数type类型一定不要该
{
    int*c=(int*)a;
    int*d=(int*)b;
    return *c-*d;//这样为正序反过来为倒序
}

第一个输入测试用例:

10 8
2 3 20 4 5 1 6 7 8 9

输出样例:

8
#include<stdio.h>
#include<stdlib.h>
int compare(const void*a,const void* b)
{
    int*c=(int*)a;
    int*d=(int*)b;
    return *c-*d;
}
int main()
{
    int N,p;
    // N p的读入
    scanf("%d %d",&N,&p);
    /*if(N==0)
    {
        //printf("0");
        return 0;
    }*/
    int num[N];
    //数据的读入
    for(int i=0;i<N;i++)
    {
        scanf("%d",&num[i]);
    }
    // 排序
    qsort(num,N,sizeof(int),compare); // 快速排序 c语言的库函数 需要包含头文件 #include<stdlib.h>
    int cnt=0;
    //负数计数器
    /*for(int i=0;i<N;i++)
    {
        if(num[i]<0)
        {
            cnt++;
        }
    }*/ //这里可以判断 -数有多少个,负数肯定无法成为完美数组的数组值因为p 大于0 会越来越小 把下面i=0修改为i=cnt可以更快的速度,当然不用也可以过哦

    if(num[N-1]<0)
    {
        printf("%d",0);
        return 0;
    }
    int index=0;
    int q=N-1;//q一定要定义在循环外面方便重复使用
    int i;
    for(i=0;i<N;i++)
    {
        if(1.0*num[i]*p<=1.0*num[q])
        {
             for(q;q>0;q--)
            {
                 //printf("%d\n",num[q]);
                 if(1.0*num[i]*p>=1.0*num[q])
                {
                     break;
                }
            }
        }else
        {
             for(q;q<N;q++)
            {
                 if(1.0*num[i]*p<1.0*num[q])
                {
                     q=q-1;
                     break;
                }
            }
            if(q==N)//这里一定一定要注意有可能循环机结束后在下一次使用的时候会越界
            {
                q=q-1;
            }
        }
        if(q-i+1>index)
        {
            index=q-i+1;
        }
        if(1.0*num[i]*p>1.0*num[N-1])
        {
            break;
        }
    }
    printf("%d",index);  
    return 0;
}
       if(1.0*num[i]*p>1.0*num[N-1])
        {
            break;
        }
    }
    printf("%d",index);  
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学c的小李

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值