Magic Index


https://www.cnblogs.com/wuchanming/p/4149788.html
http://www.voidcn.com/article/p-ofbkvbvl-bkw.html
在数组A[0..n-1]中,有所谓的魔术索引,满足条件A[i]=i。给定一个升序数组,元素值各不相同,编写一个方法,判断在数组A中是否存在魔术索引。请思考一种复杂度优于o(n)的方法。
给定一个int数组A和int n代表数组大小,请返回一个bool,代表是否存在魔术索引。
测试样例:
[1,2,3,4,5]
返回:false

解答

暴力法

class MagicIndex {
public:
    bool findMagicIndex(vector<int> A, int n) {
        // write code here
        for(int i = 0;i<n;++i)
            if(A[i] == i)
                return true;

        return false;
    }
};

根据数据特点,利用二分查找的思想

  给定的数组是有序的
  这个问题域经典的二分查找非常相似。在二分查找中,要找出元素k,我们会先拿它跟数组中间的元素x比较,确定k是位于x的左边还是右边。
  以此为基础,是否可以通过检查中间元素来确定魔术索引的位置?
  这里写图片描述
  以上面的数组为例,看到中间元素A[5] = 3,由于A[mid]
    bool findMagicIndex(vector<int> A, int n) {
        // write code here
        return findMagicIndexCore(A,0,A.size()-1) == -1?false:true;

    }

    int findMagicIndexCore(vector<int> A,int start,int end)
    {
        if(end<start || start < 0 || end>=A.size())
            return -1;
        int mid = (start+mid)/2;
        if(A[mid] == mid)
            return mid;
        else if(A[mid] < mid)
            return findMagicIndexCore(A,mid+1,end);
        else
            return findMagicIndexCore(A,start,mid-1);
    }
X. https://www.cnblogs.com/wuchanming/p/4149788.html
如果存在重复元素,前面的算法就会失效。以下面的数组为例:
-10 -5 2 2 2 3 4 7 9 12 13
  0   1  2 3 4 5 6 7 8 9 10 11
看到A[mid]<mid时,我们无法判定魔术索引位于数组哪一边。它可能在数组右侧,跟前面一样。或者,也可能在左侧(在本例中的确在左侧)。
它有没有可能在左侧的任意位置呢?不可能。由A[5]=3可知,A[4]不可能是魔术索引。A[4]必须等于4,其索引才能成为魔术索引,但数组是有序的,故A[4]必定小于A[5]。
事实上,看到A[5]=3时按照前面的做法,我们需要递归搜索右半部分。不过,如搜索左半部分,我们可以跳过一些元素,值递归搜索A[0]到A[3]的元素。A[3]是第一个可能成为魔术索引的元素。

综上:我们得到一种搜索模式,先比较midIndex和midValue是否相同。然后,若两者不同,则按如下方式递归搜索左半部分和右半部分。
左半部分:搜索索引从start到min(midIndex-1,midValue)的元素。
右半部分:搜索索引从max(midIndex+1,minValue)到end的元素。
可以看做前面的基础上求左右两边的交集,例如A[mid]<mid,需要搜索mid左边的部分元素,即区间从start到min(midIndex-1,midValue)的元素和mid右边的全部元素。
A[mid]>mid,需要搜索mid左边的全部元素和右边的部分元素,即区间从max(midIndex+1,minValue)到end,然后两者求交集,就得到上面的区间了。
int magicHelper(int arr[],int n,int l,int r)
{
    if(l>r||l<0||r>=n)
        return -1;
    int mid=(l+r)/2;
    if(mid==arr[mid])
        return mid;
    int rightindex=min(mid-1,arr[mid]);
    int left=magicHelper(arr,n,l,rightindex);
    if(left>=0)
        return left;
    int leftindex=max(mid+1,arr[mid]);
    int right=magicHelper(arr,n,leftindex,r);
    return right;
}
//有重复元素
int magicFast(int arr[],int n)
{
    if(n==0)
        return -1;
    return magicHelper(arr,n,0,n-1);
}

http://www.voidcn.com/article/p-rkooanvq-bkw.html
在数组A[0..n-1]中,有所谓的魔术索引,满足条件A[i]=i。给定一个不下降序列,元素值可能相同,编写一个方法,判断在数组A中是否存在魔术索引。请思考一种复杂度优于o(n)的方法。
给定一个int数组A和int n代表数组大小,请返回一个bool,代表是否存在魔术索引。
测试样例:
[1,1,3,4,5]
返回:true

解答

  如果数组的元素有重复,魔术索引1中的方法就会失效。以下面的数组为例
  这里写图片描述
  可以看到A[mid] < mid时,我们无法判定魔术索引位于数组的哪一边。
  它是否可能在左侧的任意位置?不是。由A[5]=3,可以知道,A[4]不可能是魔术索引。A[4]=4,它才能是魔术索引,但数组是有序的,索引A[4]必定小于等于A[5]。
  所以,我们可以将算法分为两步
  
  1. 比较midIndex与midValue,若二者相同,直接返回。
  2. 否按照如下的方式,递归搜索数组的左半部分和右半部分:
    左半部分:搜索从start到min(midIndex-1,midValue)的元素;
    右半部分:搜索从max(midIndex+1,midValue)到end的元素。
    bool findMagicIndex(vector<int> A, int n) {
        // write code here
        return findMagicIndexCore(A,0,A.size()-1) == -1?false:true;
    }

    int findMagicIndexCore(vector<int> A,int start,int end)
    {
        if(end<start || start <0 || end>=A.size())
            return -1;
        int midIndex = (start+end)/2;
        int midValue = A[midIndex];
        if( midValue == midIndex)
            return midIndex;

        int leftEnd = min(midIndex-1,midValue);
        int left = findMagicIndexCore(A,start,leftEnd);
        if(left>=0)
            return left;

        int rightStart = max(midIndex+1,midValue);
        int right = findMagicIndexCore(A,rightStart,end);

        return right;

    }



Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts