zoukankan      html  css  js  c++  java
  • [leetCode]剑指 Offer 43. 1~n整数中1出现的次数

    在这里插入图片描述

    递归

     直观思路是遍历每一个数字,对每一个数字采用“%”“/”的方法取个位判断是否为1然后累加。由于数字n有O(logn)为所以时间复杂度为O(nlogn)。应该考虑更快的算法。
     假设输入的数字n为21345,可以把它分为两部分:

    • 1~1345
    • 1346~21345

    先来分析1345~21345这部分。从万位开始万位出现1的次数为10000,因为可取10000 ~ 19999,1出现了10000次。剩余4位1出现的次数又是多少呢?把1345 ~ 21345 再分为两部分:

    • 1346 ~ 11345
    • 11346 ~ 21345
      由排列组合可知这两部分剩下4为每一位都可以取1,取1后剩下的3位有0~9种取法所以一共有 2 ∗ C 4 1 ∗ 1 0 3 = 8000 2 * C_4^1 * 10^3 =8000 2C41103=8000种。

    最后剩下的1~1345 可以递归求解。由于递归的次数为n的位数所以时间复杂度位O(logn)

    class Solution {
    
        public int countDigitOne(int n) {
            if(n <=  0) return 0;
            // 为方便递归计算将数字转换为字符串
            String strN = String.valueOf(n);
            return countDigitOne(strN);
        }
    
        private int countDigitOne(String strN) {
            int len = strN.length();
            if(strN == null || len == 0) 
                return 0;
            // 第一位数字
            int first = strN.charAt(0) - '0';
    
            // strN只有1位,且为0
            if(len == 1 && first == 0)
                return 0;
            // strN只有一位1只能出现1次
            if(len == 1 && first > 0)
                return 1;
            // 假设strN是21345
            // numOfFirstDigit是第一位1出现的数目:10000~19999;
            int numOfFirstDigit = 0;
            if(first > 1)
                numOfFirstDigit = powerBase10(len - 1);
            else if(first == 1)
                // 最后要+1 因为first本身为1
                numOfFirstDigit = Integer.valueOf(strN.substring(1,len)) + 1;
            // numOfOtherDigits是1346~21345中除第一位外的数位中的数目
            int numOfOtherDigits = first * (len - 1) * powerBase10(len - 2);
            // 1~1345中的数目
            int numRecursive = countDigitOne(strN.substring(1,len));
            return numOfFirstDigit + numOfOtherDigits + numRecursive;
        }
    
        // 求10的n次幂
        private int powerBase10(int n) {
            int result = 1;
            for(int i = 0; i < n; ++i) {
                result *= 10;
            }
            return result;
        }
    }
    
  • 相关阅读:
    DownloadManager
    Android(蓝牙)
    Android下集成Paypal支付
    java 网络(socket)
    java 泛型的几点备忘
    设计模式(模板方法)
    STM32F4_引领入门
    如何查找STM32开发资料
    Keil(MDK-ARM)使用教程(三)_在线调试
    Keil(MDK-ARM)使用教程(二)_菜单
  • 原文地址:https://www.cnblogs.com/PythonFCG/p/13859948.html
Copyright © 2011-2022 走看看