LeetCode 484 - Find Permutation


http://bookshadow.com/weblog/2017/01/22/leetcode-find-permutation/
By now, you are given a secret signature consisting of character 'D' and 'I'. 'D' represents a decreasing relationship between two numbers, 'I' represents an increasing relationship between two numbers. And our secret signature was constructed by a special integer array, which contains uniquely all the different number from 1 to n (n is the length of the secret signature plus 1). For example, the secret signature "DI" can be constructed by array [2,1,3] or [3,1,2], but won't be constructed by array [3,2,4] or [2,1,3,4], which are both illegal constructing special string that can't represent the "DI" secret signature.
On the other hand, now your job is to find the lexicographically smallest permutation of [1, 2, ... n] could refer to the given secret signature in the input.
Example 1:
Input: "I"
Output: [1,2]
Explanation: [1,2] is the only legal initial spectial string can construct secret signature "I", where the number 1 and 2 construct an increasing relationship.
Example 2:
Input: "DI"
Output: [2,1,3]
Explanation: Both [2,1,3] and [3,1,2] can construct the secret signature "DI", 
but since we want to find the one with the smallest lexicographical permutation, you need to output [2,1,3]
Note:
  • The input string will only contain the character 'D' and 'I'.
  • The length of input string is a positive integer and will not exceed 10,000
X. http://www.cnblogs.com/grandyang/p/6366738.html
这道题给了我们一个由D和I两个字符组成的字符串,分别表示对应位置的升序和降序,要我们根据这个字符串生成对应的数字字符串。由于受名字中的permutation的影响,感觉做法应该是找出所有的全排列然后逐个数字验证,这种方法十有八九无法通过OJ。其实这题用贪婪算法最为简单,我们来看一个例子:
D D I I D I
1 2 3 4 5 6 7
3 2 1 4 6 5 7
我们不难看出,只有D对应的位置附近的数字才需要变换,而且变换方法就是倒置一下字符串,我们要做的就是通过D的位置来确定需要倒置的子字符串的起始位置和长度即可。通过观察,我们需要记录D的起始位置i,还有D的连续个数k,那么我们只需要在数组中倒置[i, i+k]之间的数字即可
In order to reverse the subsections of the min array, as discussed in the last approach, we can also start by initializing the resultant arrangement res with the min array i.e. by filling with elements (1,n) in ascending order. Then, while traversing the pattern s, we can keep a track of the starting and ending indices in res corresponding to the D's in the pattern s, and reverse the portions of the sub-arrays in rescorresponding to these indices. The reasoning behind this remains the same as discussed in the last approach.

  public int[] findPermutation(String s) {
    int[] res = new int[s.length() + 1];
    for (int i = 0; i < res.length; i++)
      res[i] = i + 1;
    int i = 1;
    while (i <= s.length()) {
      int j = i;
      while (i <= s.length() && s.charAt(i - 1) == 'D')
        i++;
      reverse(res, j - 1, i);
      i++;
    }
    return res;
  }

  public void reverse(int[] a, int start, int end) {
    for (int i = 0; i < (end - start) / 2; i++) {
      int temp = a[i + start];
      a[i + start] = a[end - i - 1];
      a[end - i - 1] = temp;
    }
  }
X. 
下面这种方法没有用到数组倒置,而是根据情况来往结果res中加入正确顺序的数字,我们遍历s字符串,遇到D直接跳过,遇到I进行处理,我们每次先记录下结果res的长度size,然后从i+1的位置开始往size遍历,将数字加入结果res中即可
    vector<int> findPermutation(string s) {
        vector<int> res;
        for (int i = 0; i < s.size() + 1; ++i) {
            if (i == s.size() || s[i] == 'I') {
                int size = res.size();
                for (int j = i + 1; j > size; --j) {
                    res.push_back(j);
                }
            }
        }
        return res;
    }

直接构造法 时间复杂度O(n)
初始令数组nums = [1,2, ..., n],令数组ans = []

执行如下循环直到s为空:

  记s中的当前字符为c
  
  若c == 'I',则直接将nums中的最小元素移除并加入ans;将c从s中移除
  
  否则,记连续的字符'D'的个数为cnt,将nums[0 ... cnt+1]移除,逆置后加入ans;将cnt个'D'从s中移除,如果后面有字符'I',则一并移除。
https://discuss.leetcode.com/topic/76276/1-liner-and-5-liner-visual-explanation
If it's all just I, then the answer is the numbers in ascending order. And if there are streaks of D, then just reverse the number streak under each:
0_1485039424299_Find Permutation.png
Idea is pretty simple. There are 2 possibilities:
  1. String starts with "I". Then we should use 1 as the first item.
  2. String starts with "D..DI" (k letters) or the string is just "D...D". In this case we should use k, k - 1, ..., 1 to get lexicographically smallest permutation.
