zoukankan      html  css  js  c++  java
  • 剑指offer系列——30.连续子数组的最大和

    Q:HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)
    T:
    1.对于一个数A,若是A的左边累计数非负,那么加上A能使得值不小于A,认为累计值对整体和是有贡献的。如果前几项累计值负数,则认为有害于总和,total记录当前值。
    注意:C++中表示正无穷是INF_MAX,负无穷是INF_MIN,需要 #include

        int FindGreatestSumOfSubArray(vector<int> array) {
            if (array.empty())
                return 0;
            int max = INF_MIN;
            int cur = 0;
            for (int i = 0; i < array.size(); i++) {
                cur += array[i];
                if (cur > max)
                    max = cur;
                if (cur < 0)
                    cur = 0;
            }
            return max;
        }
    

    2.动态规划法:遍历数组,定义一个变量来存储当前向量子序列最大值,(F(i)=max(F(i-1)+array[i] , array[i]))

        int FindGreatestSumOfSubArray(vector<int> array) {
            if (array.empty())
                return 0;
            int result = array[0];
            int cur = array[0];
            for (int i = 1; i < array.size(); i++) {
                cur = max(cur + array[i], array[i]);
                result = max(result, cur);
            }
            return result;
        }
    

    3.分治法:
    考虑将数组从中间分为两个子数组,则最大的比出现在三种情况之一

    1. 完全位于左边数组
    2. 完全位于右边数组
    3. 跨越中点,包含左右数组靠近中点的部分

    具体实现: 递归左右子数组再分为两个数组,直到子数组只有一个元素

        int FindGreatestSumOfSubArray(vector<int> array) {
            if (array.empty())
                return 0;
            return Find(array, 0, array.size() - 1);
        }
    
        int Find(vector<int> array, int left, int right) {
            if (left == right) {
                return array[left];
            }
            int mid = (left + right) / 2;
            //跨越中点,包含左右数组靠近中点的部分
            int maxLeftm = INT_MIN;
            int temp = 0;
            for (int i = mid; i >= left; i--) {
                temp = temp + array[i];
                maxLeftm = max(maxLeftm, temp);
            }
            int maxRightm = INT_MIN;
            temp = 0;
            for (int i = mid + 1; i <= right; i++) {
                temp = temp + array[i];
                maxRightm = max(maxRightm, temp);
            }
            int maxMid = maxLeftm + maxRightm;
            //完全位于左边数组
            int maxLeft = Find(array, left, mid);
            //完全位于右边数组
            int maxRight = Find(array, mid + 1, right);
            return max(maxRight, max(maxMid, maxLeft));
        }
    
  • 相关阅读:
    iOS 获取全局唯一标示符
    iOS 获取全局唯一标示符
    如何让UIViewController自动弹出PickerView
    如何让UIViewController自动弹出PickerView
    防止NSTimer和调用对象之间的循环引用
    防止NSTimer和调用对象之间的循环引用
    inputAccessoryView,inputView
    @encode关键字
    @encode关键字
    用 Flask 来写个轻博客 (11) — M(V)C_创建视图函数
  • 原文地址:https://www.cnblogs.com/xym4869/p/12305123.html
Copyright © 2011-2022 走看看