程序员代码面试指南第二版 125.未排序数组中累加和为给定值的最长子数组长度
题目描述
给定一个无序数组arr, 其中元素可正、可负、可0。给定一个整数k,求arr所有子数组中累加和为k的最长子数组长度
输入描述:
第一行两个整数N, k。N表示数组长度,k的定义已在题目描述中给出
第二行N个整数表示数组内的数
输出描述:
输出一个整数表示答案
示例1
输入
5 0
1 -2 1 1 1
输出
3
第一次做; 核心:sum的含义:子数组arr[i,j]的累加和; a-b=k等价于a-k=b; 哈希表中只记录前缀和最早出现的索引; 为了记录arr[0,i]这个子数组的情况,需要先往哈希表中插入(0,-1)这个记录, 这样当sum=k时,也就是sum-k=0时,能够获取子数组arr[0,i]的长度
import java. util. Scanner;
import java. util. HashMap;
public class Main {
public static void main ( String[ ] args) {
Scanner sc = new Scanner ( System. in) ;
String[ ] str = sc. nextLine ( ) . split ( " " ) ;
int n = Integer. parseInt ( str[ 0 ] ) ;
int k = Integer. parseInt ( str[ 1 ] ) ;
str = sc. nextLine ( ) . split ( " " ) ;
int [ ] arr = new int [ n] ;
for ( int i= 0 ; i< n; i++ ) {
arr[ i] = Integer. parseInt ( str[ i] ) ;
}
HashMap< Integer, Integer> map = new HashMap < > ( ) ;
map. put ( 0 , - 1 ) ;
int sum = 0 , len= 0 ;
for ( int i= 0 ; i< n; i++ ) {
sum = sum + arr[ i] ;
if ( map. containsKey ( sum- k) ) {
len = Math. max ( len, i- map. get ( sum- k) ) ;
}
if ( ! map. containsKey ( sum) )
map. put ( sum, i) ;
}
System. out. print ( len) ;
}
}
125补充题1
题目描述
给定一个无序数组arr,其中元素可正、可负、可0。求arr所有子数组中正数与负数个数相等的最长子数组的长度。
[要求]
时间复杂度为O(n),空间复杂度为O(n)
输入描述:
第一行一个整数N,表示数组长度
接下来一行有N个数表示数组中的数
输出描述:
输出一个整数表示答案
示例1
输入
5
1 -2 1 1 1
输出
2
第一次做; 把正数看成1, 负数看成-1, 0不变, 还是求累加和, 正数个数和负数个数相等,也就是k=0; 个数相等问题转换成累加和,进而使用哈希表前缀和方法, 提前明确k的值
import java. util. Scanner;
import java. util. HashMap;
public class Main {
public static void main ( String[ ] args) {
Scanner sc = new Scanner ( System. in) ;
String[ ] str = sc. nextLine ( ) . split ( " " ) ;
int n = Integer. parseInt ( str[ 0 ] ) ;
str = sc. nextLine ( ) . split ( " " ) ;
int [ ] arr = new int [ n] ;
for ( int i= 0 ; i< n; i++ ) {
arr[ i] = Integer. parseInt ( str[ i] ) ;
}
HashMap< Integer, Integer> map = new HashMap < > ( ) ;
map. put ( 0 , - 1 ) ;
int sum = 0 , len= 0 ;
for ( int i= 0 ; i< n; i++ ) {
if ( arr[ i] > 0 )
sum = sum + 1 ;
else if ( arr[ i] < 0 )
sum = sum - 1 ;
if ( map. containsKey ( sum) ) {
len = Math. max ( len, i- map. get ( sum) ) ;
}
if ( ! map. containsKey ( sum) )
map. put ( sum, i) ;
}
System. out. print ( len) ;
}
}
125补充题2
题目描述
给定一个无序数组arr,其中元素只能是1或0。求arr所有的子数组中0和1个数相等的最长子数组的长度
[要求]
时间复杂度为O(n),空间复杂度为O(n)
输入描述:
第一行一个整数N,表示数组长度
接下来一行有N个数表示数组中的数
输出描述:
输出一个整数表示答案
示例1
输入
5
1 0 1 0 1
输出
4
第一次做; 核心:个数相等问题转换成累加和, 进而用哈希表前缀和解决
import java. util. Scanner;
import java. util. HashMap;
public class Main {
public static void main ( String[ ] args) {
Scanner sc = new Scanner ( System. in) ;
String[ ] str = sc. nextLine ( ) . split ( " " ) ;
int n = Integer. parseInt ( str[ 0 ] ) ;
str = sc. nextLine ( ) . split ( " " ) ;
int [ ] arr = new int [ n] ;
for ( int i= 0 ; i< n; i++ ) {
arr[ i] = Integer. parseInt ( str[ i] ) ;
}
HashMap< Integer, Integer> map = new HashMap < > ( ) ;
map. put ( 0 , - 1 ) ;
int sum = 0 , len= 0 ;
for ( int i= 0 ; i< n; i++ ) {
if ( arr[ i] == 0 )
sum = sum - 1 ;
else
sum = sum + 1 ;
if ( map. containsKey ( sum) ) {
len = Math. max ( len, i- map. get ( sum) ) ;
}
if ( ! map. containsKey ( sum) )
map. put ( sum, i) ;
}
System. out. print ( len) ;
}
}