25.在从1到n的正数中1出现的次数

http://zhedahht.blog.163.com/blog/static/25411174200732494452636/

http://www.cnblogs.com/GoAhead/archive/2012/05/28/2521415.html

http://blog.csdn.net/sjf0115/article/details/8600599

题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。

例如输入12,从1到12这些整数中包含1 的数字有1,10,11和12,1一共出现了5次。

分析:这是一道广为流传的google面试题。

普通n*lg(n)的解法。


/////////////////////////////////////////////////////////////////////////////
// Find the number of 1 in an integer with radix 10
// Input: n - an integer
// Output: the number of 1 in n with radix
/////////////////////////////////////////////////////////////////////////////
int NumberOf1(unsigned int n)
{
int number = 0;
while(n)
{
if(n % 10 == 1)
number ++;

n = n / 10;
}

return number;
}

/////////////////////////////////////////////////////////////////////////////
// Find the number of 1 in the integers between 1 and n
// Input: n - an integer
// Output: the number of 1 in the integers between 1 and n
/////////////////////////////////////////////////////////////////////////////
int NumberOf1BeforeBetween1AndN_Solution1(unsigned int n)
{// T(n) = n*lg(n)
int number = 0;

// Find the number of 1 in each integer between 1 and n
for(unsigned int i = 1; i <= n; ++ i)
number += NumberOf1(i);

return number;
}

更加巧妙的lg(n)的解法。

简单的方法就是按照给位进行分析:

在个位出现1的个数=n/10+(个位=0,0;个位>1,1;个位=1,低0位+1);

十位位出现1的个数=n/100*10+(十位=0,0;十位>1,10;十位=1,低一位+1);

百位出现1的个数=n/1000*100+(百位=0,0;百位>1,100;百位=1,低两位+1);

等等

算法的复杂度仅仅和位数有关。

设第i位出现1的个数为s(i),N为输入整数n的位数。则总和sum= s(1)+…s(i)+…s(N)即为所求。

设bi为整数n的第i位数字,第i位之后的剩余数字为ri;

s(i) = A + B

A = n/10i*10i-1

bi=( n/10i-1)%10

ri= n/10i-1

b(i)==0 ,则B=0

b(i)==1 ,则B=ri+1

b(i)>1 ,则B=10i-1


int PowerBase10(unsigned int n)
{// 10^n
int result = 1;
for(unsigned int i = 0; i < n; ++ i)
result *= 10;

return result;
}

int b10(unsigned int n)
{
return PowerBase10(n);
}

int NumberBitCount(unsigned int n)
{
int N = 0;
while(n)
{
n = n/10;
N++;
}
return N;
}

int NumberOf1BeforeBetween1AndN_Solution2(unsigned int n)
{// T(n) = o(N) = o(lgn)
int N = NumberBitCount(n);
int si,sum=0;
int A,B,bi,ri;
for (int i=1;i<=N;i++)
{
A = n/b10(i)*b10(i-1);
bi = n/b10(i-1)%10;
ri = n%b10(i-1);
if (bi==0)
{
B = 0;
}
else if (bi==1)
{
B = ri+1;
}
else if (bi>1)
{
B = b10(i-1);
}
si = A+B;
sum +=si;
}

return sum;
}

25.在从1到n的正数中1出现的次数

时间: 2024-08-06 02:10:03

25.在从1到n的正数中1出现的次数的相关文章

【编程题目】在从 1 到 n 的正数中 1 出现的次数

30.在从 1 到 n 的正数中 1 出现的次数(数组)题目:输入一个整数 n,求从 1 到 n 这 n 个整数的十进制表示中 1 出现的次数.例如输入 12,从 1 到 12 这些整数中包含 1 的数字有 1, 10, 1 1 和 12, 1 一共出现了 5 次. 思路:如1121 判断 千位 1出现了多少次:10000 有 0 个 有0个完整的 1000次千位 1, 千位数为1,说明本次千位还没有走完 后面的数字为 121 说明本次千位1走了 122个判断 百位 1出现了多少次:1000 有

在从1到n的正数中1出现的次数

网上很多帖子写这个问题,看了下方法基本上是以下两种:爆破.按位统计,但是按位统计都写了很长的统计过程,其实就是一个动态规划的过程 f(n) = f(n/10) * 10 + n/10 + 1  当n%10 != 0 时,否则为f(n) = f(n/10) * 10 + n/10 下面解释下第一种情况(后面的是特例,也很好理解) 公式中红色部分:固定个位数1,1-9中只有1个1:大于9的数中固定个位数为1,则起始数为11,结束值为X1,这里X为n/10,共n/10个数 公式中蓝色部分:对于子问题f

从给定的N个正数中选取若干个数之和为M

#include <iostream> #include <list> using namespace std; void find_seq(int sum, int index, int * value, list<int> & seq) { if(sum <= 0 || index < 0) return; if(sum == value[index]) { printf("%d ", value[index]); for(l

算法笔试

1.把二元查找树转变成排序的双向链表 题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表.要求不能创建任何新的结点,只调整指针的指向.   10  / \  6  14 / \ / \4  8 12 16 转换成双向链表4=6=8=10=12=14=16.  首先我们定义的二元查找树 节点的数据结构如下: struct BSTreeNode{  int m_nValue; // value of node  BSTreeNode *m_pLeft; // left child of

数据结构与算法80道

1. 把二元查找树转变成排序的双向链表 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表. 要求不能创建任何新的结点,只调整指针的指向. 10 / \ 6 14 / \ / \ 4 8 12 16 转换成双向链表 4=6=8=10=12=14=16. 首先我们定义的二元查找树 节点的数据结构如下: struct BSTreeNode { int m_nValue; // value of node BSTreeNode *m_pLeft; // left child of no

算法1

1.把二元查找树转变成排序的双向链表 题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表.要求不能创建任何新的结点,只调整指针的指向.   10  / \  6  14 / \ / \4  8 12 16 转换成双向链表4=6=8=10=12=14=16.  首先我们定义的二元查找树 节点的数据结构如下: struct BSTreeNode{  int m_nValue; // value of node  BSTreeNode *m_pLeft; // left child of

数据结构与算法面试题80道

由于这些题,实在太火了.所以,应广大网友建议要求,在此把之前已整理公布的前80题, 现在,一次性分享出来.此也算是前80题第一次集体亮相. 此些题,已有上万人,看到或见识到,若私自据为己有,必定为有知之人识破,付出代价. 所以,作者声明: 本人July对以上所有任何内容和资料享有版权,转载请注明作者本人July出处. 向你的厚道致敬.谢谢. ------------------------------------------------------------------------------

算法面试:精选微软等公司经典的算法面试100题 第1-40题

精选微软等公司,数据结构+算法,经典面试100题                            --------之前40题 -------------------------- 算法面试:精选微软等公司经典的算法面试100题 第1-40题如下: --------------- --------------1.把二元查找树转变成排序的双向链表 题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表.要求不能创建任何新的结点,只调整指针的指向.      10  / \ 6 14 

(转)面试算法总结

1.把二元查找树转变成排序的双向链表 题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表.要求不能创建任何新的结点,只调整指针的指向.   10  / \  6  14 / \ / \4  8 12 16 转换成双向链表4=6=8=10=12=14=16.  首先我们定义的二元查找树 节点的数据结构如下: struct BSTreeNode{  int m_nValue; // value of node  BSTreeNode *m_pLeft; // left child of