首页 > 试题广场 >

一个一维维数组中只有1和-1,实现程序,求和为0的最长子串长

[问答题]
一个一维维数组中只有1和-1,实现程序,求和为0的最长子串长度,并在注释中给出时间和空间复杂度。
// C
int getLongestLength(int array[],int szie){
     //   TODO
}

// C++
int getLongestLength(const vector<int> & array){
     //   TODO
}

// Java
int getLongestLength(List<Integer> array){
     //   TODO
}

动态规划,arr为原始序列,动态规划序列为dp[len+1],dp[i+1]表示以arr第i个元素结尾的序列的最长0和子串长度。
if arr[i] == -arr[i-1],dp[i+1] = dp[i-1] + 2,
if arr[i] == -arr[i-dp[i]], dp[i+1] = dp[i] + 2,
else arr[i] = 0

def foo(arr):
    dp = [0] * (len(arr) + 1)
    dp[0] = 0
    dp[1] = 0
    for i in range(1, len(arr)):
        if arr[i] == -arr[i-1]:
            dp[i+1] = dp[i-1] + 2
        elif arr[i] == -arr[i-dp[i]-1]:
            dp[i+1] = dp[i] + 2
        else:
            dp[i+1] = 0
    print(dp)
    return max(dp)

foo([ -1, -1,-1, -1, -1, 1, 1, 1])
>>> 6
foo([-1, 1, -1, -1, 1, -1])
>>> 4

发表于 2018-08-14 14:43:58 回复(3)
有一个更简单的方法。说下思路

思路就是在i从0到n,计算sum(i),sum(i)表示从0到i的元素之和。并保存在字典dic中,value是索引i,在往后的遍历中每得到一个sum(i)就查看dic的keys是否已有此sum(i)值,如果有则用当前i位置减去保存的i,并与maxLen比较,取大的那个。遍历结束,给出结果。时间复杂度O(n),空间复杂度O(1)。
原链接里是python写的,我又用Java写了一下

import java.util.HashMap;

public class yuantiku {
    public static int getLongestLength(int []a) {
        int max=0;
        int sum=0;
        HashMap<Integer,Integer> hashMap=new HashMap<>();
        hashMap.put(0,-1);
        for (int i=0;i<a.length;i++){
            sum=sum+a[i];
            if (hashMap.get(sum)==null){
                hashMap.put(sum,i);
            }else{
                int tmp=i-hashMap.get(sum);
                if (max<tmp){
                    max=tmp;
                }
            }
        }
        return max;

    }

    public static void main(String[] args) {
        int []a=new int[]{ -1, -1,-1, -1, -1, 1, 1, 1};
        System.out.println(getLongestLength(a));
    }
}


作者:贰拾贰画生
链接:https://www.jianshu.com/p/3bf87384a92b
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

编辑于 2018-08-07 22:01:20 回复(1)
动态规划解法
核心思路 dp[i][j]表示从array[i]一直加到array[j]的和
递推式:dp[i][j] = dp[i+1][j-1] + array[i] + array[j];
判定:if(dp[i][j] == 0) max = max(max, j-1+1);
public class Solution {
    public static int getLongestLength(List<Integer> array) {
        if(array.size() <= 1)
            return 0;
        int max = 0;
        int size = array.size();
        //tab[i][j]表示从array[i]一直加到array[j]的和
        int[][] tab = new int[size][size];

        //求两两相邻的和,作为下一步的边界条件
        for(int i = 1; i < size; i++) {
            tab[i-1][i] = array.get(i-1) + array.get(i);
            if(array.get(i) == -array.get(i-1)) 
                max = 2;
        }

        //由于数组中只有1和-1,要使结果为0,子串长度必须为偶数,因此len = len + 2;
        for(int len = 3; len < size; len = len + 2) {
            for(int i = 0, j; (j = i + len) < size; i++) {
                tab[i][j] = array.get(i) + array.get(j) + tab[i + 1][j - 1];
                if(tab[i][j] == 0) {
                    max = Math.max(max, j-i+1);
                }
            }
        }
        return max;
    }
} 

编辑于 2018-08-04 20:06:52 回复(1)
// Java
int getLongestLength(List<Integer> array){
    //  动规,leetcode32最长有效括号变体
    // 时间复杂度 O(N)
    // 空间复杂度 O(N)
    int len = array.length();
    int[] nums = new int[len];
    int[] dp = new int[len];
    nums[0] = array.get(0);
    int res = 0;
    for(int i = 1; i < len; i++) {
        nums[i] = array.get(i);
        if(nums[i] + nums[i-1] == 0) {
            dp[i] = (i >= 2 ? dp[i-2] : 0) + 2;
        } else if(i - dp[i-1] > 0 && nums[i-dp[i-1]-1] + nums[i] == 0) {
            dp[i] = (i-dp[i-1] >= 2 ? dp[i-dp[i-1]-2] : 0) + 2 + dp[i-1];
        }
        res = Math.max(res, dp[i]);
    }
    return res;
}

编辑于 2020-08-01 18:44:00 回复(0)
public class Solution {

    public static void main(String[] args) {
        int[] nums={1,1,1,1,-1,-1,-1,-1,1,1,1};
        System.out.println(getLongest(nums));
    }

    

    //最长为0的子串
    public static int getLongest(int[] nums)
    {
        //动态规划
        int begin=0;
        int maxLength=0;
        //扩大规则  dp[i][j]=dp[i+1][j-1]+nums[i]+nums[j]
        int length=nums.length;
        int[][] dp=new int[length][length];

        //一个数
        for(int i=0;i<length;i++)
            dp[i][i]=nums[i];

        for(int j=1;j<length;j++)
            for(int i=0;i<j;i++)
            {
                //两个数
                if(j-i==1)
                    dp[i][j]=nums[i]+nums[j];
                else//大于两个数
                    dp[i][j]=nums[i]+nums[j]+dp[i+1][j-1];


                if(dp[i][j]==0)
                    maxLength=Math.max(maxLength,j-i+1);
            }
        return maxLength;
    }

}

发表于 2020-07-24 19:49:19 回复(0)
def getLongestLength(array):
    if len(array)<= 0:
        return 0
    neg_len = 0
    pos_len = 0
    for i in array:
        if i == -1:
            neg_len += 1
        else:
            pos_len += 1
    return 2*min(neg_len, pos_len)


O(1)的内存空间 , 分别记录+1 和 -1的长度
O(N)的时间复杂度来遍历数组
思路: 分别记录+1, -1的个数,最小个数的二倍就是最大长度
发表于 2019-08-24 15:20:56 回复(0)
思路如下:直接遍历数组,记录数组中1和-1的个数,最长的字串长度即为个数较少的那个数的2倍;
class Solution(object):
    def fun(self,l):
        p=0
        t=0
        for i in range(len(l)):
            if l[i]>0:
                p+=1
            else:
                t+=1
        result=2*min(t,p)
        print(result)
        return result


发表于 2019-07-31 15:22:56 回复(1)