926. Flip String to Monotone Increasing

问题:

给定01组成的字符串,求反转(0->1 or 1->0)最少次数,使得成为0...001..11(0..00 or 1..11)这样的单调增字符串。求反转次数。

Example 1:
Input: "00110"
Output: 1
Explanation: We flip the last digit to get 00111.

Example 2:
Input: "010110"
Output: 2
Explanation: We flip to get 011111, or alternatively 000111.

Example 3:
Input: "00011000"
Output: 2
Explanation: We flip to get 00000000.
 
Note:
1 <= S.length <= 20000
S only consists of '0' and '1' characters.

  

解法:

DP动态规划:

dp[i]到第i个字符的最少反转次数。->coutflip

cout1[i]出现1的次数=1->0的次数

状态转移方程:

选择:S[i]作为最后一个字符被加进来的时候,

if S[i]=1 then

选择不反转:(现在是后半段)coutflip[i-1]。

选择反转(1->0):(现在是前半段)cout[i](还没做过选择,因此为可表示的固定值)

求两者中的最小:coutflip[i]=min(coutflip[i-1], cout[i])

if S[i]=0 then

选择反转(0->1):(现在是后半段)coutflip[i-1]+1(上次的结果+本次反转)

选择不反转:(现在是前半段)cout1[i-1] (所有1的反转次数)(还没做过选择,因此为可表示的固定值)

求两种选择下的最小值:coutflip[i]=min(coutflip[i-1]+1, cout1[i-1])

 

⚠️注意:

前半段的时候,cout1[i]>=coutflip[i]

后半段的时候,由于不只反转1,还变化的反转了0,因此二者大小不确定了。

 

代码参考:

 1 class Solution {
 2 public:
 3     int minFlipsMonoIncr(string S) {
 4         int coutflip=0, cout1=0;
 5         for(char a:S){
 6             if(a=='1') cout1++;
 7             else coutflip++;
 8             coutflip=min(coutflip, cout1);
 9         }
10         return coutflip;
11     }
12 };

 

posted @ 2020-05-24 14:04  habibah_chang  阅读(122)  评论(0编辑  收藏  举报