[CareerCup] 9.3 Magic Index 魔法序号 - Grandyang - 博客园


[CareerCup] 9.3 Magic Index 魔法序号 - Grandyang - 博客园
9.3 A magic index in an array A[0.. .n-1] is defined to be an index such that A[i] = i. Given a sorted array of distinct integers, write a method to find a magic index, if one exists, in array A.
FOLLOW UP
What if the values are not distinct?

这道题定义了一个魔法序号,就是一个数组的序号等于该位置的值的时候,这个序号就是魔法序号,给了我们一个有序数组,让我们来找魔法序号。这里brute force的方法就不提了,因为没啥考察的目的,对于高效的查找方法我们就要首先考虑二分搜索法,首先我们来看这种方法,没啥特别的地方,套用一般的二分查找法的格式即可
    int getMagicIdx(vector<int> &nums) {
        int left = 0, right = nums.size() - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (nums[mid] == mid) return mid;
            else if (nums[mid] > mid) right = mid - 1;
            else left = mid + 1;
        }
        return -1;
    }
这道题的Follow up是说如果数组由重复项怎么处理,那么传统的二分搜索法就会失效,因为下列这种情况可能存在:
-10-522234791213
012345678910
这种情况符合题意,但是左右两边都会出现魔法序号,所以二分查找法会失效。那么我们难道又要用地毯式搜索了么,其实也不必,我们可以用一种类似于二分搜索法的递归方法来解决问题,就拿上面那个例子来说,第一次找到比较完中间点后,由于左右两边都会出现答案,所以我们左右半段要分别递归一下,这里我们可以加一个trick来优化算法,比如要递归左半段时,那么新的右边界就可以设为min(mid - 1, nums[mid]),同理递归右半段时,左边界可以设为max(mid + 1, nums[mid])。还有个小trick,就是如果左半段搜到了答案,那么直接返回即可,不用再搜右半段,因为题目让我们找一个就行了,没说要找出所有的Magic index
    int getMagicIdx(vector<int> &nums) {
        return getMagicIdxDFS(nums, 0, nums.size() - 1);
    }
    int getMagicIdxDFS(vector<int> &nums, int start, int end) {
        if (end < start) return -1;
        int mid = (start + end) / 2;
        if (mid == nums[mid]) return mid;
        int left = getMagicIdxDFS(nums, start, min(mid - 1, nums[mid]));
        if (left >= 0) return left;
        int right = getMagicIdxDFS(nums, max(mid + 1, nums[mid]), end);
        return right;
    }
http://www.shuatiblog.com/blog/2014/09/17/find-magic-index/
We cannot discard half of the input any more. Instead, we discard a range between (mid) and (array[mid]). Then check left and right part seperately.
public static int myAnswerWithDup(int[] array) {
    int len = array.length;
    return helper(array, 0, len - 1);
}

public static int helper(int[] array, int left, int right) {
    if (right < left) {
        return -1;
    }
    int mid = left + (right - left) / 2;
    if (array[mid] == mid) {
        return mid;
    } else {
        int smaller = 0;
        int larger = 0;
        if (array[mid] < mid) {
            smaller = array[mid];
            larger = mid + 1;
        } else if (array[mid] > mid) {
            smaller = mid - 1;
            larger = array[mid];
        }
        int leftResult = helper(array, left, smaller);
        if (leftResult != -1) {
            return leftResult;
        } else {
            return helper(array, larger, right);
        }
    }
}
https://codesolutiony.wordpress.com/2014/12/31/9-3-magic-index/
public int findMagicIndex(int[] num) {
    return subFind(num, 0, num.length - 1);
}
private int subFind(int[] num, int start, int end) {
    int result = -1;
    if (start > end) {
        return -1;
    }
    int mid = (start + end) / 2;
    if (num[mid] == mid) {
        return mid;
    }
    if (num[mid] > mid) {
        result = subFind(num, start, mid - 1) == -1 ? result = subFind(num, num[mid], end);
    } else {
        result = subFind(num, mid + 1, end) == -1 ? subFind(num, start, num[mid]);
    }
    return result;
}
http://www.cnblogs.com/jdflyfly/p/3931807.html
https://gist.github.com/ivycheung1208/853f9f700439860848fe
// return one magic index if any
int magicIndex(vector<int> arr, int begin, int end) // arr[begin, end)
{
    if (begin == end) { // no element left in the subarray
        return -1;
    }
    int mid = (begin + end) / 2; // middle of the subarray
    if (arr[mid] == mid)
        return mid;
    else if (arr[mid] < mid)
        return magicIndex(arr, mid + 1, end); // examine the right subaaray
    else
        return magicIndex(arr, begin, mid); // examine the left subaaray
}

