求两个集合的交集和并集

本文介绍了两种求解两个集合交集和并集的方法:1) 使用排序+双指针,时间复杂度为O(n=m+n);2) 利用哈希表,时间复杂度为O(n=max(m,n))。详细步骤包括了交集和并集的实现过程。" 24002525,1167786,使用Java从数据库获取数据并转换为XML,"['Java开发', '数据处理', 'XML编程', '数据库操作', 'JDOM库']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、排序+双指针

交集:

用两个指针分别指向两个数组的头部。如果其中一个元素比另一个小,后移小的那个数组的指针;如果相等,那么把该元素添加到交集里,同时后移两个数组的指针。一直这样操作下去,直到有一个指针超过数组范围。

    public List intersection(int[] a, int[] b){//a和b已经排好序
        List<Integer> result=new ArrayList<>();
        int i=0,j=0;
        while(i<a.length && j<b.length){
            if(a[i]<b[j]){
                i++;
            }else if(a[i]>b[j]){
                j++;
            }else{
                result.add(a[i]);
                i++;
                j++;
            }
        }
        return result;
    }

并集:

用两个“指针”分别指向两个数组的头部。如果其中一个数组的元素比另一个小,把该元素添加到并集里,后移小的那个数组的指针;如果相等,那么把该元素添加到并集里,同时后移两个数组的指针。一直这样操作下去,直到有一个指针超过数组范围。将两个数组中没有遍历完的那个数组的其余元素全部添加进并集里。

      public List union(int[] a, int[] b){//a和b已经排好序
        List<Integer> result=new ArrayList<>();
        int i=0,j=0;
        while(i<a.length && j<b.length){
            if(a[i]<b[j]){
                result.add(a[i]);
                i++;
            }else if(a[i]>b[j]){
                result.add(b[j]);
                j++;
            }else{
                result.add(a[i]);
                i++;
                j++;
            }
        }
        while(i<a.length){
            result.add(a[i]);
            i++;
        }
        while(j<b.length){
            result.add(b[j]);
            j++;
        }
        return result;
    }

时间复杂度:

O(n)=O(m+n)    //m为第一个数组的长度,n为第二个数组的长度

 

2、哈希表

交集:

①建立一个哈希表(HashMap),其键(KEY)表示集合中数字的值,其值(VALUE)表示集合中数字出现的次数

②遍历集合A,将集合中的每个数字(KEY)插入哈希表,每个数字的出现次数(VALUE)设置为1

③遍历集合B,对于集合中的每个数字:

如果哈希表中已经存在该数字,将对应的VALUE改为2

如果哈希表中不存在该数字,忽略

④遍历哈希表,输出VALUE为2的数字,即得到A和B的交集

    public List intersection(int[] a, int[] b){
        List<Integer> result=new ArrayList<>();
        HashMap<Integer,Integer> hash=new HashMap<>();
        for(int i=0;i<a.length;i++){
            hash.put(a[i],1);
        }
        for(int j=0;j<b.length;j++){
            if(hash.containsKey(b[j])){
                hash.put(b[j],2);
            }
        }
        Iterator<Integer> iter=hash.keySet().iterator();
        while(iter.hasNext()){
            int key=iter.next();
            if(hash.get(key)!=1){
                result.add(key);
            }
        }
        return result;
    }

并集:

①建立一个哈希集(HashSet)

②遍历集合A,将集合中的每个数字(KEY)插入哈希集

③遍历集合B,对于集合中的每个数字:

如果哈希集中已经存在该数字,忽略

如果哈希集中不存在该数字,将这个数字插入哈希集

④遍历哈希集,即为A和B的并集

    public HashSet union(int[] a, int[] b){
        HashSet<Integer> set=new HashSet<>();
        for(int i=0;i<a.length;i++){
            set.add(a[i]);
        }
        for(int j=0;j<b.length;j++){
            if(!set.contains(b[j])){
                set.add(b[j]);
            }
        }
        return set;
    }

时间复杂度:

O(n)=O(max(m,n))    //m为第一个数组的长度,n为第二个数组的长度

在C语言中,两个数组的交集可以通过哈希集合的数据结构(如链表、散列表等)来实现。以下是基本步骤: 1. **交集**: - 首先,遍历第一个数组,将每个元素添加到一个哈希集合(例如`std::unordered_set`)中,去除重复值。 - 然后,遍历第二个数组,检查每个元素是否已经在哈希集合中存在,如果存在,则表示是交集的一部分,将其添加到结果数组中。 - 最后返回这个包含交集元素的结果数组。 ```c #include <stdio.h> #include <stdbool.h> #include <stdlib.h> bool is_in_set(int set[], int size, int element) { for (int i = 0; i < size; i++) { if (set[i] == element) return true; } return false; } void find_intersection(int arr1[], int arr1_size, int arr2[], int arr2_size, int* result, int* size) { std::unordered_set<int> hash_set; for (int i = 0; i < arr1_size; i++) hash_set.insert(arr1[i]); *size = 0; for (int j = 0; j < arr2_size; j++) { if (is_in_set(hash_set, arr1_size, arr2[j])) { result[*size++] = arr2[j]; } } } // 示例 int main() { int arr1[] = {1, 2, 3, 4, 5}; int arr2[] = {4, 5, 6, 7, 8}; int intersection[10], intersect_size = 0; find_intersection(arr1, sizeof(arr1)/sizeof(arr1[0]), arr2, sizeof(arr2)/sizeof(arr2[0]), intersection, &intersect_size); printf("Intersection: "); for (int i = 0; i < intersect_size; i++) printf("%d ", intersection[i]); printf("\n"); return 0; } ``` 2. ****: - 同样使用哈希集合存储第一个数组的所有元素。 - 再次遍历第二个数组,如果元素不在集合中,则添加到结果数组中,更新哈希集合。 - 返回最终的结果数组。 ```c void find_union(int arr1[], int arr1_size, int arr2[], int arr2_size, int* result, int* size) { std::unordered_set<int> hash_set; for (int i = 0; i < arr1_size; i++) hash_set.insert(arr1[i]); *size = arr1_size; for (int j = 0; j < arr2_size; j++) { if (!hash_set.count(arr2[j])) result[*size++] = arr2[j]; hash_set.insert(arr2[j]); } } // 示例 int main() { // 使用相同的示例数组 // 结果会是arr1加上arr2中独有的元素 int union_array[10], union_size = sizeof(arr1)/sizeof(arr1[0]); find_union(arr1, sizeof(arr1)/sizeof(arr1[0]), arr2, sizeof(arr2)/sizeof(arr2[0]), union_array, &union_size); printf("Union: "); for (int i = 0; i < union_size; i++) printf("%d ", union_array[i]); printf("\n"); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值