首页 > 试题广场 >

未排序数组中累加和为给定值的最长子数组系列问题补1

[编程题]未排序数组中累加和为给定值的最长子数组系列问题补1
  • 热度指数:3252 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
给定一个无序数组arr,其中元素可正、可负、可0。求arr所有子数组中正数与负数个数相等的最长子数组的长度。
[要求]
时间复杂度为,空间复杂度为

输入描述:
第一行一个整数N,表示数组长度
接下来一行有N个数表示数组中的数


输出描述:
输出一个整数表示答案
示例1

输入

5
1 -2 1 1 1

输出

2

备注:

和第CD11思路相同,把正数视为1,负数视为0。定义一个平衡因子balance,遇到一个正数就自增,遇到一个负数就自减,遇到零就直接跳过。遍历数组更新这个平衡因子,用一个哈希表记录0~i位置的平衡因子,我们可以知道对于一段数组arr[0:j],如果它的平衡因子为balance,且存在某个前面的位置i<j,满足arr[0:i]的平衡因子也是balance,这就说明子数组arr[i+1:j]的正数和负数数量相等,平衡因子归零,可以更新一次长度。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.HashMap;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine().trim());
        String[] strArr = br.readLine().split(" ");
        int[] arr = new int[n];
        for(int i = 0; i < n; i++) {
            arr[i] = Integer.parseInt(strArr[i]);
        }
        int balance = 0, maxLen = 0;
        HashMap<Integer, Integer> map = new HashMap<>();
        map.put(0, -1);
        for(int i = 0; i < n; i++){
            if(arr[i] == 0) continue;
            balance += arr[i] > 0? 1: -1;
            if(map.containsKey(balance)){
                maxLen = Math.max(maxLen, i - map.get(balance));
            }else{
                map.put(balance, i);
            }
        }
        System.out.println(maxLen);
    }
}

发表于 2021-12-09 17:18:52 回复(0)

C++直接处理输入数据


一个系列的题目,正数变1,负数变-1,找和为0的最长子串
问题不大,贴个代码摸个鱼
#include <bits/stdc++.h>
using namespace std;

int main(){
    int n;
    cin>>n;
    vector<int> v(n+1, 0);
    unordered_map<int,int> m;
    m[0] = 0;
    int res = 0;
    for(int i=1;i<=n;++i){
        cin>>v[i];
        if(v[i] > 0)
            v[i] = 1 + v[i-1];
        else if(v[i] < 0)
            v[i] = -1 + v[i-1];
        else
            v[i] = v[i-1];
        if(m.find(v[i]) != m.end())
            res = max(res, i-m[v[i]]);
        if(m.find(v[i]) == m.end())
            m[v[i]] = i;
    }
    cout<<res;
    return 0;
}



发表于 2020-07-18 11:26:24 回复(0)
#include <bits/stdc++.h>
using namespace std;

int main(){
    int n;
    cin>>n;
    int a[n], Max=0;
    map<int,int> M;
    M[0] = -1;
    for(int i=0,s=0;i<n;i++){
        cin>>a[i];
        if(a[i]>0)
            s++;
        else if(a[i]<0)
            s--;
        if(M.find(s)!=M.end())
            Max = max(Max, i-M[s]);
        else
            M[s] = i;
    }
    cout<<Max<<endl;
    return 0;
}

发表于 2020-02-04 02:23:26 回复(1)
arr = list(map(int,input().split()))

sum = 0 
length = 0
tmp_dict = {0:-1}

for i in range(len(arr)):
    if arr[i] > 0: sum += 1
    if arr[i] < 0: sum -= 1
    if sum not in tmp_dict:
        tmp_dict[sum] = i
    if sum in tmp_dict:
        length = max(length,i-tmp_dict[sum])