int magicIndex(vector<int> arr)
{
    return magicIndex(arr, 0, arr.size());
}

// return all possible magic indices
void magicIndexMult(vector<int> arr, int begin, int end, vector<int> &index)
{
    if (begin == end)
        return;
    int mid = (begin + end) / 2;
    if (arr[mid] >= mid)
        magicIndexMult(arr, begin, mid, index);
    if (arr[mid] == mid)
        index.push_back(mid);
    if (arr[mid] <= mid)
        magicIndexMult(arr, mid + 1, end, index);
}

vector<int> magicIndexMult(vector<int> arr)
{
    vector<int> index;
    magicIndexMult(arr, 0, arr.size(), index);
    return index;
}

// return all possible magic indices, data not dictinct
void magicIndexMultND(vector<int> arr, int begin, int end, vector<int> &index)
{
    if (begin == end)
        return;
    int mid = (begin + end) / 2;
    if (arr[mid] >= mid) // first half
        magicIndexMultND(arr, begin, mid, index);
    else if (arr[mid] >= begin)
        magicIndexMultND(arr, begin, arr[mid] + 1, index);
    if (arr[mid] == mid) // middle
        index.push_back(mid);
    if (arr[mid] <= mid) // second half
        magicIndexMultND(arr, mid + 1, end, index);
    else if (arr[mid] < end)
        magicIndexMultND(arr, arr[mid], end, index);
}

vector<int> magicIndexMultND(vector<int> arr)
{
    vector<int> index;
    magicIndexMultND(arr, 0, arr.size(), index);
    return index;
}

int magicFast(int[] array) {
        return magicFast(array, 0, array.length - 1);
}

int magicFast(int[] array, int start, int end) {
        if (end< start) {
                return -1;
        }
        int mid= (start+ end)/ 2;
        if (array[mid] == mid) {
                return mid;
        } else if (array[mid] > mid) {
                13 return magicFast(array, start, mid - 1);
        } else {
                return magicFast(array, mid+ 1, end);
        }
}

Follow Up: What if the elements are not distinct?
The general pattern is that we compare mid Index and midValue for equality first. Then, if they are not equal, we recursively search the left and right sides as follows:
• Left side: search indices start through Math. min (midlndex - 1, midValue ).
Right side: search indices Math. max(midlndex + 1, midValue) through end.
int magicFast(int[] array) {
        return magicFast(array, 0, array.length - 1);
}

int magicFast(int[] array, int start, int end) {
        if (end< start) return -1;

        int midindex =(start+ end)/ 2;
        int midValue = array[midindex];
        if (midValue == midindex) {
                return midindex;
        }

        /* Search left */
        int leftindex = Math.min(midindex - 1, midValue);
        int left = magicFast(array, start, leftindex);
        if (left>= 0) {
                return left;
        }

        /* Search right */
        int rightindex = Math.max(midindex + 1, midValue);
        int right = magicFast(array, rightlndex, end);

        return right;
}

Read full article from [CareerCup] 9.3 Magic Index 魔法序号 - Grandyang - 博客园

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