将字符串翻转到单调递增

/**
 * 字符串只包含0和1,将字符串翻转到单调递增
 */
public class Test {

    /**
     * 两种方法计算的值是一致的
     * @param args
     */
    public static void main(String[] args) {
        String str = "000000110011111000111110";
        System.out.println( getMinFlip(str) == minFlipsMonoIncrb(str));

    }


    /**
     * 这种方法比较直接,将字符串分为两部分,第一部分统计1的个数,第二部分统计0的个数,再相加
     * 时间复杂度为O(N^2)
     * @param S
     * @return
     */
    public  static  int minFlipsMonoIncrb(String S) {
        int result = S.length();
        for (int i = 0; i < S.length(); i++) {
            char[] str1 = S.substring(0, i).toCharArray();
            char[] str2 = S.substring(i + 1, S.length()).toCharArray();
            int zero = 0;
            int one = 0;
            for (int j = 0; j < str1.length; j++) {
                if (str1[j] == '1')
                    zero++;
            }
            for (int j = 0; j < str2.length; j++) {
                if (str2[j] == '0')
                    one++;
            }
            int re = zero + one;
            if (re < result)
                result = re;
        }
        return result;
    }


    /**
     * 这种方法在计算int[] one 和int[] zero数组时候,利用了前一个下标的值来计算后一个的值
     * 时间复杂度为O(N)
     * @param str
     * @return
     */
    public  static  int getMinFlip(String str){
        int len = str.length();
        int [] one = new int[len];  // [i] = a 从左边开始统计,下标为i时,左边的1的个数为a
        int[] zero = new int[len]; // [i] = b 从右边开始统计,下标为i时,右边的0的个数为b

        if(str.charAt(0) == '1'){
            one[0] = 1;
        }else {
            one[0] = 0;
        }
        for (int i = 1; i<len; i++){
            if(str.charAt(i) == '1'){
                one[i] = one[i-1]+1;
            }else {
                one[i] = one[i - 1];
            }
        }

        if(str.charAt(len-1) == '0'){
            zero[len-1] = 1;
        }else{
            zero[len-1] = 0;
        }
        for(int j = len-2;j>=0;j--){
            if(str.charAt(j) == '0'){
                zero[j] = zero[j + 1] + 1;
            }else{
                zero[j] = zero[j+1];
            }
        }

        //one[len-1] 表示的意思是当把字符串变为全0时,要翻转的步数
        //zero[0] 表示的意思是当把字符串变为全1时,要翻转的步数
        int min = Integer.min(zero[0], one[len - 1]);
        for(int k = 0; k < len-1; k++){
            int temp = zero[k+1] + one[k] ;
            //one[k] + zero[k+1] 组成一个分割点
            min = Integer.min(temp, min);
        }

        return min;

    }

}
原文地址:https://www.cnblogs.com/moris5013/p/12054911.html