print(length)
发表于 2023-06-15 10:48:19 回复(0)
import java.util.*;
public class Main{
    public static void main(String[]args){
        Scanner sc = new Scanner(System.in);
        
        
        int n = sc.nextInt(); 
        int [] arr = new int[n];
        for(int i=0;i<n;i++){
            arr[i] = sc.nextInt();
        }
      //  int[][] ma = new int[n][2];
        //map[i][0]记录从0到i的子数组的正数个数
        //map[i][1]记录从0到i的子数组的负数的个数
        
        //map[j][0]...
        //map[j][1]....
        
        
        //map[j][0]-map[i][0]表示从i到j的正数个数
        //map[j][1]-map[i][1]表示从i到j的负数个数
        
        // map[j][1]-map[j][0] = map[i][1]-map[i]-[0];
        HashMap<Integer,Integer> map = new HashMap<>();
        map.put(0,-1);//表示正数和负数的差为0的下标为-1;0 则个数为 0-(-1) =1;
        //我们取最大值
        int cha = 0;//刚开始的正数和负数个数的差值
        int max = 0;
        for(int i=0;i<n;i++){
           if(arr[i]>0){
               cha++;//正数多1个
           }else if(arr[i]<0){
               cha--;//cha为正数-负数的差值
           }
            if(map.get(cha)!=null){
                if(cha==0){//如果正数个数=负数个数,则整个数组都是正数=负数
                    max = Math.max(max,i);
                }else{//否则 只有i+1到j是符合的正数=负数
                    int end = map.get(cha);
                    max = Math.max(max,i-end);
                }
            }
            if(map.get(cha)==null){
                map.put(cha,i);
            }
            
        }
        
        System.out.println(max);
    }
}

发表于 2021-09-20 22:06:09 回复(0)
c++,可以通过。
#include<iostream>
#include<vector>
#include<map>
using namespace std;
int main()
{
    int N,sum=0,res=0;
    cin>>N;
    vector<int> arr(N,0);
    for(int i=0;i<N;++i) cin>>arr[i];
    for(int i=0;i<N;++i){
        if(arr[i]>0)  arr[i]=1;
        else if(arr[i]<0) arr[i]=-1;
    }
    map<int,int> map;
    map[0]=-1;
    for(int i=0;i<N;++i){
        sum+=arr[i];
        if(map.find(sum)==map.end()) map[sum]=i;
        else{
            res=max(res,i-map[sum]);
        }
    }
    cout<<res<<endl;
}

发表于 2021-07-13 10:24:03 回复(0)
import java.io.*;
import java.util.*;

public class Main{
    
    public static void main(String[] args) throws IOException{
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String[] str = in.readLine().split(" ");
        int n = Integer.parseInt(str[0]);
        int[] arr = new int[n];
        int j = 0;
        for(String i:in.readLine().split(" ")){
            arr[j++] = Integer.parseInt(i);
        }
        System.out.println(getLength(arr));
        
    }
    
    static int getLength(int[] arr){
        int len = 0;
        int sum = 0;
        HashMap<Integer,Integer> map = new HashMap<>();
        map.put(0,-1);
        
        for(int i=0;i<arr.length;i++){
            if(arr[i]>0)
                arr[i] = 1;
            if(arr[i]<0)
                arr[i] = -1;
        }
        
        for(int i=0;i<arr.length;i++){
            sum += arr[i];
            if(!map.containsKey(sum))
                map.put(sum,i);
            if(map.containsKey(sum))
                len = Math.max(i - map.get(sum),len);
        }
        
        return len;
    }
}

发表于 2021-03-15 14:18:51 回复(0)
看大佬们的解题代码 实在看不出动态规划的影子,为啥这题有动态规划的标签
发表于 2020-09-03 22:00:19 回复(0)
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int len = Integer.parseInt(br.readLine().trim());
        
        int[] arr = new int[len];
        String[] rawData = br.readLine().trim().split(" ");
        for (int i = 0; i < len; i++) {
            int tmp = Integer.parseInt(rawData[i]);
            if(tmp > 0) {
                arr[i] = 1;
            } else if (tmp < 0) {
                arr[i] = -1;
            }
        }
        
        // 求符合条件的子数组长度, 和为0的最长子数组长度
        HashMap<Integer, Integer> map = new HashMap<>();
        map.put(0, -1);
        int max = 0, currentSum = 0;
        for (int i = 0; i < len; i++) {
            currentSum += arr[i];
            if (map.containsKey(currentSum)) {
                int j = map.get(currentSum);
                max = Math.max(i - j, max);
            }
            if (!map.containsKey(currentSum)) {
                map.put(currentSum, i);
            }
        }
        
        System.out.print(max);
        
    }
}

