zoukankan      html  css  js  c++  java
  • 整数中1出现的次数(从1到n整数中出现的次数)

    题目描述

    求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

     简单的方法:对10取模求得每一位的数,时间复杂度O(nlogn)

    class Solution {
    public:
        int NumberOf1Between1AndN_Solution(int n)
        {
            if(n <= 0) return 0;
            int sum = 0;
            while(n){
                sum += weishu(n);
                n--;
            }
            return sum;
        }
        int weishu(int n){
            int sum = 0;
            while(n){
                if(n % 10 == 1)
                    sum++;
                n /= 10;
            }
            return sum;
        }
    };

    或者将数字转为字符串,对每一位进行判断

    剑指offer的思路:利用数学规律

    这里要注意的是类似100这种情况还有首位为1的情况

    public class Solution {
        public int NumberOf1Between1AndN_Solution(int n) {
            if(n <= 0) return 0;
            String number = n+"";
            return NumberOf1("1",number,number.length());
        }
        public int NumberOf1(String startNum,String endNum,int endNumWei){
            if(endNumWei == 1)
                return 1;
            if(startNum == "1"){
                String subNum = endNum.substring(1);
                while(subNum.length()>0&&subNum.charAt(0) == '0'){
                    subNum = subNum.substring(1);
                }
                if(subNum.length()==0) {
                    int sumOne = 0;
                    for(int i=0;i<endNum.length();i++){
                        if(endNum.charAt(i)=='1')
                            sumOne++;
                    }
                    endNum = (strToint(endNum)-1)+"";
                    return sumOne + NumberOf1("1",endNum,endNum.length());
                }
                else
                    return NumberOf1(subNum,endNum,endNumWei) +
                        NumberOf1("1",subNum,subNum.length());
            }else{
                if(endNum.charAt(0) != '1')
                    return (int)(Math.pow(10.0,endNumWei-1) + ((int)endNum.charAt(0)-(int)('0')) * (endNumWei-1) * Math.pow(10.0,endNumWei-2));
                else{
    
                    return strToint(endNum.substring(1))+1 + (endNumWei-1) * (int)Math.pow(10.0,endNumWei-2);
                }
            }
        }
        public int strToint(String str){
            int sum = 0;
            for(int i=0;i<str.length();i++)
                sum = sum * 10 + (int)(str.charAt(i)-'0');
            return sum;
        }
    }

     还是没有书上的算法简洁:

    class Solution {
    public:
        int NumberOf1Between1AndN_Solution(int n)
        {
            if(n<=0) return 0;
            char strN[50];
            sprintf(strN, "%d", n);
            return NumberOf1(strN);
        }
        int NumberOf1(char* strN){
            if(*strN <'0'||*strN>'9')
                return 0;
            unsigned int len = static_cast<unsigned int>(strlen(strN));
            int first = *strN - '0';
            if(len == 1 && first == 0)
                return 0;
            if(len == 1 && first > 0)
                return 1;
            
            //计算首位为1的个数
            int numFirstDigit = 0;
            if(first == 1)
                numFirstDigit = atoi(strN+1)+1;
            else if(first > 1)
                numFirstDigit = (int)pow(10.0, len-1);
            int otherDigits = first *(len-1)*(int)pow(10.0, len-2);
            int recurisiveDigits = NumberOf1(strN+1);
            return numFirstDigit + otherDigits + recurisiveDigits;
        }
    };
  • 相关阅读:
    HDU3336 Count the string —— KMP next数组
    CodeForces
    51Nod 1627 瞬间移动 —— 组合数学
    51Nod 1158 全是1的最大子矩阵 —— 预处理 + 暴力枚举 or 单调栈
    51Nod 1225 余数之和 —— 分区枚举
    51Nod 1084 矩阵取数问题 V2 —— 最小费用最大流 or 多线程DP
    51Nod 机器人走方格 V3 —— 卡特兰数、Lucas定理
    51Nod XOR key —— 区间最大异或值 可持久化字典树
    HDU4825 Xor Sum —— Trie树
    51Nod 1515 明辨是非 —— 并查集 + 启发式合并
  • 原文地址:https://www.cnblogs.com/ttzz/p/13974708.html
Copyright © 2011-2022 走看看