剑指offer | 从1到n整数中1出现的次数 | 22


思路分析

最简单的做法就是一位一位数字取出,看看是否为1

取数

cpp

class Solution {
public:
    
    int numberOf1Between1AndN_Solution(int n) {
        int s = 0;
        for(int i=1;i<=n;i++){
            int t =i;
            while(t){
                if(t%10==1)s+=1;
                t/=10;
            }
        }
        return s;
    }
};

python

class Solution(object):
    def numberOf1Between1AndN_Solution(self, n):
        """
        :type n: int
        :rtype: int
        """
        s = 0
        for i in range(1,n+1):
            t = i
            while t:
                if t%10==1:s+=1
                t //=10
        
        return s

高低位

按位来进行计算,分为中间位,前位,和后位,分情况进行计算,循环中间位的值
以ab c def为例,中间位为c
(1) c = 1   则个数 += (ab - 1)  * 1000(def位数)
(2) 前位取ab c = 0,则不加
        c = 1 则个数 += def + 1
        c > 1 则个数 += 1000(def位数)
自己可举详细例子进行尝试  例如12  
(1) 中间位 = 1  前位为0,后位为2  则个数 += 2 + 1 = 3  这里 c = 1的情况
(2)中间位 = 2   前位为1,后位为0  则个数 += 1 + 1 = 2  这里(ab - 1) = 0 一种情况  还有一种c > 1 的情况
总数即为 5



每次就是考虑c这个位置.

首先
res += (0~ab-1)*t

高位=ab
    1) c=0: 那么就没有情况了,因为只考虑c位
    2) c=1: 低位可以取 0~right,有 right+1个
    3) c>1: 那么只有c=1这一种情况,那么就只能加上t,也就是(0~999)

cpp

class Solution {
public:
    int numberOf1Between1AndN_Solution(int n) {
        vector<int> nums;
        while(n)nums.push_back(n%10),n/=10;
        int res=0;
        for(int i=nums.size()-1;i>=0;i--){
            int left=0,right=0,t=1;
            for(int j=nums.size()-1;j>i;j--) left = left*10+nums[j];
            for(int j=i-1;j>=0;j--)right = right*10 + nums[j],t*=10;
            res += left * t;
            if(nums[i]==1)res += right+1;
            else if(nums[i]>1) res += t;
        }
        return res;
    }
};

python

class Solution(object):
    def numberOf1Between1AndN_Solution(self, n):
        """
        :type n: int
        :rtype: int
        """
        res = 0
        nums = []
        while n:
            nums.append(n%10)
            n//=10
        nums = nums[::-1]
                    
        for i,x in enumerate(nums):
            left,right,t=0,0,1
            for j in range(i):
                left = left*10 + nums[j]
            for j in range(i+1,len(nums)):
                right = right*10 + nums[j]
                t *=10
            res += left * t
            if nums[i]==1 :res += right+1
            elif nums[i]>1 :res+=t
            
            
        return res
原文地址:https://www.cnblogs.com/Rowry/p/14312106.html