发表于 2020-06-27 15:33:28 回复(0)
import java.io.*;

public class Main {
	
	public static void main(String[] args) {
		
		BufferedReader br = null;		
		int n = 0;
		String nums = null;
		
		try {
			br = new BufferedReader(new InputStreamReader(System.in));
			n = Integer.parseInt(br.readLine());
			nums = br.readLine();
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				if (br.readLine() != null)
				br.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		int[] numbers = new int[n];		
		
		boolean hasZero = false;
		
		int negtiveCounter = 0;
		int normalCounter = 0;
		int len = 0;
		
		String[] arr = nums.split(" ");
		
		System.out.println("arr.length=" +arr.length);
		
		if (arr.length == n) {
			for ( int i = 0; i < arr.length; i++) {
				//遍历数组分别统计正数,负数的个数,并标记是否含“0”元素
				numbers[i] = Integer.parseInt(arr[i]);
				if (numbers[i] < 0)
					negtiveCounter++;
				else if (numbers[i] > 0) {
					normalCounter++;
				} else
					hasZero = true;
			}
		} else {
			System.exit(-1);
		}
		
		//统计:取正数个数和负数个数的最小值,这个值就是正数负数一一对应的个数,再考虑数组是否含“0”
		if(negtiveCounter == 0 || normalCounter==0) {
			len = 0;
		} else {
			if (hasZero) 
				len = 2*Math.min(negtiveCounter, normalCounter)+1;
			else
				len = 2*Math.min(negtiveCounter, normalCounter);
		}
		
		System.out.println(len);
	}
	
}

测试未通过,这思路哪里有问题,求指点
发表于 2019-12-27 23:25:43 回复(1)
import java.util.*;

public class Main {
	public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		
		int n = scanner.nextInt();
        int[] arr = new int[n];
        for(int i=0;i<n;i++){
            arr[i] = scanner.nextInt();
        }
       
         Map<Integer,Integer> map = new HashMap<>();
        //key为 正数个数-负数个数
        map.put(0,-1);
        int key = 0,maxLen = 0;
        for(int i=0;i<n;i++){
            key += arr[i]==0?0:arr[i]/Math.abs(arr[i]);
            
            if(map.containsKey(key)){
                maxLen = Math.max(maxLen,i-map.get(key));
            }else{
                map.put(key,i);
            }
            
        }
        
        System.out.print(maxLen);
		
	}
}

发表于 2019-10-24 13:08:04 回复(0)
N= int(input())
arr = list(map(int,input().split()))

sums = 0
dic = {0:-1}
ans = 0
for i in range(N):
    if arr[i]>0:
        sums += 1
    elif arr[i]<0:
        sums -= 1
    if sums not in dic:
        dic[sums] = i
    else:
        ans = max(ans,i-dic[sums])
print(ans)

发表于 2019-10-08 20:40:39 回复(0)
// 与上一题类似,这里相当于将正数看做1,负数看做-1。计算总和为0的最长子数组长度。
import java.util.Scanner;
import java.util.HashMap;
public class Main{
    public static void main(String args[]){
        Scanner sc = new Scanner(System.in);
        HashMap<Integer,Integer> map = new HashMap<>();
        int N = sc.nextInt();
        int sum = 0, val = 0, len = 0;
        for(int i = 0; i < N ; i++){
            val = sc.nextInt();
            if(val > 0)
                sum ++;
            else if(val < 0)
                sum--;
            
            if(sum == 0){ // 如果sum刚好为0则数组[0~i]为最长数组。这里相当于预先在map中加入(0,-1)
                len = i + 1;
                continue;
            }
            
            if(map.containsKey(sum)){
                len = len > i - map.get(sum) ? len : i - map.get(sum);
            }else{
                map.put(sum ,i);
            }
        }
        System.out.println(len);
        sc.close();
    }
}

