数据结构PTA练习题1

1.查询子序列和

对N个整数的序列,查询子序列和∑k=ij​Ak​ , (1≤i,j≤N).

输入格式:

第1行,两个整数:N和Q,表示整数的个数和查询的次数,1≤N≤100000,0≤Q≤100000.

第2行,N个用空格分开的整数 x , │x│≤20000.

第3至Q+2行,每行两个整数i和j,表示所求子序列和的区间[i,j],1≤i≤j≤N,保证所有区间都合法。

输出格式:

Q行,每行一个整数,表示相应子序列的和

代码长度限制-16 KB

时间限制-200 ms

内存限制-2 MB 

问题:常规算法当Q较大时会运行超时

思路:利用数组保存求和结果,每多加一项就sum[i++]=sum[i-1]+x,输出时sum[r]-sum[l-1]即可

long long sum[100010] = { 0 };
 for (int i = 1; i <= N; i++)
    {
        long long x;
        scanf("%lld", &x);
        sum[i] = sum[i - 1] + x;
    }

 需要注意的是,提交代码时利用scanf运行能通过,cin会超时。

完整代码

#include<iostream>
#include<cstdio>
using namespace std;
int N, Q;
long long sum[100010] = { 0 };
int main()
{
    cin >> N >> Q;
    for (int i = 1; i <= N; i++)
    {
        long long x;
        scanf("%lld", &x);
        sum[i] = sum[i - 1] + x;
    }
    for (int i = 1; i <= Q; i++)
    {
        int l, r;
        scanf("%d%d", &l, &r);
        printf("%lld", sum[r] - sum[l - 1]);
        if (i != Q)
            printf("\n");
    }
    return 0;
}

2.数列查询

已知数列的通项公式为:

     f(n) = f(n-1)*11/10,f[1]=10. 

通项从左向右计算,*和/分别表示整数乘法和除法。
现在,要多次查询数列项的值。

输入格式:

第1行,1个整数q,表示查询的次数, 1≤q≤10000.
第2至q+1行,每行1个整数i,表示要查询f(i)的值。

输出格式:

q行,每行1个整数,表示f(i)的值。查询的值都在32位整数范围内。

代码长度限制-16 KB

时间限制-10 ms

内存限制-1 MB

问题:常规递归算法会运行超时

思路:利用已经计算出的f(n)作为递归出口

int a[10000]={0};
if(n==1) return a[1];
	else {
		if(a[n]>0)return a[n];
		else {a[n]=f(n-1)*11/10;return a[n];}
	}

 注意:可以利用一个循环,每输入一个数字就求出结果。

完整代码:

#include<stdio.h>
int a[10000]={0};
int f(int n){
	if(n==1) return a[1];
	else {
		if(a[n]>0)return a[n];
		else {a[n]=f(n-1)*11/10;return a[n];}
	}
}
int main(){
	int q,k;
	scanf("%d",&q);
	a[1]=10;
	for(int i=1;i<=q;i++){
		scanf("%d",&k);
		printf("%d\n",f(k));
	}
	return 0;
} 

3.估算运行空间

一个代码的存储部分如下:

int n,m;

int vertex[MAXN];

int g[MAXN][MAXN];

假设:在32为操作系统(OS)下运行,只考虑如上代码段,不考虑程序自身存储空间等,给定MAXN,计算该算法的运行空间,其中空间的单位为Mb,1Mb = 10^6字节(Byte)。

输入格式:

一行,包含1个正整数,表示算法输入的最大取值MAXN,n <=10^6.

输出格式:

一个整数,表示该算法的运行空间估算值,该值向上取整。

代码长度限制-16 KB

时间限制-400 ms

内存限制-64 MB

 没有太大难度,求出空间/1e6即可,记得向上取整

#include<iostream>
using namespace std;

int main()
{
	long long n, m;
	cin >> n;
	m = 4 * n + 4 * (n * n)+8;
	if (m % 1000000 != 0)
	{
		m = m / 1000000 + 1;
	}
	else m = m / 1000000;
	cout << m;
	return 0;
}

4.估算运行时间

一个算法的基本运算:交换两个整数的值,时间复杂度为 T = n(n-1)/2。其中,交换使用3个赋值运算实现。

假设:交换运算时间超过整个算法的1/3,在单核通用计算机上运行,给定n的最大取值,估算该算法的最大运行时间,时间向上取整为秒。

输入格式:

行,包含1个正整数n,表示算法输入的最大取值,n <=10^8。

输出格式:

个整数,表示该算法的最大运行时间的估计.

代码长度限制-16 KB

时间限制-400 ms

内存限制-64 MB

这道题主要是意思不太好理解,赋值运算时间复杂度已知,一个交换有三个赋值语句,交换占算法时间的1/3,求算法运行时间(记得除1e8,向上取整)

#include<iostream>
using namespace std;

int main()
{
	long long n;
	long long t;
	cin >> n;
	t = n * (n - 1) / 2;
	t = t * 9;
	if (t % 100000000 == 0)
		t = t / 100000000;
	else
		t = t / 100000000 + 1;
	cout << t;
}

 5.冰雹猜想

70年代中期,美国各所名牌大学校园内,人们都像发疯一般,夜以继日,废寝忘食地玩弄一种数学游戏。这个游戏十分简单:任意写出一个正整数N,并且按照以下的规律进行变换:

如果是个奇数,则下一步变成3N+1。

如果是个偶数,则下一步变成N/2。

不单单是学生,甚至连教师、研究员、教授与学究都纷纷加入  。为什么这种游戏的魅力经久不衰?因为人们发现,无论N是怎样一个数字,最终都无法逃脱回到谷底1。准确地说,是无法逃出落入底部的4-2-1循环,永远也逃不出这样的宿命。

这就是著名的“冰雹猜想”。

给出一个正整数N,计算全部变换过程(称作“雹程”)的步数。

输入格式:

一行,1个正整数N,N <=10^6.输出保证合法。

输出格式:

一个整数,为所求步数。

代码长度限制-16 KB

时间限制-400 ms

内存限制-64 MB

很简单,记得输入是long long类型即可

#include<iostream>
using namespace std;

int main()
{
	long long N;
	int sum=0;
	cin >> N;
	while (N != 1)
	{
		if (N % 2 == 0)
			N = N / 2;
		else
			N = (3 * N + 1);
		sum++;
	}
	cout << sum;
}

 6.素数

判断正整数 N 是否为素数。

规定:自然数1既不是素数也不是合数。

输入格式:

一行,包含1个正整数N,N <= 2^31 - 1.输入保证合法。

输出格式:

一行。如果N为素数,输出Yes,否则输出No.

代码长度限制-16 KB

时间限制-5 ms

内存限制-64 MB

问题:利用常规n/2会运行超时 

思路:让i循环到根号n

 for (i = 2; i <= sqrt(N); i++)
    {
        if (N % i == 0)
        {
            cout << "No";
            return 0;
        }
    }

完整代码:

#include<iostream>
#include<math.h>
using namespace std;

int main()
{
    long long N;
    int i;
    cin >> N;
    if (N == 1)
    {
        cout << "No";
        return 0;
    }
    for (i = 2; i <= sqrt(N); i++)
    {
        if (N % i == 0)
        {
            cout << "No";
            return 0;
        }
    }
    cout << "Yes";
    return 0;
}

大二代码小白初学数据结构,用博客来记录作业笔记与学习过程,方法大都较为常规,如有错误恳请指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值