题目描述:
给定两个数组,编写一个函数来计算它们的交集。
示例 1:
输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]
示例 2:
输入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出: [4,9]
说明:
- 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。
- 我们可以不考虑输出结果的顺序。
这道题思路很奇特用到了dict,有人可能说为什么不用set,上一道题是用set判断子集的,但是这道题多了一句话:输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。这句话说明了最后的结果中可以有重复元素出现,这样的话就不能使用set进行操作,一时模棱两可,但是仔细观察我们就能发现,这道题就比第一道题那个最后结果(是唯一的这个条件)只多了一部计算次数,就是计算这个结果在这两个数组中出现的次数,需要一致才行,例如一个数组中出现2次,一个数组中出现3次,选择2次的这个结果。
具体思路是:多加了记录元素个数的功能,我们可以使用map实现它。这里注意,键为第一个数组元素,值为元素出现的次数。然后遍历数组二,判断是否在map中,在的话就证明这两个元素相同,然后判断次数,出现了几次,就在新数组中添加几次。(一边添加,一边得让map中存储的数组1的次数减1,当减为0时证明数组1没这个元素了,结束添加。)
代码如下:
public static void main(String[] args){
int [] nums1 = new int[]{1,2,2,1};
int [] nums2 = new int[]{2,2};
// 定义一个字典(哈希map),重点(键为元素,值为出现的次数),因为题目要求:
// 每个元素出现的次数,应与元素在两个数组中出现的次数一致
Map<Integer,Integer> map = new HashMap <> ( );
// list存储最后的结果
List<Integer> list = new ArrayList <> ( );
// 遍历第一个数组,将数组元素添加到map中,键为数组元素,值为出现的次数,
for (int i= 0;i<nums1.length;i++){
// 如果数组元素不再map中,则将此元素添加进去,给定次数为1.
if (!map.containsKey ( nums1[i] )){
map.put (nums1[i],1);
}else {//假如数组元素存在,则将次数加1,不断循环,这样,map就是带有计数功能的存储数组1的结构
map.put ( nums1[i],map.get ( nums1[i])+1 );
}
}
// 思路很简单,就是判断,数组二的元素是否和数组1的元素相等,因为数组一中的元素全部做了map的键,也就转变为判断数组2中的元素是否与map的键相同,也就是map是否存在这样一个键,存在时,就证明这个元素1,2,数组中都有,就添加进list(保存最后的结果)中,然后重要的一点就是让这个相同元素的次数减少1,,因为要满足共同元素在两个数组中出现的次数相同,当次数为0时,证明数组1没这个元素了,这个元素最大的次数就是map中的键为0时。这个很好理解,谁出现的少谁就决定最后的共同元素的次数。(所以要加个判断,当对应元素次数不大于0时停止向list中添加,这时nums1中没元素了。)
for (int j =0;j<nums2.length;j++){
if (map.containsKey ( nums2[j] )&&map.get (nums2[j])>0) {
list.add (nums2[j]);
map.put ( nums2[j],map.get ( nums2[j] )-1 );
}
}
System.out.println(list);
执行结果:
执行用时:
总结:这道题用到了一个结构map,用来存储数组1的元素和出现的次数,来和数组而比较,注意的是map的键值的选择。
2019-3-13