Day31:整数中1出现的次数

时间:2022-07-24
本文章向大家介绍Day31:整数中1出现的次数,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

剑指Offer_编程题——整数中1出现的次数(从1到n整数中1出现的次数)

题目描述:

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

具体要求:

时间限制: C/C++ 1秒,其他语言2秒 空间限制: C/C++32M,其他语言64M

具体思路:

  由于本题比较简单,因此思路也是很清晰,其中最直接的就是遍历i到n,把每个整数转化为string,然后转化做char[],判断每一位上1的个数。具体分别用java和python实现。 1、首先用java实现:

public class Solution{
	public int NumberOf1Between1AndN_Solution(int n){
		if(n <= 0)
			return 0;
		int sum = 0;
		for(int i = 1; i <= n; i++){
			char[] cs = String.valueOf(i).toCharArray();
			for(char c: cs){
				if(c - '1' == 0)
					sum++;
			}
		}
		  return sum;
	}
}

代码效果图如图所示:

2、接下来我们用python实现

class Solution:
	def NumberOf1Between1AndN_Solution(self, n):
		if n < 1:
			return 0
		mult, sumTimes = 1, 0
		while n // mult:
			div, mod = divmod(n, mult*10)
			curNum, curMod = divmod(mod, mult)
			if curNum > 1:
				sumTimes += div * mult + mult
			elif curNum == 1:
				sumTimes += div * mult + curMod + 1
			else:
				sumTimes += div*mult
			mult = mult * 10
		return sumTimes

代码效果图如图所示:

  以上做法尽管代码可以通过测试,并且思路很清晰,很好实现。但是由于需要额外的空间来保存每个数字转化为字符的数组,有点浪费空间,因此我们可以直接用数字除十来求值取余即可。大大减少了空间的浪费,提高了代码运行的速度。我们也用java和python将其实现。 1、首先用java实现呢:

public class Solution{
	public int NumberOf1Between1AndN_Solution(int n) {
    int cnt = 0;
    for (int m = 1; m <= n; m *= 10) {
        int a = n / m, b = n % m;
        cnt += (a + 8) / 10 * m + (a % 10 == 1 ? b + 1 : 0);
    }
    return cnt;
	}
}

代码效果图如图所示:

2、接下来用python实现

class Solution:
	def NumberOf1Between1AndN_Solution(self, n):
		mult, sumTimes = 1, 0
		while n // mult > 0:
			high, mod = divmod(n, mult*10)
			curNum, low = divmod(mod, mult)
			if curNum > 1:
				sumTimes += high * mult + mult
			elif curNum == 1:
				sumTimes += high * mult + low + 1
			else:
				sumTimes += high * mult
			mult = mult * 10
		return sumTimes

代码效果图如图所示:

  本来此题到此为止已经结束了,但是如果我们把题目稍微的拓展一下,即将整数中1出现的次数改为**整数中任意数X出现的次数。**即原来的题目变为:

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

  其实还是和之前提到的差不多,只需要将原来的判断条件1换成x即可,具体用python实现如下:

class Solution:
	def NumberOfXBetween1AndN_Solution(self, n, x):
		mult, sumTimes = 1, 0
		while n // mult > 0:
			high, mod = divmod(n, mult * 10) 
			curNum, low = divmod(mod, mult)
			if curNum > x:
				sumTimes += high * mult + mult
			elif curNum == x:
				sumTimes += high * mult + low + 1
			else:
				sumTimes += high * mult
			mult = mult * 10
		return sumTimes

总结

  本道题主要是简单的考察了从数字1-n中1出现的次数,这个题目思路很清晰,我们分别用java和python很容易就实现了,但是,发现其效率执行很低,关键还浪费了很多的空间,因此,我们又找到了一种改进的方式,直接用数学中的取整和取模来进行优化,并且分别用java和python将其实现。发现其空间和时间复杂度均降低了不少。另外,我们还将此题扩展了一下,将从1~n整数中1出现的次数改为了从1-n整数中任意数x出现的次数,并且用python将其实现。因此,我们在做题的时候,应该多次尝试各种方法,扩展自己的思维,写出优质的代码。总之,我们要继续加油,争取早日找到工作,Good Luck!!!

参考文献

[1] 夏臻Rock [2] goddaniel