pat刷题笔记1101-1104

第一次完整做完一套pat题目,没有限时,分数分别为25+25+24+15
上学期刚学的算法,然而现在DFS都不会写了确实是没想到,二叉树相关的基础操作还是挺扎实(感谢数据结构的屈老师)
下面附上这几题的代码和简要思路:

第一题就是求左边的数都比他小,同时右边的数都比他大的数的个数,遍历两次数组即可,时间复杂度O(n),两层循环会超时

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    cin>>n;
    int a[n],maxleft[n],minright[n];
    int i,j;
    for(i=0;i<n;i++)
    {
        cin>>a[i];
    }
    vector<int> b;
    maxleft[0]=a[0];
    minright[n-1]=a[n-1];
    for(i=1;i<n;i++)
    {
        maxleft[i]=max(maxleft[i-1],a[i]);
        minright[n-i-1]=min(minright[n-i],a[n-i-1]);
    }
    for(i=0;i<n;i++)
    {
        if(a[i]==maxleft[i]&&a[i]==minright[i])
        {
            b.push_back(a[i]);
        }
    }
    cout<<b.size()<<endl;
    for(i=0;i<b.size();i++)
    {
        if(i!=b.size()-1)cout<<b[i]<<' ';
        else cout<<b[i]<<endl;
    }

}

第二题二叉树的基本操作

mark一下关于stl库中queue容器的pop,front,push操作,分别为出队,取队首元素和入队。

#include<bits/stdc++.h>
using namespace std;
bool flag;
struct node
{
    int n;
    node *lc=NULL;
    node *rc=NULL;
    node *f=NULL;
};

void bianli2(node *p)
{
    if(p==NULL)
        return;
    bianli2(p->lc);
    if(flag!=0)
        cout<<' '<<p->n;
    else{
        cout<<p->n;
        flag=1;
    }
    bianli2(p->rc);
}
int main()
{
    int n;
    cin>>n;
    int i;
    char l,r;
    node tree[n];
    for(i=0; i<n; i++)
    {
        tree[i].n=i;
    }
    for(i=0; i<n; i++)
    {
        cin>>l>>r;
        if(r!='-')
        {
            tree[i].lc=&tree[r-'0'];
            tree[r-'0'].f=&tree[i];
        }
        if(l!='-')
        {
            tree[i].rc=&tree[l-'0'];
            tree[l-'0'].f=&tree[i];
        }
    }
    node *p=&tree[0];
    while(p->f!=NULL)
    {
        p=p->f;
    }
    node *root=p;
    if(n==1)
    {
        cout<<0<<endl;
        cout<<0<<endl;
    }
    if(n==0)
    {
        cout<<endl;
        cout<<endl;
    }
    if(n>1)
    {
        flag=0;
        queue<node*> q;
        q.push(root);
        node *p2;
        while(q.size()!=0)
        {
            p2=q.front();
            q.pop();
            if(flag==0)
            {
              cout<<p2->n;
              flag=1;
            }
            else cout<<' '<<p2->n;
            if(p2->lc!=NULL)
            {
                q.push(p2->lc);
            }
            if(p2->rc!=NULL)
            {
                q.push(p2->rc);
            }
        }
        cout<<endl;
        flag=0;
        bianli2(root);
    }

}

第三题是DFS,有两个测试点超时,扣了六分
本题还有一个坑就是pow(x,y)参数和返回值均为double类型,会存在精度问题(无法精确表示整数)
所以我自己写的幂次函数
后补:
超时的原因是item数组插的元素太多,实际上最大也只需要n-k+1这么大的幂,所以应把for循环条件改为pow(i,p)<n-k+1
测试点2卡住的原因是和相同时未选取字典序更大的解,将nkp函数中
if(k==0)内的result>maxsum改为>=即可,因为我们是按字典序从小到大遍历的!
代码已修改:

#include<bits/stdc++.h>
using namespace std;
vector<int> flag;
vector<int> item;
int maxsum=0;
vector<int> maxflag;
void nkp(int n,int k,int p,int maxt,int result)  //n剩余的值,还有k位,p的值,允许幂次最大值
{
    int i;
    if(n<0) return;
    if(k==0)
    {
        if(result)
        if(n==0)
        {
            if(result>maxsum)
            {
                maxsum=result;
                maxflag=flag;
            }
        }
            return ;
    }
    else
    {
        for(i=0; i<item.size()&&i<maxt+1; i++)
        {
            flag.push_back(i+1);
            nkp(n-item[i],k-1,p,i,result+i+1);
            flag.pop_back();
        }

        return;
    }
}
int p0w(int i,int j)
{
    int k,p=i;
    for(k=1;k<j;k++)
    {
        i=i*p;
    }
    return i;
}
int main()
{
    int n,k,p,i,op=1;
    cin>>n>>k>>p;
    if(n>k){
    for(i=1; p0w(i,p)<n-k+2; i++)
    {
        item.push_back(p0w(i,p));
    }
    }
    else if(n==k)
    {
        item.push_back(1);
    }
    else{
        cout<<"Impossible"<<endl;
        return 0;
    }
    nkp(n,k,p,item.size()-1,0);
    if(maxsum==0)
        cout<<"Impossible"<<endl;
    else
    {

        cout<<n<<" = "<<maxflag[0]<<"^"<<p;
        for(i=1; i<k; i++)
        {
            cout<<" + "<<maxflag[i]<<"^"<<p;
        }
        cout<<endl;
    }


}

第四题巨坑。。思想很简单,每个数的出现次数很容易就可以算出,但是又是double类型!无法精确表示的这些小数,误差累积起来,会导致最后的结果误差

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,i;
    cin>>n;
    double a[n];
    long long b[n];
    long long sum=0;
    for(i=0;i<n;i++)
    {
        cin>>a[i];
         sum+=(long long)((a[i]*1000)*(i+1)*(n-i));
    }
    printf("%.2f",sum/1000.0);
}

为什么是1000,我也很迷惑,而且a[i]*1000和(i+1)(n-i)的顺序居然也有讲究。。。这两个测试点也错了

all in all,感受了一下pat的难度,更有信心了,这一个月要好好准备,争取一步到位

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值