求:
给你一个整数数组 arr,请你检查是否存在两个整数 N 和 M,满足 N 是 M 的两倍(即,N = 2 * M)。
更正式地,检查是否存在两个下标 i 和 j 满足:
i != j
0 <= i, j < arr.length
arr[i] == 2 * arr[j]
示例 1:
输入:arr = [10,2,5,3]
输出:true
解释:N = 10 是 M = 5 的两倍,即 10 = 2 * 5 。
示例 2:
输入:arr = [7,1,14,11]
输出:true
解释:N = 14 是 M = 7 的两倍,即 14 = 2 * 7 。
示例 3:
输入:arr = [3,1,7,11]
输出:false
解释:在该情况下不存在 N 和 M 满足 N = 2 * M 。
提示:
2 <= arr.length <= 500
-10^3 <= arr[i] <= 10^3
解:
首先最直观的想到暴力法,时间复杂度是O(N^2)
bool
checkIfExist(
int
* arr,
int
arrSize){
int
i,j;
for
(i=
0
;i
for
(j=i+
1
;j
if
(arr[i]==arr[j]*
2
|| arr[j]==arr[i]*
2
)
return
true
;
}
return
false
;
}
对暴力法进行改进,很自然的想到使用哈希表以空间换时间的策略,通过判断哈希表对应位置上的索引关系,能够知道是否存在符合题意的一对数。
注意这里有2个细节:
1、数组可能包含数组,而使用数组实现哈希表,索引不能是负数,但是因为题目给出了数的范围,我们对这个区间统一加上1000,就可以保证索引的有效性。
2、0要单独处理,否则会因为0的存在导致错误的结果。
bool
checkIfExist(
int
* arr,
int
arrSize){
int
hashMap[
2001
] = {
0
};
int
countZero =
0
;
int
i;
for
(i=
0
;i
if
(arr[i]==
0
) ++countZero;
if
(countZero>=
2
)
return
true
;
hashMap[
1000
+arr[i]] =
1
;
}
for
(i=
0
;i
if
(arr[i]!=
0
&& arr[i]%
2
==
0
&& hashMap[
1000
+arr[i]/
2
]==
1
)
return
true
;
return
false
;
}