「这是我参与2022首次更文挑战的第25天,活动详情查看:2022首次更文挑战」。
题目描述🌍
给你一个整数数组 arr,请你检查是否存在两个整数 N 和 M,满足 N 是 M 的两倍(即,N = 2 * M)。
更正式地,检查是否存在两个下标 i 和 j 满足:
i != j0 <= i, j < arr.lengtharr[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- <=
arr[i]<=
暴力求解🌖
解题思路
双重循环直接带走,需要注意的是判断条件要双向判断。
代码
Java
class Solution {
public boolean checkIfExist(int[] arr) {
int length = arr.length;
for (int i = 0; i < length - 1; i++) {
for (int j = i + 1; j < length; j++) {
// 双向判断
if (arr[j] == 2 * arr[i] || arr[i] == 2 * arr[j])
return true;
}
}
return false;
}
}
C++
class Solution {
public:
bool checkIfExist(vector<int> &arr) {
int length = arr.size();
for (int i = 0; i < length - 1; ++i) {
for (int j = i + 1; j < length; ++j) {
if (arr[j] == 2 * arr[i] || arr[i] == 2 * arr[j])
return true;
}
}
return false;
}
};
时间复杂度:
空间复杂度:
排序 & 双指针法🚀
解题思路
你会想,可以排序后遍历数组,当 arr[b] = 2 * arr[a] (b > a) 时,不就可以判断了吗?
不对。因为本题中说的是整数,所以有可能是正整数、负整数和零,所以将这些纳入考虑的话,可以使用双指针完成 2 轮一次遍历。
设指针
i用于遍历数组元素x,指针j用于查找2x.
对于 的情况,指针只需要一直前进。若 j 在前进过程中找到一个比 2x 大的数字,那么 2x 必然不存在。在 i 前进的过程中 i 所指向的 x 会不断递增,2x 也会不断递增,因此指针 j 不需要后退。
对于 的情况,指针只需要一直后退。若 j 在后退过程中找到一个比 2x 小的数字,那么 2x 必然不存在。在 i 后退的过程中 p 所指向的 x 会不断递减,2x 也会不断递减,因此指针 j 不需要前进。
代码
Java
class Solution {
public boolean checkIfExist(int[] arr) {
Arrays.sort(arr);
// 2 <= arr.length <= 500
int length = arr.length;
// 判断>0部分: 交替前进
for (int i = 0, j = i + 1; i != length - 1; i++) {
while (j < length && arr[i] * 2 > arr[j])
j++;
if (j < length && arr[i] * 2 == arr[j] && i != j)
return true;
}
// 判断<0部分: 交替后退
for (int i = length - 1, j = i - 1; i != 0; i--) {
while (j >= 0 && arr[i] * 2 < arr[j])
j--;
if (j >= 0 && arr[i] * 2 == arr[j] && i != j)
return true;
}
return false;
}
}
C++
class Solution {
public:
bool checkIfExist(vector<int> &arr) {
sort(arr.begin(), arr.end());
int length = arr.size();
// judge '>0' part
for (int i = 0, j = i + 1; i < length - 1; ++i) {
while (j < length - 1 && arr[j] < arr[i] * 2)
j++;
if (arr[j] == arr[i] * 2 && i != j)
return true;
}
// judge '<0' part
for (int i = length - 1, j = i - 1; i > 0; --i) {
while (j > 0 && arr[j] > arr[i] * 2)
j--;
if (arr[j] == arr[i] * 2 && i != j)
return true;
}
return false;
}
};
时间复杂度:,排序时间复杂度 ,而双指针遍历的时间复杂度为
空间复杂度:
哈希法🧩
解题思路
在数组中查找两个存在某种关联的数字,这不就和「两数之和」的思路很像吗?!
看不懂解题思路的话,可以看链接中「两数之和」哈希法的求解过程!
唯一需要注意的是:需要添加当前遍历元素 num 的 2 倍数和 1/2 倍数,才能让后面的元素完全判断。
代码
Java
class Solution {
public boolean checkIfExist(int[] arr) {
Set<Integer> hashSet = new HashSet<>();
for (int num : arr) {
// 判断该数的2倍或1/2倍是否存在
if (hashSet.contains(num))
return true;
// num可能是某个数的1/2
hashSet.add(num * 2);
if (num % 2 == 0)
// num可能是某个数的2倍(当且仅当num为偶数)
hashSet.add(num / 2);
}
return false;
}
}
C++
class Solution {
public:
bool checkIfExist(vector<int> &arr) {
unordered_set<int> unorderedSet;
for (int num: arr) {
if (unorderedSet.find(num) != unorderedSet.end())
return true;
unorderedSet.insert(num * 2);
if (num % 2 == 0)
unorderedSet.insert(num / 2);
}
return false;
}
};
时间复杂度:
空间复杂度:
最后🌅
该篇文章为 「LeetCode」 系列的 No.23 篇,在这个系列文章中:
- 尽量给出多种解题思路
- 提供题解的多语言代码实现
- 记录该题涉及的知识点
👨💻争取做到 LeetCode 每日 1 题,所有的题解/代码均收录于 「LeetCode」 仓库,欢迎随时加入我们的刷题小分队!