思路:
其实这种解法与遍历每两个数之和有点类似,只不过加了许多小技巧。
首先我们需要对数组排序,然后对数组进行遍历,每次遍历时,在第 i i i个数后面的数 [ i + 1 , . . . , n − 1 ] [i + 1, ..., n - 1] [i+1,...,n−1]中进行对 x − a r r a y [ i ] x-array[i] x−array[i]的二分查找。
总的时间复杂度为 O ( n l o g n + n ∗ n 1 2 ) O(n{log}n + n * n^{\frac{1}{2}}) O(nlogn+n∗n21)。
源代码:
//
// main.c
// SumOfTwoNums
//
// Created by 胡昱 on 2021/11/5.
//
#include <stdio.h>
#include <stdlib.h>
#define N 50000
int cmp(const void * a, const void * b) {
return ( *(int*)a - *(int*)b );
}
int search(int* nums, int numsSize, int target) {
int low = 0, high = numsSize - 1;
int mid = (low + high) / 2;
while (low <= high) {
mid = (low + high) / 2;
if(target == nums[mid]) {
return 1;
}
if(target < nums[mid]) {
high = mid - 1;
}else{
low = mid + 1;
}
}
return 0;
}
int main(int argc, const char * argv[]) {
// 共m个问题
int m;
scanf("%d", &m);
while((m--) > 0) {
// 共n个元素
int n;
scanf("%d", &n);
// x为2个元素的和的目标
int x;
scanf("%d", &x);
// 创建并输入数组
int a[N];
for(int i = 0; i < n; ++i) {
scanf("%d", &a[i]);
}
// 排序,时间复杂度为O(nlogn)
qsort(a, n, sizeof(int), cmp);
// 查找是否有两个元素和为x
// 原理为:选出一个数,在剩余的数字里面进行二分查找,故时间复杂度为O(n * n^0.5)
int flag = search(a + 1, n - 1, x - a[0]);
for(int i = 1; i < n - 1 && !flag; ++i) {
// Tip:跳过重复的元素
if(a[i] == a[i - 1]) {
continue;
}
else {
flag = search(a + i + 1, n - i, x - a[i]);
}
}
// 输出
if(flag == 1) {
printf("yes\n");
}
else {
printf("no\n");
}
}
return 0;
}
文章评论