題目連接c++
動態規劃算法
時間複雜度O(n)
數組
1.題目要求最終造成[紅、黃、紅]三部分,每部分數量能夠不相等,問最終調整操做數量最小是多少。這道題一開始考慮暴力去作,枚舉兩個分界點,即紅黃,黃紅之間的分界點的位置,但因爲長度是函數1e5
,時間複雜度爲O(n^2)
級別,故此法做廢。
2.經過查看官方題解,瞭解到這道題能夠使用動態規劃去作,能夠將時間複雜度優化到O(n)
級別,爲方便查閱複習,現結合本身的理解寫下該題解。具體以下:優化
能夠定義一個數組f[i][j]
,表示符合要求的最小的操做數,即便leaves[]
數組從0到i的值符合題目規範的最小的操做數。i的範圍是[0,leaves.length)
,j的範圍是[0,2],其中0表示當前葉子爲紅色(在黃色前面),1表示當前葉子爲黃色,2表示當前葉子爲紅色(在黃色後面)。code
初始時f[0][0]
的值會由第一片葉子的顏色決定。下面分狀況討論j的不一樣值的狀況:leetcode
(1)當j=0時,f[i][0] = f[i-1][0] + isYellow(i)
。isYellow函數會根據葉子的顏色返回對應的布爾值;同時需注意j=0這種狀況下i最大爲leaves.length-3,由於題目要求每部分葉子數量至少爲1個;get
(2)當j=1時,f[i][1] = min(f[i-1][0],f[i-1][1]) + isRed(i)
。該葉子左面的葉子的顏色多是紅色,也多是黃色,取造成前面兩種狀況操做的最小值便可。同時須要判斷當前葉子是否黃色。在這種狀況下i最大值爲leaves.length-2,最小值爲1;string
(3)當j=2時,f[i][2] = min(f[i-1][1],f[i-1][2]) + isYellow(i);
。該葉子左面的葉子的顏色多是紅色,也多是黃色,取造成前面兩種狀況操做的最小值便可。同時須要判斷當前葉子是否爲紅色。在這種狀況下i最大值爲leaves.length-1,最小值爲2;io
最終返回結果爲f[leaves.length - 1]
。
//一開始是用函數調用的,但超時,故直接判斷 class Solution { public: /* bool isYellow(string leaves, int u){ return (leaves[u] == 'y'); } bool isRed(string leaves, int u){ return (leaves[u] == 'r'); } */ int minimumOperations(string leaves) { int len = leaves.length(); vector<vector<int> > f(len, vector<int>(3, INT_MAX)); //f[0][0] = isYellow(leaves, 0); f[0][0] = (leaves[0] == 'y'); for(int i = 1; i < len; i++){ int yellow = (leaves[i] == 'y'); int red = (leaves[i] == 'r'); if(i < len - 2){ //f[i][0] = f[i-1][0] + (int)isYellow(leaves, i); f[i][0] = f[i-1][0] + yellow; } if(i >= 1 && i < len - 1){ //f[i][1] = min(f[i-1][0],f[i-1][1]) + (int)isRed(leaves, i); f[i][1] = min(f[i-1][0],f[i-1][1]) + red; } if(i >= 2){ //f[i][2] = min(f[i-1][1],f[i-1][2]) + (int)isYellow(leaves, i); f[i][2] = min(f[i-1][1],f[i-1][2]) + yellow; } } return f[len - 1][2]; } };