• 【数组】最大子数组问题(要求时间复杂度最佳)


    思路:

    就是最大子列和呗,时间复杂度最佳那就是O(n),使用贪心算法。

    以下是三种方法,时间复杂度递减

      1 // preface.cpp : 基本概念 求最大子列和
      2 #include "pch.h"
      3 #include <iostream>
      4 using namespace std;
      5 
      6 /* 方法一:确定子列的首部,逐个累加,时间复杂度 O(n^2)*/
      7 int MaxSubseqSum1(int n, int a[]) {
      8     int max = 0;
      9     for (int i = 0; i < n; i++) {
     10         int temp = 0;//当前子列和
     11         for (int j = i; j < n; j++) {
     12             temp += a[j];
     13             if (temp > max)
     14                 max = temp;
     15         }
     16     }
     17     return max;
     18 }
     19 
     20 /* 方法二:分治法,递归分成两份,分别求每个分割后最大子列和,时间复杂度为 O(n*logn)*/
     21 
     22 
     23 /*返回三者中的最大值*/
     24 int Max3(int A, int B, int C) {
     25     return (A > B) ? (A > C ? A : C) : (B > C ? B : C);
     26 }
     27 
     28 /*分治*/
     29 int DivideAndConquer(int a[], int left, int right) {
     30     /*递归结束条件:子列只有一个数字*/
     31     // 当该数为正数时,最大子列和为其本身
     32     // 当该数为负数时,最大子列和为 0
     33     if (left == right) {
     34         if (a[left] > 0)
     35             return a[left];
     36         return 0;
     37     }
     38 
     39     /* 分别递归找到左右最大子列和*/
     40     int center = (left + right) / 2;
     41     int MaxLeftSum = DivideAndConquer(a, left, center);
     42     int MaxRightSum = DivideAndConquer(a, center+1, right);
     43 
     44     /* 再分别找左右跨界最大子列和*/
     45     int MaxLeftBorderSum = 0;
     46     int LeftBorderSum = 0;
     47     for (int i = center; i >= left; i--) {//从边界出发向左找
     48         LeftBorderSum += a[i];
     49         if (MaxLeftBorderSum < LeftBorderSum)
     50             MaxLeftBorderSum = LeftBorderSum;
     51     }
     52     int MaXRightBorderSum = 0;
     53     int RightBorderSum = 0;
     54     for (int i = center + 1; i <= right; i++) {  // 从边界出发向右边找
     55         RightBorderSum += a[i];
     56         if (MaXRightBorderSum < RightBorderSum)
     57             MaXRightBorderSum = RightBorderSum;
     58     }
     59     /*最后返回分解的左边最大子列和,右边最大子列和,和跨界最大子列和三者中最大的数*/
     60     return Max3(MaxLeftSum, MaxRightSum, MaXRightBorderSum + MaxLeftBorderSum);
     61 }
     62 
     63 int MaxSubseqSum2(int n, int a[]) {
     64     return DivideAndConquer(a, 0, n - 1);
     65 }
     66 /*“贪心法”,即不从整体最优上加以考虑,只做出某种意义上的局部最优解。
     67 其实最大子列和与它的首部和尾部都没有关系,我们只关心它当前的大小。
     68 当临时和加上当前值为负时,它对之后子列和肯定没有帮助(甚至只会让之后的和更小!)
     69 我们抛弃这段临时和将它置0*/
     70 
     71 /* 方法三:直接累加,如果累加到当前的和为负数,置当前值或0,时间复杂度为 O(n)*/
     72 int MaxSubseqSum3(int n, int a[]) {
     73     int max = 0;
     74     int tempmax = 0;
     75     for (int i = 0; i < n; i++) {
     76         tempmax += a[i];
     77         if (tempmax < 0) {
     78             tempmax = 0;
     79         }
     80         else if (max < tempmax) {
     81             max = tempmax;
     82         }
     83         
     84     }
     85     return max;
     86 }
     87 
     88 int main()
     89 {
     90     int n;
     91     int a[100000 + 5];
     92     cin >> n;
     93     for (int i = 0; i < n; i++)
     94         cin >> a[i];
     95     MaxSubseqSum1(n, a);
     96     MaxSubseqSum2(n, a);
     97     MaxSubseqSum3(n, a);
     98     cout<< MaxSubseqSum1(n, a)<<endl;
     99     cout << MaxSubseqSum2(n, a)<<endl;
    100     cout << MaxSubseqSum3(n, a)<<endl;
    101     return 0;
    102 }
  • 相关阅读:
    unity3d优化-代码篇(不定期更新)
    Activity的生命周期
    继承了AppCompatActivity的全屏设置
    shaderlab UV动画所需的变量声明
    加载Assetbundle需要注意的地方
    VisualStudio中的编辑后期生成事件
    unity3D射线检测敌人是否在前方
    Unity3D 定时发射子弹
    Unity3D使用NGUI做个弹窗
    Unity3D TouchScript 插件教程一
  • 原文地址:https://www.cnblogs.com/PennyXia/p/12654466.html
Copyright © 2020-2023  润新知