第三十题(从1到n的正数中出现1的次数 )

2024-08-29 17:48
文章标签 次数 正数 第三十

本文主要是介绍第三十题(从1到n的正数中出现1的次数 ),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

给出两种方法

第一种是时间效率较低的常规方法,遍历1~n,求出每个数中1的个数,将求出的所有结果求和即可。

第二种方法基于这个规律:1~10^n-1的所有整数中1的出现的次数总和为n*10^(n-1)。

对于一个整数,按照最高位是否为1分两种情况讨论:

若最高位为1,例如数字12345,可以分为

1~9999,10000~12345两部分,1~9999中1出现的次数总和可以用上述规律求得为4*10^3

10000~12345所有数的最高位1的总数为2345+1(10000最高位的1

而10001~12345所有数后四位中1的个数总和0~2345中1的个数总和相同,相当于求1~2345中1的个数总和,这是原问题的子问题,可以通过递归求解。


若最高位大于1,例如数字3456,可以这样划分:

第一,1~9999,10000~19999的后四位 利用上面给出的规律,为2*4*10^3

第二,10000~19999的最高位1的个数总和,为(2-1)*10^4

第三,20001~23456中后四位中1的个数总和,相当于1~3456中1的个数总和,同理采用递归求解。

代码如下:

#include "stdafx.h"
#include<iostream>
using namespace std;
namespace MS100P_30
{int count1OfNumber_method1(int number){int count=0;int temp;for (int i = 1; i <= number; i++){temp = i;while (temp != 0){if (temp % 10 == 1)	count++;temp /= 10;}}return count;}int count1OfNumber_method2(int number){if (number >= 1 && number <= 9)	return 1;if (number == 0)	return 0;int digits = 0,sum=0;int temp = number;while (temp != 0)	//求位数{temp /= 10;digits++;}int highDigit = number / (int)pow(10, digits-1);	//最高位数字int remaider = number % ((int)pow(10, digits - 1));if (highDigit == 1){sum += (remaider + 1);sum += (digits-1)*pow(10, digits - 2);	sum += count1OfNumber_method2(remaider);}else{sum = highDigit*(digits-1)*pow(10, digits - 2) + pow(10, digits - 1) + count1OfNumber_method2(remaider);}return sum;}void test(){cout << count1OfNumber_method1(24567) << endl;cout << count1OfNumber_method2(24567) << endl;cout << count1OfNumber_method1(12345) << endl;cout << count1OfNumber_method2(12345) << endl;}
}int _tmain(int argc, _TCHAR* argv[])
{MS100P_30::test();return 0;
}



这篇关于第三十题(从1到n的正数中出现1的次数 )的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1118543

相关文章

hdu 3065 AC自动机 匹配串编号以及出现次数

题意: 仍旧是天朝语题。 Input 第一行,一个整数N(1<=N<=1000),表示病毒特征码的个数。 接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。 在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。

C语言练习题之 数组中出现次数超过一半的数

题目描述 给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。 数据范围:n≤50000,数组中元素的值0≤val≤10000 要求:空间复杂度:O(1),时间复杂度O(n) 输入描述: 保证数组输入非空,且保证有

【每日一题】LeetCode 2379.得到K个黑块的最少涂色次数(字符串、滑动窗口)

【每日一题】LeetCode 2379.得到K个黑块的最少涂色次数(字符串、滑动窗口) 题目描述 给定一个字符串 blocks,其中每个字符代表一个颜色块,可以是 ‘W’(白色)或 ‘B’(黑色)。你需要找到一个至少包含 k 个连续黑色块的子串。每次操作可以将一个白色块变成黑色块。你的任务是找到至少出现一次连续 k 个黑色块的最少操作次数。 和该题目类似:【每日一题】LeetCode 202

43. 1 ~ n 整数中 1 出现的次数【难】

comments: true difficulty: 中等 edit_url: https://github.com/doocs/leetcode/edit/main/lcof/%E9%9D%A2%E8%AF%95%E9%A2%9843.%201%EF%BD%9En%E6%95%B4%E6%95%B0%E4%B8%AD1%E5%87%BA%E7%8E%B0%E7%9A%84%E6%AC%A1%

0to1使用Redis实现“登录验证”次数限制

1 引言 系统为了避免密码遭到暴力破解,通常情况下需要在登录时,限制用户验证账号密码的次数,当达到一定的验证次数后,在一段时间内锁定该账号,不再验证。本章将用几行代码实现该功能,完整代码链接在文章最后。 2 原理介绍 可以看到在登录接口中,4行代码即可实现该功能,这里使用Redis可以很方便的记录“登录失败次数”,以及设置其失效时间(即锁定时间),主要步骤是: 账号登录时,当前账号“登录失

面试题41:和为s的两个数VS和为s的连续正数数列

问题说明: 1.和为s的两个数问题是从一个排序的数组中找出和为s的两个数; 2.原题是找出一个即可,现在全部找出; 3.和为s的连续正数数列是给定一个数找出所有连续正数数列的和为s,例如s为9,(2,3,4)就是其中一组。 (一)和为s的两个数问题 public static int findNumbersWithSum(int[] sorted, int fromIndex, in

LeetCode 热题100-17 缺失的第一个正数

缺失的第一个正数 给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1: 输入:nums = [1,2,0]输出:3解释:范围 [1,2] 中的数字都在数组中。 示例 2: 输入:nums = [3,4,-1,1]输出:2解释:1 在数组中,但 2 没有。 示例 3: 输

Golang-指定文本,求奇数行正数平方和

在stack看到HENNGE公司的招聘信息,于是去参加了一次线上笔试。对方法发了三道题,此为第一道题——使用Golang处理文本。 下为要求: 仔细思考后,发现一个规律: 第1行指定总行数;偶数行n指定下一行奇数行n+1行的个数;全部数据喂完后出结果,意味着最后是扔进数组,放到最后遍历。 提示: 要求不能使用for;只能使用基本库。 因为Golang的循环语句出来了for,只剩下g

【算法】单词出现次数和位置统计

【算法】单词出现次数和位置统计 题目描述 编写一个程序,用于统计一个给定单词在一段文本中出现的次数以及第一次出现的位置。如果单词在文本中出现,则输出出现次数和第一次出现的位置(位置从0开始计算)。如果单词没有出现,则输出-1。 思路分析 使用Scanner类从控制台读取两个字符串:要搜索的文本str和要统计的单词substring。定义一个方法countStr,该方法接收两个字符串参数