LintCode - Permutation Index


https://segmentfault.com/a/1190000004683277
Given a permutation which contains no repeated number, find its index in all the permutations of these numbers, which are ordered in lexicographical order. The index begins at 1.
Given [1,2,4], return 1.
http://algorithm.yuanbin.me/zh-hans/exhaustive_search/permutation_index.html
例如[4,2,1],对于4, 比4小的有2和1, 在4这一位,对应的factor为2! (factor的含义是在当前位置数值指定的情况下,变化index大于当前数值的数字,所可能的到的不同排列的个数), 因此在index=0时,可能的排列一共有2*2!. 同理,对于[4,2,1],结果为2*2! + 1*1 + 0*1 + 1 = 6

以序列1, 2, 4为例,其不同的排列共有 3!=6 种,以排列[2, 4, 1]为例,若将1置于排列的第一位,后面的排列则有 2!=2 种。将2置于排列的第一位,由于[2, 4, 1]的第二位4在1, 2, 4中为第3大数,故第二位可置1或者2,那么相应的排列共有 2 * 1! = 2种,最后一位1为最小的数,故比其小的排列为0。综上,可参考我们常用的十进制和二进制的转换,对于[2, 4, 1], 可总结出其排列的index2! * (2 - 1) + 1! * (3 - 1) + 0! * (1 - 1) + 1.
+

以上分析看似正确无误,实则有个关键的漏洞,在排定第一个数2后,第二位数只可为1或者4,而无法为2,故在计算最终的 index 时需要动态计算某个数的相对大小。按照从低位到高位进行计算,我们可通过两重循环得出到某个索引处值的相对大小。
注意 index 和 factor 的初始值,rank 的值每次计算时都需要重新置零,index 先自增,factorial 后自乘求阶乘。
    public long permutationIndex(int[] A) {
        if (A == null || A.length == 0) return 0L;

        long index = 1, fact = 1;
        for (int i = A.length - 1; i >= 0; i--) {
            // get rank in every iteration
            int rank = 0;
            for (int j = i + 1; j < A.length; j++) {
                if (A[i] > A[j]) rank++;
            }

            index += rank * fact;
            fact *= (A.length - i);
        }

        return index;
    }
http://www.cnblogs.com/EdwardLiu/p/5104310.html
在计算最终的 index 时需要动态计算某个数的相对大小。我们可通过两重循环得出到某个索引处值的相对大小。

以4,1,2为例,4为第3大数,1为剩余序列第1大数,2为剩余序列第1大数,

故表达式为:(3-1)*2! + (1-1)*1! + (1-1)*0! + 1 = 5

以2,4,1为例,2为第2大数,4为剩余序列第2大数,1为剩余序列第1大数

故表达式为:(2-1)*2! + (2-1)*1! + (1-1)*0! + 1 = 4

这后面这个1一定要加,因为前面算的都是比该数小的数,加上这个1,才是该数是第几大数。

2!表示当时当前位后面还有两位,全排列有2!种
 6     public long permutationIndex(int[] A) {
 7         // Write your code here
 8         long res = 0;
 9         int n = A.length;
10         long fact = 1;
11         for (int i=1; i<n; i++) {
12             fact *= i; //fact should at last equal (n-1)!
13         }
14         int initial = n-1; //use to update factorial
15         for (int i=0; i<n; i++) {
16             long count = 0;
17             for (int j=i; j<n; j++) {
18                 if (A[i] >= A[j]) {
19                     count++;
20                 }
21             }
22             res += (count-1)*fact;
23             if (initial != 0) {
24                 fact /= initial;
25                 initial--;
26             }
27         }
28         res = res + 1;
29         return res;
30     }

https://segmentfault.com/a/1190000004683277
搞一个哈希表,存储数组A中每一位A[i]的后面小于它的数的个数count。
为什么这样做呢,因为按照lexicographical order,小的数应该排在前面。那么A[i]后面小于A[i]的数有count个,而i前面又应该有n-i-1位,有(n-1-i)的阶乘种排列的可能,所以应该排在A[i]之前的可能排列就有count * (n-1-i)!个:所以遍历A[]中每一个数,计算在其之前的自然排列的数目,这些数目相加之和存入res,那么res的下一个数字就是现在数组A[]的排列。
对题目有了思索和理解之后,可以找找简化一点的办法。有没有可能不使用HashMap,也能够记录阶乘呢?只要从最后一位fact = 1开始, 向高位阶乘,直到最高位fact = A.length!
    public long permutationIndex(int[] A) {
        int n = A.length;
        long res = 0;
        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
        for (int i = 0; i < n; i++) {
            int count = 0;
            for (int j = i+1; j < n; j++) {
                if (A[i] > A[j]) count++;
            }
            map.put(A[i], count);
        }
        for (int i = 0; i < n; i++) {
            long fact = 1;
            for (int j = n-1-i; j > 0; j--) {
                fact *= j;
            }
            res += map.get(A[i]) * fact;
        }
        return ++res;
    }
    public long permutationIndex(int[] A) {
        if (A == null || A.length == 0) return 0;
        long fact = 1, index = 0;
        for (int i = A.length-1; i >= 0; i--) {
            int rank = 0;
            for (int j = i+1; j < A.length; j++) {
                if (A[j] < A[i]) rank++;
            }
            index += rank * fact;
            fact *= (A.length-i);
        }
        return index+1;
    }
//这种思路是从高位向低位计算当前位剩余排列总数,阶乘逐位减小,理解起来就没有那么直观了。
    public long permutationIndex(int[] A) {
        if (A == null || A.length == 0) return 0;
        long index = 0, fact = 1;
        for (int i = 1; i <= A.length; i++) fact *= i;
        for (int i = 0; i < A.length; i++) {
            int rank = 0;
            for (int j = i+1; j < A.length; j++) {
                if (A[j] < A[i]) rank++;
            }
            fact /= (A.length-i);
            index += rank * fact;
        }
        return index+1;
    }
http://www.jiuzhang.com/solutions/permutation-index/
 long fac(int numerator) {
   
  long now = 1;
  for (int i = 1; i <= numerator; i++) {
   now *= (long) i;
  }
  return now;
 }

 long generateNum(HashMap<Integer, Integer> hash) {
  long denominator = 1;
  int sum = 0;
  for (int val : hash.values()) {
   if(val == 0 ) 
    continue;
   denominator *= fac(val);
   sum += val;
  }
  if(sum==0) {
   return sum;
  }
  return fac(sum) / denominator;
 }

 public long permutationIndex(int[] A) {
  HashMap<Integer, Integer> hash = new HashMap<Integer, Integer>();
  
  for (int i = 0; i < A.length; i++) {
   if (hash.containsKey(A[i]))
    hash.put(A[i], hash.get(A[i]) + 1);
   else {
    hash.put(A[i], 1);
   }
  }
  long ans = 0;
  for (int i = 0; i < A.length; i++) {
   for (int j = i + 1; j < A.length; j++) {
    if (A[j] < A[i]) {
     hash.put(A[j], hash.get(A[j])-1);
     ans += generateNum(hash);
     hash.put(A[j], hash.get(A[j])+1);
     
    }
   
   }
    hash.put(A[i], hash.get(A[i])-1);
  }
  
  return ans+1;

 }
http://www.tuwenzhai.com/d/94558250-815c-4b50-95f3-68d2ed883cd1/ab63e816-26ce-4339-bf94-dd4c325bb3ea


X. DFS
http://lintcode.peqiu.com/content/lintcode/permutation_index.html


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