zoukankan      html  css  js  c++  java
  • [getLongestLength] 加和为0的最长子串长度

    点击这里查看原文

    假设一个数组仅仅由1和-1组成,求该数组的和为0的最长子串的长度。
    例如:
    {1,-1,1,-1,1,1,1} 输出:4.
    昨天机试的时候做到这道题,不会做,今天思考一下。

    普通的解法

    枚举所有的子串,然后得到和为0的最长的长度,复杂度是O(n*n),这个应该会超时,昨天只能保存,不能运行,我猜这样应该不行,需要下面方法。其实看到这题,我想到的是最长回文子串这道题,仔细想想,还是挺像的,该搞一个传送门的。

    正确的解法

    解法:动态规划,dp0[i]表示以i结尾的加和为0 得到最长子串长度,dp1[i] 表示以i结尾的加和为1的最长子串长度,dp2[i]表示以i结尾的加和为-1 的最长子串长度。于是可以得到下面的递推关系:

    上面这段话摘自那个博客,n的平方复杂度不行,那大概就是nlogn或者n,需要考虑dp,然后分析,数组只有1或者-1,然后需要获得结果为0的长度,所以碰到1,我们希望能知道前面和为-1的最长,遇到-1,我们需要知道和为1的最长,所以我们就需要维护到当前位置,以当前位置结尾的和为0,1,-1的最长长度,然后思考怎么递推。显然,1 + 0 = 1, 1 + (-1) = 0,转移到1和0,很容易,转移到-1,怎么处理,什么结果加上1能得到结果是-1,当然是-2,但是我没维护和为2的,这就需要巧妙的思想。

    利用当前段的结果为0,加上这段之前的结果为-1,这样就能导出当前段为-1的,这样的思想很巧妙,仔细想想怎么回事,是不是有点kmp,马拉车算法之类的思想。

    好了,贴一下那位大神的代码:

    #include<iostream>
    #include<vector>
    using namespace std;
    int getLongestLength(int array[],int size){
        if(size<=1) return 0;
        vector<int>dp0(size);
        vector<int>dp1(size);
        vector<int>dp2(size);
        dp0[0]=0;
        if(array[0]==1){
            dp1[0]=1;
            dp2[0]=0;
        }else{
            dp1[0]=0;
            dp2[0]=1;
        }
        int result =0;
        for(int i =1;i<size;i++){
            if(array[i]==1){
                dp0[i]=dp2[i-1]==0?0:dp2[i-1]+1;
                dp1[i]=dp0[i-1]==0?1:dp0[i-1]+1;
                dp2[i]=dp0[i]==0?0:dp2[i-dp0[i]]+dp0[i];
            }else{
                dp0[i]=dp1[i-1]==0?0:dp1[i-1]+ 1;
                dp1[i]=dp0[i]==0?0:dp1[i-dp0[i]]+dp0[0];
                dp2[i]=dp0[i-1]==0?0:dp0[i-1]+1;
            }
            if(result<dp0[i]) result  =dp0[i];
        }
    
        return result;
    }
    int main(){
        int nums[]={-1,1,-1,1};
        cout<<getLongestLength(nums,4);
    }
    

    我认为也需要判断一下dp2[i-dp0[i]]的结果不为0,才行。没有画图,不知道解释清楚没有。

    还可以这样做,维护前缀和s,i<j, s(j) = s(i)的时候,可以知道i + 1 到j和为0,即可满足要求。这个好像容易理解一些。

    百度搜索1,-1,最长字串 可以找到解法。延伸到数组里面只有0和1,比如只有a和b,求最长子串a和b的个数相等之类的。还有什么变形,想出来再记下来吧。

    int getLongestString(vector<int> & v) {
        int n = v.size();
        if(n < 2) return 0;
        map<int, int> m;
        int s = 0;
        int res = 0;
        for(int i = 0; i < n; i++) {
            s += v[i];
            if(s == 0) {
                res = max(res, i + 1); continue;
            }
            if(!m.count(s)) {
                m[s] = i;
            } else {
                int len = i - m[s];
                res = max(res, len);
            }
        }
        return res;
    }
    
  • 相关阅读:
    php-数据类型
    php常量
    php变量
    loadrunner11安装教程
    ThumbProcess.exe错误的解决方法
    jmeter 测试MD5加密登录接口
    jmeter 上传附件脚本报Non HTTP response code: java.io.FileNotFoundException
    jmeter中提取json串
    Jmeter 非 GUI 命令行执行脚本文件
    jmeter 报错Error in NonGUIDriver java.lang.IllegalArgumentException: Report generation requires csv output format, check 'jmeter.save.saveservice.output_format' property
  • 原文地址:https://www.cnblogs.com/y119777/p/5851025.html
Copyright © 2011-2022 走看看