📢前言
🌲 每天打卡一道算法题,既是一个学习过程,又是一个分享的过程😜 🌲 提示:本专栏解题 编程语言一律使用 C# 和 Java 两种进行解题 🌲 要保持一个每天都在学习的状态,让我们一起努力成为算法大神吧🧐! 🌲 今天是力扣算法题持续打卡第53天🎈!
🌲原题样例:两个数组的交集
给定两个数组,编写一个函数来计算它们的交集。
示例:
输入:nums1 = [ 1 , 2 , 2 , 1 ] , nums2 = [ 2 , 2 ]
输出:[ 2 ]
示例 2:
输入:nums1 = [ 4 , 9 , 5 ] , nums2 = [ 9 , 4 , 9 , 8 , 4 ]
输出:[ 9 , 4 ]
说明:
输出结果中每个元素出现的次数,应与元素在两个数组中出现次数的最小值一致。 我们可以不考虑输出结果的顺序。
🌻C#方法:字典
使用Dictionary字典操作,先把第一个数组遍历进字典,然后再同第二个数组做判定即可!
代码:
public class Solution {
public int [ ] Intersect ( int [ ] nums1, int [ ] nums2) {
var dic = new Dictionary< int , int > ( ) ;
List< int > list = new List< int > ( ) ;
foreach ( int n in nums1)
{
if ( dic. ContainsKey ( n) )
dic[ n] ++ ;
else
dic. Add ( n, 1 ) ;
}
foreach ( int n in nums2)
{
if ( dic. ContainsKey ( n) && dic[ n] > 0 )
{
dic[ n] -- ;
list. Add ( n) ;
}
}
return list. ToArray ( ) ;
}
}
执行结果
通过
执行用时:128 ms,在所有 C# 提交中击败了99.61 % 用户
内存消耗:40.4 MB,在所有 C# 提交中击败了5.26 % 的用户
🌻Java 方法:哈希
思路解析
由于同一个数字在两个数组中都可能出现多次,因此需要用哈希表存储每个数字出现的次数。
对于一个数字,其在交集中出现的次数等于该数字在两个数组中出现次数的最小值。
首先遍历第一个数组,并在哈希表中记录第一个数组中的每个数字以及对应出现的次数,然后遍历第二个数组,对于第二个数组中的每个数字,如果在哈希表中存在这个数字,则将该数字添加到答案,并减少哈希表中该数字出现的次数。
为了降低空间复杂度,首先遍历较短的数组并在哈希表中记录每个数字以及对应出现的次数,然后遍历较长的数组得到交集。
代码:
class Solution {
public int [ ] intersect ( int [ ] nums1, int [ ] nums2) {
if ( nums1. length > nums2. length) {
return intersect ( nums2, nums1) ;
}
Map < Integer , Integer > map = new HashMap < Integer , Integer > ( ) ;
for ( int num : nums1) {
int count = map. getOrDefault ( num, 0 ) + 1 ;
map. put ( num, count) ;
}
int [ ] intersection = new int [ nums1. length] ;
int index = 0 ;
for ( int num : nums2) {
int count = map. getOrDefault ( num, 0 ) ;
if ( count > 0 ) {
intersection[ index++ ] = num;
count-- ;
if ( count > 0 ) {
map. put ( num, count) ;
} else {
map. remove ( num) ;
}
}
}
return Arrays . copyOfRange ( intersection, 0 , index) ;
}
}
执行结果
通过
执行用时:3 ms,在所有 Java 提交中击败了45.01 % 的用户
内存消耗:38.8 MB,在所有 Java 提交中击败了5.86 % 的用户
复杂度分析
时间复杂度:O ( m+ n )
空间复杂度:O ( m+ n )
Java方法二:排序 + 双指针
如果两个数组是有序的,则可以使用双指针的方法得到两个数组的交集。
首先对两个数组进行排序,然后使用两个指针遍历两个数组。
可以预见的是加入答案的数组的元素一定是递增的,为了保证加入元素的唯一性,我们需要额外记录变量 pre
表示上一次加入答案数组的元素。
初始时,两个指针分别指向两个数组的头部。每
次比较两个指针指向的两个数组中的数字,如果两个数字不相等,则将指向较小数字的指针右移一位,如果两个数字相等,且该数字不等于pre
,将该数字添加到答案并更新 pre
变量,同时将两个指针都右移一位。
当至少有一个指针超出数组范围时,遍历结束。
代码
class Solution {
public int [ ] intersect ( int [ ] nums1, int [ ] nums2) {
Arrays. sort ( nums1) ;
Arrays. sort ( nums2) ;
int length1 = nums1. length, length2 = nums2. length;
int [ ] intersection = new int [ Math. min ( length1, length2) ] ;
int index1 = 0 , index2 = 0 , index = 0 ;
while ( index1 < length1 && index2 < length2) {
if ( nums1[ index1] < nums2[ index2] ) {
index1++ ;
} else if ( nums1[ index1] > nums2[ index2] ) {
index2++ ;
} else {
intersection[ index] = nums1[ index1] ;
index1++ ;
index2++ ;
index++ ;
}
}
return Arrays. copyOfRange ( intersection, 0 , index) ;
}
}
执行结果
通过
执行用时:2 ms,在所有 Java 提交中击败了77.89 % 的用户
内存消耗:38.8 MB,在所有 Java 提交中击败了16.56 % 的用户
复杂度分析
时间复杂度:O ( mlogm + nlogn )
空间复杂度:O ( logm + logn )
💬总结
今天是力扣算法题打卡的第五十三天! 文章采用 C#
和 Java
两种编程语言进行解题 一些方法也是参考力扣大神写的,也是边学习边分享,再次感谢算法大佬们 那今天的算法题分享到此结束啦,明天再见!