题目
给你一个整数数组 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
来源:力扣(LeetCode)
链接:https:///problems/check-if-n-and-its-double-exist
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
分析
第一种思路,利用哈希表,对0需要进行特殊处理,将数组中的每个数放入哈希表,再用2乘以数组中的每个数,然后拿去哈希表中进行判断,如果哈希表中存在该数则返回true,否则返回false。
第二种思路,暴力破解,双层循环判断。
第三种思路是利用双指针(思路来源于:https:///problems/check-if-n-and-its-double-exist/solution/shuang-zhi-zhen-fa-yu-hashmapfa-by-handling/)。
首先将数组排序,之后遍历数组,数组中正数与负数找2倍数是要区分开的,具体为:
例如:-8 -4 -1 0 1 8 9
当前遍历到的元素是负数时,双指针l应该是最左侧,因为负数的双倍数需要以左边临界点为起始点,左端为负数的最小值,负数*2是会变小的。
- 1:当前 arr[l] > arr[i]*2 则说明当前l指向元素已经大于元素的双倍数,需要跳出循环,因为已经找不到其对应的双倍数,数组元素从左至右依次变大。
- 2:当前arr[l] < arr[i]*2 则说明l指向元素小,需要向右增大,因此执行 ++l
- 3:若arr[l] =arr[i]*2 返回true
当前遍历到的元素是正数时,双指针r应该是最右侧,因为正数的双倍数需要以右边临界点为起始点,右端为正数的最小值,正数*2是会变大的。
- 1:当前 arr[r] > arr[i]*2 则说明当前r指向元素已经大于元素的双倍数,需要--r,遍历较小的元素。
- 2:当前arr[r] < arr[i]*2 则说明r指向元素小于遍历元素的二倍,向左移动已经不能满足,因此跳出循环。
- 3:若arr[r] =arr[i]*2 返回true
代码
第一种思路:
/**
* 题目:1346. 检查整数及其两倍数是否存在(第一种算法:利用哈希表)
* @param arr 数组
* @return 如果存在返回true,否则返回false
*/
public boolean checkIfExist(int[] arr) {
Map map=new HashMap();
int zeroCount=0;// 对0进行特殊处理
for (int i = 0; i < arr.length; i++) {
if(arr[i]==0){// 计算0的个数
zeroCount++;
}
map.put(arr[i],0);
}
if(zeroCount>=2){// 如果存在两个以上的0,就输出true
return true;
}else {
for (int i : arr) {
if (i!=0&&map.containsKey(i * 2)) {
return true;
}
}
}
return false;
}
第二种思路:
/**
* 题目:1346. 检查整数及其两倍数是否存在(第二种算法:暴力破解,循环判断)
*
* @param arr 数组
* @return 如果存在返回true,否则返回false
*/
public boolean checkIfExist(int[] arr){
int zeroCount=0;
for (int num : arr) {
if(0==num){
zeroCount++;
}else {
int temp=num*2;// 不能用除,而需要用乘法
for (int j : arr) {
System.out.println(num);
if(temp!=0&&temp==j){
return true;
}
}
}
}
if(zeroCount>=2){
return true;
}
return false;
}
第三种思路:
public boolean checkIfExist(int[] arr) {
Arrays.sort(arr);
for (int i = 0; i != arr.length; ++i) {
if (arr[i] < 0) {
int l = 0;
while (i != l && arr[l] < 0) {
if (arr[l] < arr[i] * 2) ++l;
else if (arr[l] > arr[i] * 2) break;
else return true;
}
} else {
int r = arr.length - 1;
while (i != r) {
if (arr[r] > arr[i] * 2) --r;
else if (arr[r] < arr[i] * 2) break;
else return true;
}
}
}
return false;
}