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; } };
類似題目:
參考資料:
https://leetcode.com/problems/find-permutation/
https://leetcode.com/problems/find-permutation/discuss/96644/c-simple-solution-in-72ms-and-9-lines