持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情
一、题目描述:
给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。
示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的
提示:
- 1 <= nums1.length, nums2.length <= 1000
- 0 <= nums1[i], nums2[i] <= 1000
二、思路分析:
目标:两个数组中的重复元素,返回数据只包含重复值一次。
思路:
1、两个数组重排序后,从小到大(从大到小)遍历一次,即可找出;
2、类似于桶标记法,将数组元素标记(只需要返回重复值的一次,若要求多次,需计数),采用位标记法,将元素标记为位,而后再将标记数组进行与操作(相当于找到重复值的索引),最后将标记的方式逆变换,得出元素;
三、AC 代码:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
char *mark_arry1,*mark_arry2;
int index,r_size;
//max set.
mark_arry1 = (char *)malloc(sizeof(char)*((1000 + 7)>>3));
mark_arry2 = (char *)malloc(sizeof(char)*((1000 + 7)>>3));
memset(mark_arry1,0,((1000 + 7)>>3));
memset(mark_arry2,0,((1000 + 7)>>3));
//for array1
for(index = 0;index < nums1Size;index++)
mark_arry1[nums1[index]>>3] |= 1<<(nums1[index]%8);
//for array2
for(index = 0;index < nums2Size;index++)
mark_arry2[nums2[index]>>3] |= 1<<(nums2[index]%8);
//find repeat.
for(index = 0;index < ((1000 + 7)>>3);index++)
mark_arry1[index] &= mark_arry2[index];
//deconstruct mark array - >result.
r_size = 0;
for(index = 0;index < ((1000 + 7)>>3);index++)
{
if(mark_arry1[index])
for(int i =0;i< 8;i++)
{
if((1<<i)&mark_arry1[index])
{
nums2[r_size++] = (index<<3) + i;
}
}
}
free(mark_arry1);
free(mark_arry2);
*returnSize = r_size;
return nums2;
}
参考
遍历其中长度小的数组,遇到前后两个相同的数就跳过前面那个重复的数,然后用遍历到的数当target值,到长度较长的数组中进行二分查找 - 两个数组的交集 - 力扣(LeetCode)