陈越数据结构_第一周

陈越数据结构_第一周

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值