【问题描述】[简单]
【解答思路】
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/