初级算法之给定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
示例 2:

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]

说明:

输出结果中每个元素出现的次数,应与元素在两个数组中出现次数的最小值一致。
我们可以不考虑输出结果的顺序。
进阶:

如果给定的数组已经排好序呢?你将如何优化你的算法?
如果 nums1 的大小比 nums2 小很多,哪种方法更优?
如果 nums2 的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/intersection-of-two-arrays-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
在不考虑数组已经排好序的情况下,可以使用哈希表来得出数组交集
为了降低空间复杂度,我们首先遍历长度较短的数组,用数组的每一个元素值和它对于出现的次数以键值对的形式存入数组,在这里我介绍一个map里面的方法map.getOrDefault(num, 0);意思就是当Map集合中有这个key时,就使用这个key对于的value值,如果没有这个key就使用默认值defaultValue
所以在map中如果没有数组元素,他会自动设置为0,如果有,就取出键所对应的值然后加一。
然后再根据和第二个数组对比,如果第二个数组的元素在哈希表中存在就写入交集中。
对应代码如下
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 i : nums1){
int count=map.getOrDefault(i,0)+1;
map.put(i,count);
}
int []result =new int[nums1.length];
int acc=0;
for(int i:nums2){
int count=map.getOrDefault(i,0);
if(count>0){
result[acc++]=i;
count–;
if(count>0){
map.put(i,count);
}else{
map.remove(i);
}
}
}
return Arrays.copyOfRange(result, 0, acc);
}
}
复杂度分析
时间复杂度:O(m+n)其中 m 和 n 分别是两个数组的长度。
空间复杂度:O(min(m,n)),其中 m 和 n 分别是两个数组的长度。
第二种方法就是当数组已经排好序的情况下,利用双指针进行求解
数组在排好序的情况下,各个元素都是有序的,所以指针分别指向两个数组的第一个元素,如果相同,存入结果数组中,两个指针分别向右移动一个位置,如果不相同,看指针指向的元素哪个小一点,然后把指向较小元素的指针向右移动一个位置,看是否能够找到与较大元素匹配的元素
代码如下:
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
Arrays.sort(nums1);
Arrays.sort(nums2);
int Next1=0,Next2=0;
int result[]=new int[nums1.length],count=0;
while(Next1<nums1.length&&Next2<nums2.length){
if(nums1[Next1]==nums2[Next2]){
result[count++]=nums1[Next1];
Next1++;
Next2++;
}else {
if(nums1[Next1]<nums2[Next2]){
Next1++;
}else if(nums1[Next1]>nums2[Next2]){
Next2++;
}
}
}
return Arrays.copyOfRange(result,0,count);
}
}
时间复杂度:
O(mlogm+nlogn),其中m和n分别是两个数组的长度。对两个数组进行排序的时间复杂度是O(mlogm+nlogn),遍历两个数组的时间复杂度是 O(m+n),因此总时间复杂度是O(mlogm+nlogn)。
空间复杂度:
O(min(m,n)),其中 m 和 n 分别是两个数组的长度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值