1到n中1的出现次数

https://www.nowcoder.com/practice/38af9b5a06ea4448ae9b2a488b6a991ftpId=101&tqId=33140&tPage=1&rp=1&ru=/ta/programmer-code-interview-guide&qru=/ta/programmer-code-interview-guide/question-ranking

题目描述

给定一个整数n,返回从1到n的数字中1出现的个数。

例如:

n=5,1∼n为1, 2, 3, 4, 5。那么1出现了1次,所以返回1。

n=11,1∼n为1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11。那么1出现的次数为1(出现1次),10(出现1次),11(有两个1,所以出现了2次),所以返回4。

输入描述:

输入一个整数N。

输出描述:

输出一个整数表示答案

示例

输入

2345

输出

1775

备注:

1⩽N⩽10^13

算法:

固定某一位为1,看其他位置可以变化的范围,其次使用递归将大的问题转换成小的子问题,比如21345划分成1-1345,1346-21345。

注意:每个要处理数字的最高位要特殊处理一下。

//O(logn*logn)
#include<bits/stdc++.h>
using namespace std;

int numDigits(long long num){
    int len=0;
    while(num){
        len++;
        num/=10;
    }
    return len;
}

long long solution(long long n){
    if(n<1){
       return 0;
    }
    int len=numDigits(n);
    if(1==len){
        return 1;
    }
    long long base=pow(10,len-1);
    long long first=n/base;
    long long firstDigitHas1 = first==1 ? n%base+1 : base;
    long long otherDigitHas1 = first*(len-1)*(base/10);
    return firstDigitHas1+otherDigitHas1+solution(n%base);
}

int main(){
    long long n;
    cin>>n;
    cout<<solution(n)<<endl;
    return 0;
}
#include<bits/stdc++.h>
using namespace std;

class Solution{
private:
    int numDigits(long long num){
        int len=0;
        while(num){
            len++;
            num/=10;
        }
        return len;
    }
public:
    long long countOf1(long long n){
        if(n<1){
           return 0;
        }
        int len=numDigits(n);
        if(1==len){
            return 1;
        }
        long long base=pow(10,len-1);
        long long first=n/base;
        long long firstDigitHas1 = first==1 ? n%base+1 : base;
        long long otherDigitHas1 = first*(len-1)*(base/10);
        return firstDigitHas1+otherDigitHas1+countOf1(n%base);
    }    
};

int main(){
    long long n;
    cin>>n;
    Solution sol;
    cout<<sol.countOf1(n)<<endl;
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值