[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 signaturewas 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

 

這道題給了我們一個由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]之間的數字即可,根據上述思路可以寫出代碼如下:

 

解法一:

class Solution {
public:
    vector<int> findPermutation(string s) {
        int n = s.size();
        vector<int> res(n + 1);
        for (int i = 0; i < n + 1; ++i) res[i] = i + 1;
        for (int i = 0; i < n; ++i) {
            if (s[i] != 'D') continue;
            int j = i;
            while (s[i] == 'D' && i < n) ++i;
            reverse(res.begin() + j, res.begin() + i + 1);
            --i;
        }
        return res;
    }
};

 

下面這種方法沒有用到數組倒置,而是根據情況來往結果res中加入正確順序的數字,我們遍歷s字符串,遇到D直接跳過,遇到I進行處理,我們每次先記錄下結果res的長度size,然后從i+1的位置開始往size遍歷,將數字加入結果res中即可,參見代碼如下:

 

解法二:

class Solution {
public:
    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;
    }
};

 

類似題目:

Palindrome Permutation II

Palindrome Permutation

Permutation Sequence

Permutations II

Permutations

Next Permutation

 

參考資料:

https://leetcode.com/problems/find-permutation/

https://leetcode.com/problems/find-permutation/discuss/96644/c-simple-solution-in-72ms-and-9-lines

https://leetcode.com/problems/find-permutation/discuss/96663/greedy-on-java-solution-with-explanation

https://leetcode.com/problems/find-permutation/discuss/96613/java-on-clean-solution-easy-to-understand

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM