LeetCode 454 四数相加II 2023.10.31
题目链接 代码随想录讲解[链接] 题意:输入4个长度都为n的数组,判断任意四个元素分别来自4个不同的数组,求其和为0的组合次数 方法:
结合了1两数之和和242有效字母异位词的方法 1两数之和考虑了两数之和等于一个目标值 ,用unordered_map 结构判断当前遍历数组中元素与(target-当前值是否在无序映射中,在则记录答案,不在则将当前遍历元素插入无序映射中,第一题中是两个数的判断,本题是4个判断,所以先用unordered_map 分别记录第一个和第二个数组、第三个和第四个数组中元素求和并记录该和组合的次数 (这里参考了242有效字母异位词的方法),最后判断一个映射中的每个元素的相反数(和为0)是否在第二个映射中存在,如果存在则记录两个和的组合次数乘积,累计的次数即为题目答案
int fourSumCount ( vector< int > & nums1, vector< int > & nums2, vector< int > & nums3, vector< int > & nums4) {
int num = 0 ;
unordered_map< int , int > s1s2;
unordered_map< int , int > s3s4;
for ( int i = 0 ; i < nums1. size ( ) ; i++ )
{
for ( int j = 0 ; j < nums2. size ( ) ; j++ )
{
s1s2[ nums1[ i] + nums2[ j] ] ++ ;
s3s4[ nums3[ i] + nums4[ j] ] ++ ;
}
}
for ( unordered_map< int , int > :: iterator i = s1s2. begin ( ) ; i != s1s2. end ( ) ; i++ )
{
if ( s3s4. find ( - ( i-> first) ) != s3s4. end ( ) )
num += i-> second * s3s4. find ( - ( i-> first) ) -> second;
}
return num;
}
LeetCode 383 赎金信 2023.10.31
题目链接 代码随想录讲解[链接] 题意:输入两个字符串,判断其中第一个字符串的所有字符是否存在于第二个字符串中,包括字符和字符个数 方法:典型的“键”(字符)“值”(出现次数)对 问题,可以用哈希表 完成,这里索引最大26个,所以优先选用数组 ,记录第一个字符串中每个字符的种类及其出现次数;然后遍历第二个字符串中的每个字符,当对应元素数组出现次数不为0时其值递减;最后遍历数组值是否都为0,存在不为0的说明第二个数组中有缺少
bool canConstruct ( string ransomNote, string magazine) {
vector< int > result ( 26 ) ;
for ( int i = 0 ; i < ransomNote. size ( ) ; i++ )
result[ ransomNote[ i] - 'a' ] ++ ;
for ( int i = 0 ; i < magazine. size ( ) ; i++ )
{
if ( result[ magazine[ i] - 'a' ] != 0 )
result[ magazine[ i] - 'a' ] -- ;
}
for ( int i = 0 ; i < 26 ; i++ )
{
if ( result[ i] != 0 )
return false ;
}
return true ;
}
LeetCode 15 三数之和 2023.10.31
题目链接 代码随想录讲解[链接] 题意:输入一个数组,求该数组中任意不同索引的三个数 和为0,求这样的子数组集合 方法:因为要求最终的数组,所以此处再用哈希表法考虑较多,不太合适;此处将数组排序后选用双指针法再遍历整个数组,需要注意两次去重,建议看代码随想录讲解视频[链接] 或下面代码及注释
vector< vector< int >> threeSum ( vector< int > & nums) {
vector< vector< int >> result;
sort ( nums. begin ( ) , nums. end ( ) ) ;
int left = 0 , right = nums. size ( ) - 1 ;
for ( int i = 0 ; i < nums. size ( ) - 1 ; i++ )
{
if ( nums[ i] > 0 )
return result;
if ( i > 0 && ( nums[ i- 1 ] == nums[ i] ) )
continue ;
left = i+ 1 ;
right = nums. size ( ) - 1 ;
while ( left < right)
{
if ( ( nums[ i] + nums[ left] + nums[ right] ) > 0 )
{
right-- ;
continue ;
}
else if ( ( nums[ i] + nums[ left] + nums[ right] ) < 0 )
{
left++ ;
continue ;
}
else
{
vector< int > temp;
temp. push_back ( nums[ i] ) ;
temp. push_back ( nums[ left] ) ;
temp. push_back ( nums[ right] ) ;
result. push_back ( temp) ;
while ( left < nums. size ( ) - 1 && nums[ left] == nums[ left+ 1 ] )
left++ ;
while ( right > 0 && nums[ right] == nums[ right- 1 ] )
right-- ;
left++ ;
right-- ;
}
}
}
return result;
}
LeetCode 18 四数之和 2023.10.31
题目链接 代码随想录讲解[链接] 题意:输入一个数组,求该数组中任意不同索引的四个数 和为目标值target,求这样的子数组集合 方法:延续15题求三数之和方法,加一层循环遍历数组固定一个数 ,求剩下三数之和为某一固定值,注意此时target可能为负数或者极大值 ,剪枝以及定义变量类型需注意
vector< vector< int >> fourSum ( vector< int > & nums, int target) {
vector< vector< int >> result;
sort ( nums. begin ( ) , nums. end ( ) ) ;
int left = 0 , right = nums. size ( ) - 1 ;
for ( int i = 0 ; i < nums. size ( ) - 1 ; i++ )
{
if ( target >= 0 && nums[ i] > target)
return result;
if ( i > 0 && nums[ i- 1 ] == nums[ i] )
continue ;
long temp = target - nums[ i] ;
for ( int j = i+ 1 ; j < nums. size ( ) - 1 ; j++ )
{
if ( temp >= 0 && nums[ j] > temp)
break ;
if ( j > i+ 1 && nums[ j- 1 ] == nums[ j] )
continue ;
left = j+ 1 ;
right = nums. size ( ) - 1 ;
while ( left < right)
{
if ( ( long ) nums[ j] + nums[ left] + nums[ right] > temp)
{
right-- ;
continue ;
}
else if ( ( long ) nums[ j] + nums[ left] + nums[ right] < temp)
{
left++ ;
continue ;
}
else
{
result. push_back ( vector< int > { nums[ i] , nums[ j] , nums[ left] , nums[ right] } ) ;
while ( left < nums. size ( ) - 1 && nums[ left] == nums[ left+ 1 ] )
left++ ;
while ( right > j && nums[ right] == nums[ right- 1 ] )
right-- ;
left++ ;
right-- ;
}
}
}
}
return result;
}