2021-05-22

本文介绍了四个数据结构与算法问题的解题思路和代码实现,包括:1) 统计正整数序列中数字出现次数,按顺序输出;2) 约瑟夫问题的拓展,输出出圈顺序;3) 计算带有括号的算术表达式;4) 求区间内整数序列和的最大值及其区间。涉及知识点包括链表、栈、单调队列等数据结构和算法。
摘要由CSDN通过智能技术生成

2020级数据结构荣誉可课第一次上机考试题解(线性表)

一、重复计数

 在一个有限的正整数序列中,有些数会多次重复出现。请你统计每个数的出现次数,然后按数字在序列中第一次出现的位置顺序输出数及其次数。

                                                                                                                                                                                                                                 

题意:统计数列中每种数字出现的次数,并按照出现顺序输出。

思路:

一)、二重循环

这是没学数据结构之前最容易想到的方法,两次扫描。虽然简单但是时间复杂度为o(n2),至少开两个数组,空间复杂度较高。不是一个好的算法。在此不在展示代码。

二)、模拟链表

开一个结构体A,里面1存储数字和其出现的次数,边输入,边进行数据处理,加快了程序运行速度,从前往后扫描一遍若有重复数据,则num值+1,若没有则更新当前的结构体数组。

此作法时间复杂度为0(logn)。

完整代码

二、报数游戏

题意:约瑟夫问题的拓展,要求输出所有人出圈的的顺序。

思路:设置一个计步数的变量count,和出圈人数变量,每当count达到指定步长,将对应的编号输出并置标记‘0’,在清零count,更新出圈人数。

完整代码:

三、算术表达式的计算:

题意:输入一串算术表达式(带有括号),将其计算输出。、

思路:

可以采用栈来完成,利用栈的性质将中缀表达式转换为后缀表达式,根据优先级弹栈压栈。因为要识别运算符“+,-,*”,所以我们还要写计算函数和判断优先级的函数。

代码:

运算函数:

优先级函数:

关键代码:将中缀表达式转换为后缀表达式,我们需要两个栈一个存储运算符一个存储待运算的值或运算结果。

1)、判断将数字压入栈q中

2)、将运算符压入栈s中,并随即将其转换为后缀运算符的形式:

  

3)、完整代码:

#include<stack>
#include<iostream>
#include<math.h>
#include<ctype.h>
using namespace std;
int  calculate(int d1,char t,int d2);
int jugepre(char x);
int main()
{   char a[1001];
    cin>>a;
    
    stack<char> s;
    stack<int> q;
    int i=0,d=0;

while(a[i]!='=')
{    char x=a[i];
    if(x>='0'&&x<='9')
    {
        d=x-'0';
        while(a[i+1]!='\0'&&a[i+1]>='0'&&a[i+1]<='9')
        {
            x=a[++i];
            d=d*10+(x-'0');
        }
        q.push(d);
    }
    else
    {
       if(s.empty()||x=='(') {s.push(x);}

                    else  if(x==')')
                        {
                        while(s.top()!='('&&!s.empty())
                            {
                                int d2=q.top();q.pop();
                                int d1=q.top();q.pop();
                                char t=s.top();s.pop();
                                if(t=='/'&&d2==0)
                                {
                                    cout<<"NaN";
                                    return 0;
                                }
                                int al=calculate(d1,t,d2);
                                q.push(al);
                            }
                        s.pop();
                    }
                        else  if(jugepre(x)>jugepre(s.top())) s.push(x);
                           else if(jugepre(x)<=jugepre(s.top())) {

                            while(!s.empty()&&(jugepre(x)<=jugepre(s.top())))
                            {
                                int d2=q.top();q.pop();
                                int  d1=q.top();q.pop();

                               char t=s.top();s.pop();
                                if(t=='/'&&d2==0)
                                {
                                    cout<<"NaN";
                                    return 0;
                                }
                               int  al=calculate(d1,t,d2);
                               q.push(al);
                            }
                            s.push(x);
                            }
    }
i++;
}


while(!s.empty())
{
            int  d2=q.top();q.pop();
            int  d1=q.top();q.pop();
            char t=s.top();
            s.pop();
            if(t=='/'&&d2==0)
            {
            cout<<"NaN";
            return 0;
            }
            int  al=calculate(d1,t,d2);
            q.push(al);

}

cout<<q.top();
 return 0;
}
int jugepre(char x)
{
    if(x=='(') return 0;
    else if(x=='*'||x=='/') return 2;
    else if(x=='+'||x=='-') return 1;
}
int  calculate(int d1,char t,int d2)
{
    if(t=='^')
       {
//cout<<int(pow(d1,d2))<<endl;
            return int(pow(d1,d2));
        }
    else if(t=='*')
            return d1*d2;
        else if(t=='/')
             return d1/d2;
            else if(t=='+')
                return d1+d2;
                else if(t=='-')
                    return d1-d2;
}

 

四、最喜爱序列

题意:一个含有N个整数的序列,求区间长度不超过m的区间中,区间内值和的最大值,以及该区间。若有多个则取第一个;

思路:才开始没有看清题意以为区间为定长暴力求解,只拿了40分,后来学习了其他同学的算法。采用单调队列自己重新写了一遍后,才通过。

知识点 :单调队列

单调队列。维护一个区间正确且单调
递增的队列,每次队首就是当前区间的最值
1.
单调性的维护 :当前元素和队尾元素比较, 若队尾
元素大于当前元素,队尾元素出队 ;重复处理,
到队空或队尾元素小于当前元素;当前元素入队;
// f 队首, r 队尾后空位
while(f<r && a[que[r-1]] > a[i] ) r--;
que[r++] = i;
2.
区间的维护: 若队首元素的位置不在区间内 ,则队
首元素出队;重复处理,直到队首元素在区间内
while( f<r && que[f] < i-m+1 ) f++;

代码:

#include<iostream>
#include<queue>
using namespace std;
 

int main(void)
{   int  a[600000];
    deque<int> s;
    int l, r;
    int  i=0, j=0,n=0, m=0;
    cin>>n>>m;
    a[0] = 0;
    for (i = 1; i <= n; i++)
    {
        cin>>a[i];
        a[i] += a[i - 1];
    }
     int  max = 0;
    while (!s.empty())
    s.pop_back();
    s.push_front(0);
    for (i = 1; i <= n; i++)
    {
        while ( a[s.front()] > a[i] &&!s.empty() )
        {
           s.pop_front();
        }
        s.push_front(i);
        while  ( m<i - s.back() &&!s.empty())
        {
            s.pop_back();
        }
        if(max< a[i] -a[s.back()])
        {
            max = a[i] - a[s.back()];
            l = s.back()+1;
            r = i;
        }
     }
cout<<max<<" "<<l<<" "<<r<<"\n";
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值