这里咱们进行pta部分有嗲表型题目进行讲解与展示
最大子列和问题
***题目***给定K个整数组成的序列{n1,n2,n3,nk},其中 1≤i≤j≤K。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。
问题现要求你编写程序,计算给定整数序列的最大子列和。
本题旨在测试各种不同的算法在各种数据情况下的表现。
注意各组测试数据特点如下:
数据1:与样例等价,测试基本正确性;
数据2:102个随机整数;
数据3:103个随机整数;
数据4:104个随机整数;
数据5:105个随机整数;
输入格式: 输入第1行给出正整数K (≤100000);第2行给出K个整数,其间以空格分隔。
输出格式: 在一行中输出最大子列和。如果序列中所有整数皆为负数,则输出0。
输入样例:
6
-2 11 -4 13 -5 -2
结尾无空行
输出样例:
20
结尾无空行
代码一:
#include<iostream>
#include<vector>
#include<numeric>
using namespace std;
int main()
{
vector<int>v;
int n;
cin>>n;
int a,b,flag=0;b=n;
while(b--)
{
cin>>a;
if(a<0)
{flag++;}
v.push_back(a);
}
if(flag==n)//判断整数为负数
{
cout<<"0";
}
vector<int>::iterator it=v.begin();
vector<int>::iterator its=v.end();
a=accumulate(v.begin(), v.end(), 0);
for(;it!=v.end();it++)//一一进行判断,比对,把所有情况均写出来然后一一比较,这里好处是不用思考即可得出答案
{
its=v.end();
for(;it<=its;its--)
{
if(a<accumulate(it, its, 0))//采用STL中的函数,非常简便。
{
a=accumulate(it, its, 0);}
}
}
cout<<a;
}
此处采用暴力枚举,并且大致类似,即将所有情况全部列举出来,然后比对,运行时间较长,可能会在测试数据时出现运行超时的情况。在数目较小时可以运行,一旦树木较大,就不行
这里我又找到了另一种方法:
先上代码:
#include <iostream>
using namespace std;
int main() {
int N, c, t = 0, maxn = 0;
cin >> N;
while (N--) {
cin >> c;
t += c;
if (t <= 0)
t = 0;
maxn = max(maxn, t);
}
cout << maxn;
return 0;
}
注意使用N进行计数,然后用maxn记录目前的最大结果,(由于此题目的特殊性,求顺序子列)用t来记录加上负数的情况,简直不要太妙,采用max函数进行比较,即简单又方便。而且运行时间较短,非常妙。
数组循环左移
本题要求实现一个对数组进行循环左移的简单函数:一个数组a中存有n(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向左移m(≥0)个位置,还需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?
输入格式:
输入第1行给出正整数n(≤100)和整数m(≥0);第2行给出n个整数,其间以空格分隔。
输出格式:
在一行中输出循环左移m位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。
输入样例:
8 3
1 2 3 4 5 6 7 8
结尾无空行
输出样例:
4 5 6 7 8 1 2 3
结尾无空行
#include<iostream>
#include<list>
using namespace std;
struct lnode{
int a;
struct lnode *next;
};
typedef struct lnode lnode;
int main()
{
lnode *p,*q,*l=new lnode;
l->next=NULL;
p=l;
int n,m;
int i;
cin>>n>>m;
while(n--)
{
cin>>i;
p->a=i;q=p;
p->next=new lnode;
p=p->next;
}
delete p;
q->next=l;
while((--m)&&m>0)//注意此题目中的m的范围,否则很可能就失败。
{
l=l->next;
}
q=l;
l=l->next;
while(q!=l)
{
cout<<(l->a)<<" ";
l=l->next;
}
cout<<(l->a);
}
此题注意m范围,其他都还好,此处使用循环链表,较为简单,如果使用数组,比较复杂,且移动数据较多。但是注意使用时出现的逻辑关系,否则很容易出现错误,数组越界等情况。
数列求和-加强版
题目给定某数字A(1≤A≤9)以及非负整数N(0≤N≤100000),求数列之和S=A+AA+AAA+⋯+AA⋯A(N个A)。例如A=1, N=3时,S=1+11+111=123。
&输入格式:
输入数字A与非负整数N。
输出格式:
输出其N项数列之和S的值。
输入样例:
1 3
结尾无空行
输出样例:
123
结尾无空行
第一次求解:
#include<iostream>
#include<string>
using namespace std;
int main()
{
double n;double c,d;
cin>>c>>n;d=c;//使用d来保存原始的c ,反之之后改变c时改变原始值
long double sum=0;
while(n--)
{
sum+=c;
c=c*10+d;//注意此时的c已经发生改变,如何生成多个数已经成为问题
}
cout<<sum;
}
但是并未充分考虑到数据的大小,使得当数据足够大时无法进行运算。
所以采用数组进行存储
第二次:
#include <stdio.h>
#define MAX_N 100000
/* A的位数最大可能为10万,故涉及大整数,
此题考虑用字符数组存储大整数各位
*/
int main(void){
int A, N, i, tempSum, remainder=0;
int arr[MAX_N+1];
scanf("%d%d", &A, &N);
if(N==0){
printf("0");
return 0;
}
for(i=0; i<N; i++){ /*所有加数中权值相同的位求和,低位向高位进位*/
tempSum = A*(N-i)+remainder;
arr[i] = tempSum%10;
remainder = tempSum/10;
}//从最低位算起
if(remainder)
arr[i] = remainder;
else
i--;
for(;i>=0; i--){
printf("%d", arr[i]);
}
return 0;
}
**注意:**这里的reminder是用来控制位数以及进位,必要时要使用
在进行这种运算时必须要记得使用数组进行运算