程序员面试金典 8.3

Magic Index:如果一个数组A中的索引i满足A[i] = i,则i就是一个魔术索引。给定一个有序数组,查找其中最小的魔术索引,不存在则返回-1

最简单的方法就是对数据进行一次遍历,这样时间复杂度为O(n),注意到数组是有序的,所以有可能实现一个O(logn)的算法。

0 1 2 3 4 5 6 7 8 9 10
0 1 2 2 2 3 4 7 9 12 13

在上面的数组中,A[5] = 3,用idx表示索引,elt表示索引对应的元素:

  • 如果数组中没有重复元素,那么索引不可能在左边,因为索引减少k时,元素值至少也减少k,所以左边会一直保持idx > elt;同理,如果索引值小于元素值,则右边的idx < elt
  • 如果数组中有重复元素,在索引值大于元素值时,左边也可能存在魔术索引,但是魔术索引的上界是3;同理,如果索引值小于元素值右边也可能存在魔术索引,但是魔术索引的下限为5 + 1

注意书上的代码只返回一个就好,所以可以使用二分法,而力扣要求返回索引最小值,所以二分法不一定肯定可以排除一半的。同时力扣上的测试用例有问题,例如下面的用例应该都返回0,而力扣都返回1

[0, 1, 1]
[0, 1, 2, 2, 2, 3, 4, 7, 9, 12, 13]
class Solution {
public:
    int findMagicIndex(vector<int>& nums) {
        return MagicIndex(nums, 0, nums.size());
    }
private:
    int MagicIndex(const vector<int> &nums, int b, int e)
    {
        int mid = b + (e - b) / 2, ret;
        if(b >= e) return -1;
        //int end = mid <= nums[mid] ? mid : mid;
        ret = MagicIndex(nums, b, mid);
        if(ret != -1) return ret;
        else if(mid == nums[mid]) return mid;
        else{
            int begin = mid < nums[mid] ? nums[mid] : mid + 1;
            return MagicIndex(nums, begin, e);
        }
    }
};
发布了194 篇原创文章 · 获赞 2 · 访问量 7719

猜你喜欢

转载自blog.csdn.net/RayoNicks/article/details/105450882
8.3
今日推荐