找出数组中符合条件的数对的个数

题目:一个整型数组,元素取值可能是1~N(N是一个较大的正整数)中的任意一个数,相同数值不会重复出现。设计一个算法,找出数列中符合条件的数对的个数,满足数对中两数的和等于N+1。
方法一:排序+二分查找。先对数组进行排序,然后遍历该有序数组,同时使用二分查找方法,查找对应的值是否存在(例如,有序数组中某元素值为a,那么在该有序数组中,使用二分查找方法,来查找(N+1- a)是否存在)。

方法二:排序+线性扫描。先对数组进行排序,然后使用两个指示器(front和back)分别指向第一个和最后一个元素,再从两端同时向中间遍历,直到两个指针交叉。
(1)如果A[front] + A[back] > N+1,则back - -。
(2)如果A[front] + A[back] = N+1,则计数器加1,back - -,同时front++。
(3)如果A[front] + A[back] < N+1,则front++。
重复上述步骤,O(n)时间就可以找到所有数对,因此总体复杂度为O(nlogn)。
通过给出一个有序数组,来观察方法二的实现,如下:

#include <iostream>

void FindSum(int arr[], int len, int sum)
{
    int i,j;
    for (i = 0, j = len - 1; i < len && j >= 0 && i < j;)
    {
        if (arr[i] + arr[j] < sum)
            i++;
        else if (arr[i] + arr[j] == sum)
        {
            printf("%d + %d = %d\n", arr[i], arr[j], sum);
            i++;
            j--;
        }
        else
            j--;

    }
}

int main(int argc, const char * argv[]) {

    int arr[] = {1,2,3,4,5,6};
    int len = sizeof(arr)/sizeof(int);
    FindSum(arr, len, 8);

    return 0;
}

方法三:hash法。即使用hash法,对数组进行计数排序,将1~N个数放在一块很大的空间里面,比如1放在1号位,N放在n号位置,然后对每个数m,在hash表中寻找“下标N+1- m 对应的值是否存在“,若存在,则构成一对满足要求的数对。总体时间复杂度为O(n)。

拓展一:
如果是任意数组,而不是本题的有规律数组,如何求解数组对?即给定一个任意整数数组array[n],寻找数组中和值为SUM的数对。(方法同上)
方法一:排序+二分查找。先对数组进行排序,然后遍历该有序数组,同时使用二分查找方法,查找对应的值是否存在(例如,有序数组中某元素值为m,那么在该有序数组中,使用二分查找方法,来查找(SUM - m)是否存在)。

方法二:排序+线性扫描。先将数组排序后(一般最快的排序算法时间复杂度为O(nlogn)),然后设两个指针指向数组的两端,判断这两个指针对应元素之和是否为SUM,如果等于SUM,则找到了,继续查找;如果小于SUM,那么首指针递增;如果大于SUM,尾指针递减,直到两个指针相遇时,如果还是没有和为SUM的元素对出现,那么返回false。

方法三:hash法。将数组存储到hash表中,对每个数m,在hash表中寻找SUM - m,此时时间复杂度为 O(n)。需要注意的是,如果数组空间很大,超过了内存的容量,那么可以按照hash(max(m, SUM - m))%g,将数据分到g个小的组中,然后对每个小组进行单独处理,此时时间复杂度还是O(n)。

拓展二:
已知大小分别为 m、n 的两个无序数组 A、B 和一个常数 c,求满足A[ i ] + B[ j ] = c 的所有 A[ i ] 和 B[ j ]。(方法同上)
方法一:排序+二分查找。首先,对两个数组中较大数组(假设为 A)排序;然后,对 B 中每个元素 B[ i ] 在 A 中二分查找 c - B[ i ],如果找到,直接输出。此方法的时间复杂度为 O(mlogm + nlogm)。

方法二:排序+线性扫描。首先,对两个数组 A 和 B 进行排序;然后用指针 p 从头扫描 A,用指针 q 从尾扫描 B,如果 A[ p ] + B[ q ] == c,则输出 A[ p ] 和 B[ q ],且p++,q++;如果 A[ p ] + B[ q ] > c,则 q–;否则 p++。时间复杂度为O(mlogm + nlogn)。

方法三:hash法。首先,将两个数组中较小的数组(假设为A)保存到hash表中,然后,对于 B 中的每个元素 B[ i ],也采用相同的hash算法在hash表中查找 c - B[ i ] 是否存在,如果存在,则输出。时间复杂度为O(m + n),空间复杂度为O(min(m, n))。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值