Then we proceed computing the rest of the array. Also we should increase min variable that is used to store minimum value in remaining part of the array.
public int[] findPermutation(String s) {
    
    s = s + ".";
    int[] res = new int[s.length()];
    int min = 1, i = 0;

    while (i < res.length) {
        if (s.charAt(i) != 'D') {
            res[i++] = min++;
        } else {
            int j = i;
            while (s.charAt(j) == 'D') j++;
            for (int k = j; k >= i; k--)
                res[k] = min++;
            i = j + 1;
        }
    }

    return res;
}
X. Two Pointers
Instead of initializing the res array once with ascending numbers, we can save one iteration over res if we fill it on the fly. To do this, we can keep on filling the numbers in ascending order in res for I's found in the pattern s. Whenever we find a D in the pattern s, we can store the current position(counting from 1) being filled in the res array in a pointer j. Now, whenever we find the first I following this last consecutive set of D's, say at the i^{th} position(counting from 1) in res, we know, that the elements from j^{th} position to the i^{th}position in res need to be filled with the numbers from j to i in reverse order. Thus, we can fill the numbers in res array starting from the j^{th} position, with i being the number filled at that position and continue the filling in descending order till reaching the i^{th} position. In this way, we can generate the required arrangement without initializing res.
  public int[] findPermutation(String s) {
    int[] res = new int[s.length() + 1];
    res[0] = 1;
    int i = 1;
    while (i <= s.length()) {
      res[i] = i + 1;
      int j = i;
      if (s.charAt(i - 1) == 'D') {
        while (i <= s.length() && s.charAt(i - 1) == 'D')
          i++;
        for (int k = j - 1, c = i; k <= i - 1; k++, c--) {
          res[k] = c;
        }
      } else
        i++;
    }
    return res;

  }

X. Stack
  public int[] findPermutation(String s) {
    int[] res = new int[s.length() + 1];
    Stack<Integer> stack = new Stack<>();
    int j = 0;
    for (int i = 1; i <= s.length(); i++) {
      if (s.charAt(i - 1) == 'I') {
        stack.push(i);
        while (!stack.isEmpty())
          res[j++] = stack.pop();
      } else
        stack.push(i);
    }
    stack.push(s.length() + 1);
    while (!stack.isEmpty())
      res[j++] = stack.pop();
    return res;

  }


X.
https://discuss.leetcode.com/topic/76221/java-o-n-clean-solution-easy-to-understand
For example, given IDIIDD we start with sorted sequence 1234567
Then for each k continuous D starting at index i we need to reverse [i, i+k] portion of the sorted sequence.
    public int[] findPermutation(String s) {
        int n = s.length(), arr[] = new int[n + 1];
        for (int i = 0; i <= n; i++) arr[i] = i + 1; // sorted
        for (int h = 0; h < n; h++) {
            if (s.charAt(h) == 'D') {
                int l = h;
                while (h < n && s.charAt(h) == 'D') h++;
                reverse(arr, l, h);
            }  
        }  
        return arr;
    }  
    void reverse(int[] arr, int l, int h) {
        while (l < h) {
            arr[l] ^= arr[h];
            arr[h] ^= arr[l];
            arr[l] ^= arr[h];
            l++; h--;
        }  
    }
http://www.learn4master.com/interview-questions/leetcode/leetcode-find-permutation
A simple solution is to use dfs search and back tracking.
    public int[] findPermutation(String s) {
        int n = s.length() + 1;
        boolean[] visited = new boolean[n + 1];
        int[] res = new int[n];
        for(int i = 1; i <= n; i++) {
            visited[i] = true;
            res[0] = i;
            if(find(1, visited, s, res)) {
                return res;
            }
            visited[i] = false;
        }
        return new int[0];
    }
    
    boolean find(int i, boolean[] visited, String s, int[] res) {
        if(i == visited.length - 1) {
            return true;
        }
        for(int k = 1; k < visited.length; k++) {
            if(visited[k]) continue;
            if(s.charAt(i - 1) == 'D') {
                if(k < res[i - 1]) {
                    res[i] = k;
                    visited[k] = true;
                    if(find(i + 1, visited, s, res)) {
                        return true;
                    }
                    visited[k] = false;
                    res[i] = 0;
                }
            }
            if(s.charAt(i - 1) == 'I') {
                if(k > res[i - 1]) {
                    res[i] = k;
                    visited[k] = true;
                    if(find(i + 1, visited, s, res)) {
                        return true;
                    }
                    visited[k] = false;
                    res[i] = 0;
                }
            }
        }
        return false;
    }


第一题:给一个pattern “IIDDI”, D代表decrease, I代表increase,找出能满足这个pattern的由数字1到n组成的值最小的Permutation,n=pattern.length+1,比如上面这个例子结果就是125436
思路:
先将原数组升序排列,满足了所有的I, 然后对于连续的D,全部reverse
code:
class Solution {
   public int[] findPermutation(String s) {
       int len = s.length();
       int[] res = new int[len + 1];
       for(int i = 0 ; i < res.length ; i++) {
           res[i] = i + 1;
       }
       for(int i = 0 ; i < len ; i++) {
           if(s.charAt(i) == 'D') {
               int j = i;
               while(j < len && s.charAt(j) == 'D') j++;
               reverse(res, i, j);
               i = j - 1;
           }
       }
       return res;
   }
   private void reverse(int[] arr, int left, int right) {
       int l = left, r = right;
       while(l < r) {
           swap(arr, l++, r--);
       }
   }
   private void swap(int[] arr, int i, int j) {
       int tmp = arr[i];
       arr[i] = arr[j];
       arr[j] = tmp;
   }
}


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