Lintcode:884. 尋找排列
阿新 • • 發佈:2018-12-13
現在,給你一個由字元'D'和'I'構成的加密簽名。'D'表示兩個數字是遞減關係,'I'表示兩個數字是遞增關係。我們的加密簽名是由一個特殊的整數陣列生成的。這個陣列含有從1到n(n是加密簽名的長度加1)的所有數字,並且每個數字只出現一次。舉例來說,加密簽名"DI"可以有陣列[2,1,3]或者[3,1,2]生成,但是不能由陣列[3,2,4]或者[2,1,3,4]生成。[3,2,4]和[2,1,3,4]都不能生成"DI"這個特定的加密簽名。
找到能夠生成輸入加密簽名的[1, 2, ... n]的最小字典序的排列。
public int[] findPermutation(String s) { // write your code here int n = s.length(); int lastD_pos = -1; int lastI_pos = -1; int[] arr = new int[n + 1]; if (s.charAt(0) == 'D'){ arr[0] = 2; arr[1] = 1; lastD_pos = 0; }else if(s.charAt(0) == 'I'){ arr[0] = 1; arr[1] = 2; lastI_pos = 0; } int curMax = 2; for (int i = 1; i < n; i++) { if (s.charAt(i) == 'D') { lastD_pos = i; for (int j = lastI_pos; j < i; j++) { arr[j + 1] = arr[j + 1] + 1; curMax = Integer.max(arr[j+1], curMax); } arr[i + 1] = arr[i] - 1; }else if (s.charAt(i) == 'I'){ lastI_pos = i; arr[i+1] = curMax + 1; curMax++; } } for (int i = 0; i < arr.length; i++) { System.out.print(arr[i]+" "); } return arr; }
dalao解法:
public int[] findPermutation2(String s) { // write your code here //對s進行遍歷,先給I位置的數賦值,賦值之後給I前面的D賦逐漸減小的值 int i = 0, j = 0; int[] ans = new int[s.length() + 1]; while (j < s.length()) { if (s.charAt(j) == 'I') { ans[i] = j + 1; while (++i <= j) { ans[i] = ans[i-1] - 1; } } j++; } ans[i] = j + 1; while (++i <= j) { ans[i] = ans[i-1] - 1; } return ans; }
這道題一開始最困擾的就是如果後一個字母是d,就會影響前面的排列,怎麼消除這種影響,一直在想如果後面是d怎麼解決,其實當時想複雜了,如果是d那麼直接更新前面的排列,不要再想著如果後面一個還是d要怎麼做,是不是該留出幾個數字空位來給後面的d。其實這種想法完全多餘,你根本管不了未來會發生什麼,你只需要關心的是如果出現了d,該如何更新前面的序列,所以我的思路很簡單,定義一個變數記錄當前出現的最大數 因為要在他的基礎上加減,再定義一個變數記錄上一次d出現的位置,因為更新的話會影響到上一個d
因此採取的貪心策略就是出現什麼處理什麼(感覺強行貪心,其實是因為不知道怎麼總結)
dalao的思路就清晰的多
採用兩根指標,貪心策略是先處理I的情況,進行遍歷,先給I位置的數賦值,賦值之後給I前面的D賦逐漸減小的值 summary: 1.不要考慮以後會怎樣,先處理好當下 2.有時候兩種情況就意味著只需處理一種情況的同時就可以把另一種情況同時處理了