数据结构_第一周编程作业_C++题解
DS_Lecture 1 Assignments_C++题解
中国大学MOOC_陈越、何钦铭_数据结构_第一周编程作业
1. 最大子列和问题
本次课最后讲到的4种算法的实验题,属于基本要求,必做
算法2_双层循环
#include<cstdio>
using namespace std;
int main()
{
int n;
scanf("%d",&n);
int *data = new int[n];
for (int i = 0; i < n; i++){
scanf("%d",&data[i]);
}
int maxsum = 0;
for (int i = 0; i < n; i++){
int subseqsum = 0;
for (int j = i; j < n; j++){
subseqsum += data[j];
if (subseqsum > maxsum) maxsum = subseqsum;
}
}
printf("%d",maxsum);
return 0;
}
时间复杂度:\(O(n^2)\)
算法3_分治法
#include<cstdio>
using namespace std;
int max3(int A, int B, int C){
return A > B ? (A > C ? A : C) : (B > C ? B : C);
}
int DivideAndConquer(int* data, int left, int right)
{
if (left == right){
if (data[left] > 0) return data[left];
else return 0;
}
int center = (left + right) / 2;
int leftmaxsum = DivideAndConquer(data, left, center);
int rightmaxsum = DivideAndConquer(data, center+1, right);
int leftmaxbordersum = 0; int leftbordersum = 0;
for (int i = center; i >= left; i--){
leftbordersum += data[i];
if (leftbordersum > leftmaxbordersum) leftmaxbordersum = leftbordersum;
}
int rightmaxbordersum = 0; int rightbordersum = 0;
for (int i = center+1; i <= right; i++){
rightbordersum += data[i];
if (rightbordersum > rightmaxbordersum) rightmaxbordersum = rightbordersum;
}
return max3(leftmaxsum, rightmaxsum, leftmaxbordersum + rightmaxbordersum);
}
int main()
{
int n;
scanf("%d",&n);
int *data = new int[n];
for (int i = 0; i < n; i++){
scanf("%d",&data[i]);
}
int maxsum = DivideAndConquer(data, 0, n-1);
printf("%d",maxsum);
return 0;
}
时间复杂度:\(O(n\log n)\)
注意递归的写法
算法4_在线处理
#include<cstdio>
using namespace std;
int main()
{
int n;
scanf("%d",&n);
int *data = new int[n];
int maxsum = 0;
int subseqsum = 0;
for (int i = 0; i < n; i++){
scanf("%d",&data[i]);
subseqsum += data[i];
if (subseqsum > maxsum) maxsum = subseqsum;
if (subseqsum < 0) subseqsum = 0;
}
printf("%d",maxsum);
return 0;
}
时间复杂度:\(O(n)\)
当前子列和为负时清零,因为必然对后面的和没有正的贡献
2. PAT(A) 1007 Maximum Subsequence Sum
2004年浙江大学计算机专业考研复试真题,是本次课最后讲到的算法的改造,要求略高,选做。
#include<cstdio>
using namespace std;
int main()
{
int n;
scanf("%d",&n);
int *data = new int[n];
int maxsum = -1;
int subseqsum = 0;
int maxleft = 0; int maxright = n-1;
int left = 0; int right = 0;
for (int i = 0; i < n; i++){
scanf("%d",&data[i]);
subseqsum += data[i];
right = i;
if (subseqsum > maxsum){
maxsum = subseqsum;
maxleft = left;
maxright = right;
}
if (subseqsum < 0){
subseqsum = 0;
left = i + 1;
}
}
printf("%d %d %d", maxsum<0 ? 0 : maxsum, data[maxleft], data[maxright]);
return 0;
}
- 时间复杂度:\(O(n)\)
- 测试点:负数和零=》
maxsum不能初始化为0,而应初始化为负数 - 由于最后要给出子列的起始坐标,用
left和right记录,每当maxsum更新时,maxleft和maxright也跟着更新
3. 二分查找
Position BinarySearch( List L, ElementType X ){
int left = 1; int right = L->Last;
while(left <= right){
int mid = (left + right) / 2;
if (L->Data[mid] == X) return mid;
if (L->Data[mid] < X) left = mid + 1;
else right = mid - 1;
}
return NotFound;
}
- 注意循环边界条件
- 二分查找及各种变种

浙公网安备 33010602011771号