ch1 基本概念

数据结构

定义

image.png

抽象数据类型

image.png 类似于java中的类的概念

算法

定义

  • 一个指令集 每条指令都不能有歧义
  • 产生输出
  • 在有限步骤之后终止

评判标准

往往看的是最差的情况

  • 时间复杂度T(n)
  • 空间复杂度S(n)

上界:O(f(n))
下界:Ω(g(n))
C⋅g(n)≤T(n)≤C⋅f(n)

屏幕截图

习题

最大子列和问题

给定n个整数的序列,求其中子列和的最大值。
如{-2,11,-4,13,-5,-2}其连续子列{11,-4,13}有最大的和20

暴力算法

T(N)=O(N³)

int MaxSubseqSum1(int n, int a[]) {
    int max = 0;
    for (int i = 0; i < n; i++) {//i是子列左端
        for (int j = i; j < n; j++) {//j是子列右端
            int tmp = 0;//用于储存子列和的临时变量
            for (int k = i; k <= j; k++) {//从i加到j 如果比max大则替换max
                tmp += a[k];
                if (tmp > max) {
                    max = tmp;
                }
            }
        }
    }
    return max;
}

较暴力算法

T(N)=O(N²)

int MaxSubseqSum2(int n, int a[]) {
    int max = 0;
    for (int i = 0; i < n; i++) {//i是子列左端
        int tmp = 0;//用于储存子列和的临时变量
        for (int j = i; j < n; j++) {//j是子列右端
            tmp += a[j];//i同j不同时 只需在j-1后加上最后一项
            if (tmp > max) {
                max = tmp;
            }
        }
    }
    return max;
}

分治算法

把整个数列一分为二,再一分为二,一直递归直到每个小序列左右两边只有一个数字;判断左边大还是右边大还是中间大,求出小序列的最大子列和;最后再递归回去,求出整个大序列的最大子列和
image.png
image.png 课程中仅讲解了分治算法思想 没有展示具体代码

贪心算法

从左到右遍历数组,如果前面的和加上当前值是负数(意味着对之后的加和没有帮助),就抛弃前面的数字们,如果如果前面的和加上当前值比max还大,就更新max
T(N)=O(N)

int MaxSunseqSum4(int n, int a[]) {
    int max = 0;
    int tmp = 0;
    for (int i = 0; i < n; i++) {//向右累加
        tmp += a[i];
        if (tmp > max) {//发现更大的和则更新结果
            max = tmp;
        }
        else if (tmp < 0) {//如果当前子列和为负 则不可能使后面的部分和更大 全部抛弃
            tmp = 0;
        }
    }
    return max;
}