陈越数据结构_第一周
1. 最大子列和问题
是第一周最后讲到的4种算法的实验题,属于基本要求,一定要做;
-
题目见PAT
-
输入样例:
6 -2 11 -4 13 -5 -2
-
输出样例:
20
1.1 解法1:暴力解法
- 算法思想:暴力枚举所有子序列求解,保留最大的子序列和
- c++代码如下:
#include <iostream>
using namespace std;
int maxSubsequenceSum1(int n,int input_arr[]){
int max_sum=0;
for(int i=0;i<n;i++){
for(int j=i;j<n;j++){
int this_sum = 0;
for(int k=i;k<j;k++){
this_sum+=input_arr[k];
}
if(this_sum>max_sum){
max_sum = this_sum;
}
}
}
return max_sum;
}
int main(){
int N = 100000;
int input_arr[N];
int n;
int max_sum;
cin >> n;
for(int i=0;i<n;i++){
cin >> input_arr[i];
}
max_sum = maxSubseqceSum2(n, input_arr);
cout << max_sum << endl;
return 0;
}
- 时间复杂度:O(n^3)
1.2 解法2:针对解法1改进
- 算法思想:分析可知,解法1中会有重复计算的子序列,因此去掉一个
- c++代码如下:
int maxSubsequenceSum2(int n,int input_arr[]){
int max_sum=0;
for(int i=0;i<n;i++){
int this_sum = 0;
for(int j=i;j<n;j++){
this_sum+=input_arr[j];
if(this_sum>max_sum){
max_sum = this_sum;
}
}
}
return max_sum;
}
- 算法复杂度:O(n^2) 陈越老师讲到优秀的程序员看到O(n^2) 时就要想到把它优化到O(nlogn)
1.3 解法3:分而治之的解法
-
算法思想:
-
递归+分而治之。
-
分为三部分分别求解最大子序列和:左半部分的最大子序列和、右半部分的最大子序列和、跨越中间边界的最大子序列和
-
-
c++代码:
int max3(int num1, int num2, int num3){
int max_num = num1;
if(num2>max_num){
max_num = num2;
}
if(num3>max_num){
max_num = num3;
}
return max_num;
}
int maxSubSum3(int left, int right, const int input_arr[])
{
int max_sum = 0;
int left_max_sum, right_max_sum;
int left_board_max_sum, right_board_max_sum;
int left_board_sum, right_board_sum;
int center;
// 1. 递归基准情形
if(left == right){
if(input_arr[left]>0){
return input_arr[left];
}
else{
return 0;
}
}
// 2. 递归不断推进
center = (left + right)/2;
left_max_sum = maxSubSum3(left, center, input_arr);
right_max_sum = maxSubSum3(center+1, right, input_arr);
// 3. 求解跨边界的情况
left_board_sum = 0;
left_board_max_sum =0;
for(int i= center; i>=left;i--){
left_board_sum += input_arr[i];
if(left_board_sum>left_board_max_sum){
left_board_max_sum = left_board_sum;
}
}
right_board_sum = 0;
right_board_max_sum = 0;
for(int i=center+1;i<=right;i++){
right_board_sum += input_arr[i];
if(right_board_sum>right_board_max_sum){
right_board_max_sum = right_board_sum;
}
}
max_sum = max3(left_max_sum, right_max_sum, (left_board_max_sum+right_board_max_sum));
return max_sum;
}
int maxSubsequenceSum3(int n, const int input_arr[])
{
return maxSubSum3(0, n-1, input_arr);
}
- 时间复杂度:O(nlogn)
1.4 解法4:漂亮的解法
- 算法思路:目前能力有限,只是可以看懂,阐述不出思想
- c++代码:
int maxSubsequenceSum4(int n, const int input_arr[]){
int max_sum=0;
int this_sum=0;
for(int i=0;i<n;i++){
this_sum += input_arr[i];
if(this_sum > max_sum){
max_sum = this_sum;
}
else if(this_sum < 0){
this_sum = 0;
}
}
return max_sum;
}
- 时间复杂度:O(n)
2. Maximum Subsequence Sum
**Maximum Subsequence Sum:**是2004年浙江大学计算机专业考研复试真题,要求略高,选做。
-
题目:
-
c++代码
-
算法思想:
-
最大子列和问题中解法4的复杂版
-
设置start和end两个变量,当this_sum<0时,要开始新的序列,更新临时变量temp_index,当发现有了最大值更新的时候,更新start值和end两个值.
-
-
c++代码:
#include <iostream>
using namespace std;
int start_index = 0, end_index = 0;
int maxSubsequenceSum4(int n, const int input_arr[])
{
start_index = 0, end_index = n-1;
int max_sum = -1;
int this_sum = 0;
int temp_index = 0;
for (int i = 0; i < n; i++)
{
this_sum += input_arr[i];
if (this_sum < 0)
{
this_sum = 0;
temp_index = i+1;
}
else if (this_sum > max_sum)
{
max_sum = this_sum;
start_index = temp_index;
end_index = i;
}
}
if (max_sum < 0) max_sum = 0;
return max_sum;
}
int main()
{
int N = 100000;
int input_arr[N];
int n;
int max_sum;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> input_arr[i];
}
max_sum = maxSubsequenceSum4(n, input_arr);
cout << max_sum << ' ' << input_arr[start_index] << ' ' << input_arr[end_index] << endl;
return 0;
}
3. 二分查找
PAT 函数填空题
- 算法思想:难点在于停止条件的把握
- c语言代码:
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
#define NotFound 0
typedef int ElementType;
typedef int Position;
typedef struct LNode *List;
struct LNode {
ElementType Data[MAXSIZE];
Position Last; /* 保存线性表中最后一个元素的位置 */
};
List ReadInput(); /* 裁判实现,细节不表。元素从下标1开始存储 */
Position BinarySearch( List L, ElementType X );
int main()
{
List L;
ElementType X;
Position P;
L = ReadInput();
scanf("%d", &X);
P = BinarySearch( L, X );
printf("%d\n", P);
return 0;
}
/* 你的代码将被嵌在这里 */
Position BinarySearch( List L, ElementType X ){
Position low, high, mid;
low = 0; high = L->Last-1;
while (low<=high)
{
mid = (low+high)/2;
if(L->Data[mid]>X){
high = mid-1;
}
else if(L->Data[mid]<X){
low = mid+1;
}
else
{
return mid;
}
}
return NotFound;
}