LeetCode 926. 將字串翻轉到單調遞增 遞迴實現動態規劃 兩種解法
阿新 • • 發佈:2018-11-04
這個題做了一個多小時,考慮複雜了。
- 開始推動規沒有推出來,然後找到一個遞推關係:從左往右,如果是0,則不需要變動;如果是1,則有兩種選擇(1)將1變為0(2)將1後面的所有數字變為1,這兩種方法中的變動數字最小的方法就是最佳方法,然後依次遞推,很容易寫出遞迴程式。但是這裡面存在問題,如果直接計數1後面0的個數會超時;開陣列提前儲存會爆記憶體。所以在其中採用動規,在呼叫返回時記錄0的數量。(這裡的動規用for迴圈寫也可以)
- 另一種方法是看兩個數字間的縫隙的左右兩側的需要變動的0和1的數量,加和最小為最優。
java程式碼如下:
- 遞迴實現動態規劃
class Solution {
public int count_0;
public Solution(){
count_0 = 0;
}
public int minFlipsMonoIncr(String S) {
if(S.length() <= 0) return 0;
int min = 999;
if(S.charAt(0) == '0'){
min = minFlipsMonoIncr(S.substring(1));
count_0++ ;
}
else{
min = minFlipsMonoIncr(S.substring(1)) + 1;
if(min > count_0) min = count_0;
}
return min;
}
}
- 另一種解法
class Solution {
public int minFlipsMonoIncr(String S) {
int[] count_0 = new int[S.length() + 5];
int [] count_1 = new int[S.length() + 5];
count_0[S.length()] = 0;
count_1[0] = 0;
for (int i = S.length() - 1, sum = 0; i >= 0; i--) {
if (S.charAt(i) == '0') {
count_0[i] = ++sum;
} else {
count_0[i] = sum;
}
}
for (int i = 1, sum = 0; i <= S.length(); i++) {
if (S.charAt(i - 1) == '1') {
count_1[i] = ++sum;
} else {
count_1[i] = sum;
}
}
int min = 99999;
for (int i = 0; i <= S.length(); i++) {
if (count_0[i] + count_1[i] < min) {
min = count_0[i] + count_1[i];
}
}
return min;
}
}