zoukankan      html  css  js  c++  java
  • 动态规划-数位dp-600. 不含连续1的非负整数

    2020-05-17 16:31:41

    问题描述:

    给定一个正整数 n,找出小于或等于 n 的非负整数中,其二进制表示不包含 连续的1 的个数。

    示例 1:

    输入: 5
    输出: 5
    解释:
    下面是带有相应二进制表示的非负整数<= 5:
    0 : 0
    1 : 1
    2 : 10
    3 : 11
    4 : 100
    5 : 101
    其中,只有整数3违反规则(有两个连续的1),其他5个满足规则。
    说明: 1 <= n <= 109

    问题求解:

    解法一:计算至少有一次出现连续1的个数

        int[] digits = new int[32];
        int[][][][] dp = new int[32][2][2][2];
        
        public int findIntegers(int num) {
            int total = num + 1;
            int pos = 0;
            while (num > 0) {
                digits[pos++] = num % 2;
                num /= 2;
            }
            
            for (int i = 0; i < 32; i++) {
                for (int j = 0; j < 2; j++) {
                    for (int k = 0; k < 2; k++) {
                        Arrays.fill(dp[i][j][k], -1);
                    }
                }
            }
            
            return total - dfs(pos - 1, 1, 0, 0);
        }
        
        private int dfs(int pos, int limit, int prev, int f) {
            if (pos == -1) return f == 1 ? 1 : 0;
            if (dp[pos][limit][prev][f] != -1) return dp[pos][limit][prev][f];
            dp[pos][limit][prev][f] = 0;
            int up = limit == 1 ? digits[pos] : 1;
            for (int i = 0; i <= up; i++) {
                int flag = 0;
                if (prev == 1 && i == 1) flag = 1;
                dp[pos][limit][prev][f] += dfs(pos - 1, limit == 1 && i == up ? 1 : 0, i, f == 1 || flag == 1 ? 1 : 0); 
            }
            return dp[pos][limit][prev][f];
        }
    

      

    解法二:直接计算不含连续1的个数

        int[] digits = new int[32];
        int[][][] dp = new int[32][2][2];
        
        public int findIntegers(int num) {
            int pos = 0;
            while (num > 0) {
                digits[pos++] = num % 2;
                num /= 2;
            }
            
            for (int i = 0; i < 32; i++) {
                for (int j = 0; j < 2; j++) {
                    Arrays.fill(dp[i][j], -1);
                }
            }
            
            return dfs(pos - 1, 1, 0);
        }
        
        private int dfs(int pos, int limit, int prev) {
            if (pos == -1) return 1;
            if (dp[pos][limit][prev] != -1) return dp[pos][limit][prev];
            dp[pos][limit][prev] = 0;
            int up = limit == 1 ? digits[pos] : 1;
            for (int i = 0; i <= up; i++) {
                if (i == 1 && prev == 1) continue;
                dp[pos][limit][prev] += dfs(pos - 1, limit == 1 && i == up ? 1 : 0, i); 
            }
            return dp[pos][limit][prev];
        }
    

      

  • 相关阅读:
    算法笔记 --- Selection Sort
    算法笔记 --- Radix Sort
    算法笔记 --- Quick Sort
    算法笔记 --- Merge Sort
    算法笔记 --- Insertion Sort
    算法笔记 --- Heap Sort
    算法笔记 --- Counting Sort
    算法笔记 --- Bubble Sort
    算法笔记 --- Tree Travers
    javaweb_JDBC
  • 原文地址:https://www.cnblogs.com/hyserendipity/p/12905712.html
Copyright © 2011-2022 走看看