《剑指offer》-整数中1出现的次数

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

直接暴力可以过。但是不优美。
尝试推导公式,思路是递归求解,发现假如n都是999,99999这种全9的数字会很好处理:f(n)=g(t)*f(h(n)), 其中t表示n的第一个位,h(n)表示n去掉第一位,g(t)要特别考虑1的情况。

但是n很可能连一个9都没有。没关系,那就把n切分成两部分,一部分是能用99999这种处理的,另一部分是再单独计算的。

而其实这两个部分是可以合并的,99999的情况是后者的特例而已。

利用数字特点和规律,计算每一位上1出现的次数:
例如百位上1出现次数,数值n在百位上的值是curNum则:

if(curNum==0)
1出现的次数等于比百位更高位数100。例如n=1023,高位数就是1,百位上出现1的次数是1100;

if(curNum==1)
1出现的次数等于比百位更高位数100,再加上低位上的数,再加1。例如n=1123,高位数就是1,低位数是23,百位上出现1的次数是1100+23+1;

if(curNum>1)
1出现的次数等于比百位更(高位数+1)100,例如n=1223,高位数就是1,次数百位上出现1的次数是(1+1)100;

而其实这种策略是适用于各个位的,不仅仅是在百位上。那么直接上码吧:

class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        int count=0;
        int factor=1;
        while(n/factor!=0){
            int curNum = (n/factor)%10;
            int lowNum = n%factor;
            int highNum = n/(factor*10);

            if(curNum==0){
                count += factor*highNum;
            }
            else if(curNum==1){
                count += factor*highNum + lowNum + 1;
            }
            else{
                count += factor*(highNum + 1);
            }
            factor *= 10;
        }
        return count;
    }
};

参考:[https://troywu0.gitbooks.io/interview/content/整数中出现1的次数(从1到n整数中1出现的次数).html]

时间: 2024-10-23 15:14:33

《剑指offer》-整数中1出现的次数的相关文章

剑指offer系列之三:在二维数组中查找元素

题目描述: 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 由于题目条件的成立,所以使得这道题可以使用对角线的方法完成,可以从右上角的元素考虑,如果目标查找元素小于右上角的元素,那么不可能在右上角元素所在的列,如果目标大于剩余列的右上角的元素,那么不可能在该右上角元素所在的行.依照这个规律,就可以完成目标元素的查找(参考剑指offer书中的思路).基于此,我写出如下的代码(已被

[剑指Offer] 第4章课后题详解

[剑指Offer] 第4章课后题详解 目录 剑指Offer 第4章课后题详解 目录 二叉树的镜像 分析 解法 拓展 判断前序遍历 分析 解法 拓展 字符的组合 分析 解答 正方体的顶点 分析 解法 8个皇后 分析 解法 二叉树的镜像 本题为<剑指Offer>"面试题19:二叉树的镜像"一节中的"本题拓展". 请完成一个函数,输入一个二叉树,该函数输出它的镜像,要求使用循环的方法,不能用递归.二叉树节点定义如下: struct BinaryTreeNode

剑指offer系列之三十:整数中1出现的次数

题目描述 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此共出现6次,但是对于后面问题他就没辙了.ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数. 有一种比较简洁的思路:由于是一个整数区间,所以可以对每一个数进行判断,那么如何判断某个数中1出现了多少次呢?注意到如果一个数一直被10除,如果被10整除后的余数是1,那么一定出现了数字1.举个例子,数字11

[剑指Offer]5.二维数组中的查找

题目 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. 思路 [算法系列之三十三]杨氏矩阵 代码 /*--------------------------------------- * 日期:2015-07-19 * 作者:SJF0115 * 题目: 5.二维数组中的查找 * 网址:http://www.nowcoder.com/books/coding-interviews/a

剑指Offer之链表中倒数第k个结点

题目描述: 输入一个链表,输出该链表中倒数第k个结点. (hint: 请务必使用链表.) 输入: 输入可能包含多个测试样例,输入以EOF结束. 对于每个测试案例,输入的第一行为两个整数n和k(0<=n<=1000, 0<=k<=1000):n代表将要输入的链表元素的个数,k代表要查询倒数第几个的元素. 输入的第二行包括n个数t(1<=t<=1000000):代表链表中的元素. 输出: 对应每个测试案例, 若有结果,输出相应的查找结果.否则,输出NULL. 样例输入: 5

剑指Offer之数值的整数次方

题目描述: 给定一个double类型的浮点数base和int类型的整数exponent.求base的exponent次方. 输入: 输入可能包含多个测试样例. 对于每个输入文件,第一行输入一个整数T,表示测试案例的数目,接下来的T行每行输入一个浮点数base和一个整数exponent,两个数中间用一个空格隔开. 输出: 对应每个测试案例, 输出一个浮点数代表答案,保留两位小数即可. 样例输入: 5 1.0 10 0.0 -5 1.0 0 1.2 5 2.0 -1 样例输出: 1.00e+00f

剑指offer之字符串转整数

题目描述: 将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数. 输入: 输入可能包含多个测试样例. 对于每个测试案例,输入为一个合法或者非法的字符串,代表一个整数n(1<= n<=10000000). 输出: 对应每个测试案例, 若输入为一个合法的字符串(即代表一个整数),则输出这个整数. 若输入为一个非法的字符串,则输出"My God". 样例输入:5-5+8样例输出:5-58    关于这道题目,题目本身还是不错的,真正核心的代码也就那么两行,大部分代码基

[剑指Offer]40.数组中只出现一次的数字

题目 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. 思路 我们直到异或的性质: 任何一个数字异或他自己都等于0. 所以说我们如果从头到尾依次异或每一个数字,那么最终的结果刚好只出现一次的数字,因为成对出现的两次的数字全部在异或中抵消了. 这道题中有两个数字只出现一次.这样的话我们得到的结果就是这两个数字的异或结果.因此我们想办法把原数组分成两个子数组,使得每个子数组包含一个只出现一次的数字.这样我们就可以对这两个子数组分别异或,就能得到两个只出现一

《剑指offer》写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。

弱菜刷题还是刷中文题好了,没必要和英文过不去,现在的重点是基本代码能力的恢复. [题目] 剑指offer 写一个函数,求两个整数之和,要求在函数体内不得使用+.-.*./四则运算符号. [思路] 直觉想到用二进制的位运算.最后写出来是一个迭代的过程. 每次迭代先计算x和y的和但不处理进位,那么相当于做异或,得到res1 然后处理进位问题,相当于计算与运算,得到res2 那么res2左移1位,再加到res1上,则整个运算的最终结果转化为res1+(res2<<1) 因为res2做左移,总会减小到