编程之美1:那些关于1的个数的经典面试题

那些关于1的个数的经典面试题

好长时间没有练算法了,笔试题一做,发现非常吃力,所以近日来找来《编程之美》一书来看看练练。为了激励自己多练,楼楼可能会出个专栏什么的,感兴趣的同学我们可以一起抱团,楼楼也会保证每天都会更新。那今天呢,就是《编程之美》的第一题了,原题叫做“1”的数目,楼楼会把这道题还有相关的一些题都会记录下来,下面要开始了哦,Are you ready?

题目1 给定一个十进制正整数N,写下从1开始,到N的所有整数,然后数一下其中出现的所有“1”的个数

  • 解法1 暴力穷举

我相信如果是我们正在处于笔试或者面试的当场,暴力穷举肯定是我们的第一个想法。一个一个算,算出1中出现“1”的个数,再算出2中出现“1”的个数,依次类推,直到N中“1”的个数,然后相加得出最后的结论。我们看代码:

#include <iostream>  

using namespace std;  
int getOneShowTimes(unsigned int n) ;
int getOneShowSumTimes(unsigned int N) ;

int main()  
{  
    unsigned int N = 123;
    cout << "1出现的次数为:" << getOneShowSumTimes(N) << endl;
    system("pause");
}  

int getOneShowSumTimes(unsigned int N) 
{
    unsigned int count = 0;
    for (unsigned int i = 0; i <= N; i++)
    {
        count += getOneShowTimes(i);
    }
    return count;
}

int getOneShowTimes(unsigned int n) 
{
    unsigned count = 0;
    while(0 != n) 
    {
        count += (n % 10) == 1 ? 1 : 0;
        n /= 10;
    }
    return count;
}

我们分析一下复杂度,外层循环要循环N次,内存循环要循环 log10N+1 次,所以总的复杂度为 O(N(log10N+1)) ,可以看出这个复杂度是比较高的。

下面我们想想,有没有更简单的办法呢?比如对于一个三位数123而言,“1”只能在个位出现,或者十位出现或者千位出现。如果是按照这个原理来统计的,那我们可以完全将外层循环降低到 log10N+1 次。那我们来写几个例子来寻找一下规律。

  • 解法2 逐位统计法

如123,那么

个位出现1 十位出现1 百位出现1
1 10 100
11 11 101
21 12 102
31 13 103
41 14 104
51 15
61 16
71 17
81 18
91 19
101 110
111
121 119 123
共计13次 共计20次 共计24次
猜想公式 N/10+1 猜想公式 (N/100+1)10 猜想公式 (N/1000)100+N%100+1

但是在这里有我们有几个特殊的情况需要特别考虑,如相应的位数为0怎么办?比如51和50结果是完全不一样的。还有相应的位数为1怎么办?12和22的结果也是不一样的。我下面把结果罗列出来,大家也可以试着推导一下。

分情况 个位出现1 十位出现1 百位出现1
bit = 0
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值