【问题描述】[简单]
【解答思路】
1. 逐个查找
时间复杂度:O(N) 空间复杂度:O(1)
public int findMagicIndex(int[] nums) {
for (int i = 0, length = nums.length; i < length; i++) {
if (i == nums[i])
return i;
}
return -1;
}
2. 逐个查找优化
有序升序整数
假如nums[0]=100,假如是升序的,那么num[0]后面的值都不会比100小,所以i如果还是一步步的加,效率肯不高,我们直接让i从100开始,因为小于100的i肯定是查找不到的。
时间复杂度:O(N) 空间复杂度:O(1)
public int findMagicIndex(int[] nums) {
for (int i = 0, length = nums.length; i < length; i++) {
if (i == nums[i])
return i;
if (nums[i] > i + 1) {
//如果nums[i]大于i+1,我们就让i加上nums[i] - 1,
// 这里减1的目的是为了抵消上面for循环中的i++。
//这里判断的时候为什么是nums[i] > i + 1而不是
//nums[i] > i ,因为如果num[i]只比i大1的话,
//直接执行上面的i++就可以了,没必要再执行下面的计算
i = nums[i] - 1;
}
}
return -1;
}
3. 递归
一想到排序数组很容易想到的是二分法查找,但是这里如果直接使用二分法查找的i不一定是最小的,有重复的数字。
[0,0,2,2,5] 存在多个满足
所以有一种方式就是先把数组劈两半,先在前面一半查,如果找到就直接返回,如果没找到就在后面部分查,并且前面部分和后面部分再分别劈两半,一直这样递归下去……。
时间复杂度:O(N) 空间复杂度:O(1)
class Solution {
public int findMagicIndex(int[] nums) {
return getAnswer(nums, 0, nums.length - 1);
}
public int getAnswer(int[] nums, int left, int right) {
if (left > right) {
return -1;
}
int mid = (right - left) / 2 + left;
int leftAnswer = getAnswer(nums, left, mid - 1);
if (leftAnswer != -1) {
return leftAnswer;
} else if (nums[mid] == mid) {
return mid;
}
return getAnswer(nums, mid + 1, right);
}
}
【总结】
暴力容易想到 也容易想到二分 但没想到它是不能直接用二分,而只能用二分剪枝的思想 直接使用二分一定要单调递增或递减
转载链接:https://leetcode-cn.com/problems/magic-index-lcci/solution/zhu-ge-cha-zhao-yi-ji-you-hua-di-gui-you-hua-ji-di/
参考链接:https://leetcode-cn.com/problems/magic-index-lcci/solution/mo-zhu-suo-yin-by-leetcode-solution/