编程作业
01-复杂度1 最大子列和问题 (20 point(s))
此题为课上所讲的内容,为了让同学们感受四种算法的运算速度,PTA也专门为此设置超大上限的time limited。
原题链接
下面给出在线处理算法,即最快的算法。
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
int main() {
int number = 0;
int TargetNumber = 0, MaxNubmer = 0, thisSum = 0;
cin >> number;
int target[100010] = { 0 };
for (int i = 0; i < number; i++) {
scanf("%d", &target[i]);
thisSum += target[i];
if (thisSum < 0) {
thisSum = 0;
continue;
}
if (MaxNubmer < thisSum)
MaxNubmer = thisSum;
}
cout << MaxNubmer;
return 0;
}
主要思路是:将输入的数据从1开始不断累加,不断地判断是否为Max。当发现累加的结果小于零时,可以发现如果继续累加,只会使结果越小,此时抛弃前面累加的结果,从下一个重新开始。
01-复杂度2 Maximum Subsequence Sum (25 point(s))
此题为上一题的进化版,要记录序列的起始位置和终点位置,同时也挖了很多的小坑。
原题连接
下面给出我自己的accept代码。
#include<stdio.h>
#include<iostream>
using namespace std;
int main() {
int start = 0, end = 0, t = 0;
int thisSum = 0, MaxSum = -1;
int target[100010] = { 0 };
int number = 0;
bool flag = false;
cin >> number;
end = number - 1;
for (int i = 0; i < number; i++) {
scanf("%d", &target[i]);
thisSum += target[i];
if (MaxSum < thisSum) {
MaxSum = thisSum;
start = t;
end = i;
flag = true;
}
else if (thisSum < 0) {
thisSum = 0;
t = i + 1;
}
}if (MaxSum == -1)
cout << "0" << " " << target[0] << " " << target[number - 1] << endl;
else
cout << MaxSum << " " << target[start] << " " << target[end] << endl;
}
要注意的点:
- 可能只有我犯了这一个错误,但这的确卡了我很久!没有看完题(或者没有看懂)就开始瞎输出了!我一开始看到输出样例为1 4,再扫一眼题目,嗯,大概是输出序列的首位和末尾的下标的意思……然后就看到一堆绿绿的wrong answer不知所措……注意了,是输出目标序列的第一位数据和最后一位数据!
- 测试点5:0和负数。倘若有零和负数,我们要输出最大为零和零的位置。如果令Max=0,会捕捉不到数据为0的情况,这样程序有可能会视其为测试点4去处理,但其实是不同的。
- 记得判断Max值是否发生改变!不去判断的话测试点4的最大值将不会输出为0而为-1。
01-复杂度3 二分查找 (20 point(s))
此题为二分查找,比较简单。
原题链接
下面给出我的accept代码。
Position BinarySearch(List L, ElementType X) {
int left = 1, right = L->Last, mid = 0;
while (left <= right) {
mid = (left + right) / 2;
if (L->Data[mid] > X)
right = mid - 1;
else if (L->Data[mid] < X)
left = mid + 1;
else
return mid;
}
return NotFound;
}
要注意的点:
- 题目说数据为递增数列,则当中间值大于目标值时,应移动right边界,反之,应移动left边界。
- 因为只要判断出中间值时大于或者小于目标时,就能说明该点不是目标点,所以移动边界时,记得是right-1或者left+1.
- 判断条件记得是要left<=right。因为有可能判断到left=right时才确定结果,所以要等俩边界错位再跳出循环。
总结
- 审清题意,再动手。大部分时间都纠结在了那个非常弱智的坑里……明明很快就能ac掉的东西……
- 边界条件是很爱挖的坑,以后再刷pat的时候,多积累经验,再不给提示的情况下多琢磨可能出现的边界条件。