发表于 2019-09-06 22:47:23 回复(0)
帮忙看看有啥错
#include<iostream>
using namespace std;
int main()
{
    int arr[100000],n;
    cin>>n;
    if(0<n && n<=100000){
        for(int i=0;i<n;i++){
          cin>>arr[i];
    }
    int z=0,f=0,num=0;
    for(int i=0;i<n;i++){
        if(arr[i]>0){
            z++;
        }
        if(arr[i]<0){
            f++;
        }
        if(z==f){
            num=i;
        }
    }
        int x;
       x=num+1;
    cout<<x<<endl;
    }
    return 0;
}
发表于 2019-09-03 20:53:50 回复(0)
package com.hhdd.leetcode;

import java.util.HashMap;
import java.util.Scanner;

public class LargestNumNativeEqualsPositive {

    /*public static int func1(int[] arr) {
        //help1用来存放i到j上负数的个数,help2用来存放i到j上正数的个数
        int[][] help1 = new int[arr.length][arr.length];
        int[][] help2 = new int[arr.length][arr.length];
        //遍历生成从i到j上负数、正数的个数,并存在help1、help2
        for (int i = 0; i < arr.length; i++) {
            //count1用来记录负数的个数,count2用来记录正数的个数
            int count1 = 0;
            int count2 = 0;
            for (int j = i; j < arr.length; j++) {
                if (arr[j] < 0) {
                    help1[i][j] = ++count1;
                    help2[i][j] = count2;
                } else if (arr[j] > 0) {
                    help2[i][j] = ++count2;
                    help1[i][j] = count1;
                } else {
                    help1[i][j] = count1;
                    help2[i][j] = count2;
                }
            }
        }
        int ans = 0;
        for (int i = 0; i < arr.length; i++) {
            for (int j = i; j < arr.length; j++) {
                if (help1[i][j] != 0 && (help1[i][j] == help2[i][j])) {
                    ans = (j - i + 1) > ans ? (j - i + 1) : ans;
                }
            }
        }

        return ans;
    }*/

    public static int maxLength(int[] arr, int k) {

        if (arr == null || arr.length == 0) {
            return 0;
        }
        //map中的key用来记录累加和,对应的value是这个累加和第一次出现的下标
        HashMap<Integer, Integer> map = new HashMap<>();
        //这个很关键的,当数组从0开始的累加和是k时就会用到,所以一定要保证<0,-1>已经在map中了,这个当前i个和等于k时就用到了
        //当{1,2,3} k = 3时就可以体现出来,好好体会!
        map.put(0, -1);
        //sum用来记录数组前i项的和,length用来记录最后的答案
        int sum = 0, length = 0;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
            //看看map中是否已经存过sum-k这个累加和了,有的话从那个值到目前的i就是length了
            if (map.containsKey(sum - k)) {
                int j = map.get(sum - k);
                length = i - j > length ? i - j : length;
            }
            if (!map.containsKey(sum)) {
                map.put(sum, i);
            }
        }
        return length;
    }



    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] arr = new int[n];
        for (int i = 0; i < arr.length; i++) {
            int temp = scanner.nextInt();
            if(temp<0){
                arr[i] = -1;
            }else if(temp>0){
                arr[i] = 1;
            }else {
                arr[i] = 0;
            }
        }
        int ans  = maxLength(arr,0);
        System.out.println(ans);
    }


}

发表于 2019-09-01 00:24:03 回复(0)
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;
int getMaxLen(vector<int>&vec, int k)
{
	unordered_map<int, int> hashMap;
	hashMap[0] = -1;
	int sum = 0;
	int maxLen = 0;
	for (int i = 0; i < vec.size(); i++)
	{
		sum += vec[i];
		if (hashMap.find(sum) == hashMap.end())hashMap[sum] = i;

		auto tmp = hashMap.find(sum - k);
		if (tmp != hashMap.end())
		{
			int len = i - tmp->second;
			if (maxLen < len)maxLen = len;
		}
	}
	return maxLen;
}

int main()
{
	int n;
	scanf("%d", &n);
	vector<int>vec(n);
	for (int i = 0; i < n; i++)
	{
		int tmp;
		scanf("%d", &tmp);
		vec[i] = tmp == 0 ? 0 : (tmp > 0 ? 1 : -1);
	}
	printf("%d", getMaxLen(vec, 0));
}

发表于 2019-08-10 12:56:34 回复(0)

问题信息

上传者:小小
难度:
16条回答 3204浏览

热门推荐

通过挑战的用户

查看代码