今天的面试题做错了,呜呜

作者: 分类: 代码 时间: 2012-03-05 评论: 61条评论

题目是这样的:

有一个整数n,写一个函数f(n),返回0到n之间出现的"1"的个数。比如f(13)=6,现在f(1)=1,问此后最大的f(n)=n的n是什么?

回学校,敲了一下自己当时写的代码,哎呀,错误百出啊。

当时,我是这样写的……

int f(int n,int count)
{
    if(n<10)
    {
        if(n==1) count++;
        return count;
    }
    
    if(n%10==1) count++;
    
    f(n/10,count);
}

int main()
{
    for(int i=1;i<100000;i++)
    {
        if(i==f(f))
        {
            printf("%d\n",i);
            getchar();
        }
    }
}

错到我都不忍心看了。错误点有以下:

1、递归的最终结果没有返回,应该是 return f(n/10,count); 才对。

2、我这个f函数,仅仅是求了n这个数中含的1而已嘛,离题万里。于是加了一个函数:

int f(int n)
{
    int sum = 0;
    for(int i=1;i<=n;i++)
    {
        sum += f(i,0);
    }
    return sum;
}

这个只需要一个参数的f,才是符合题意的f。

3、只是草率的随便写了一个返回去搜索,当然,我现在知道,在这个范围内一个符合要求的值也没有!!

正确的应该从0到0xFFFFFFFF,当然,这个时候不能用int了,而是unsigned int。


即使把这些全部改正过来,搜索效率也依然很低,因为f是一个循环。调用f的也是一个循环。

但是,我们知道n+1,其实就是在n的基础上加上n+1这个数中的1个个数,因此最终代码如下:

#include <windows.h>
#include <stdio.h>

//返回一个数字中包含"1"的个数
unsigned int f(unsigned int n,unsigned int count)
{
    if(n<10)
    {
        if(n==1) count++;
        return count;
    }
    
    if(n%10==1) count++;
    
    return f(n/10,count);
}

//效率低,重复计算,不使用
unsigned int f(unsigned int n)
{
    unsigned int sum = 0;
    for(unsigned int i=1;i<=n;i++)
    {
        sum += f(i,0);
    }
    return sum;
}


int main()
{
    double time = GetCurrentTime();
    unsigned int temp = 0; //保存上次计算结果
    for(unsigned int i=0;i<=0xFFFFFFFF;i++)
    {
        temp = f(i,temp);
        if(i==temp) printf("%u\n",i);
    }
    
    printf("Calc Over! %f",(GetCurrentTime()-time)/1000);
    getchar();
    return 0;
}

我计算的时候终点值是0x7FFFFFFF,因为那时候我没有改成unsigned int。而且已经能够得出答案,不用继续运行浪费时间。

 

还把另外一个不使用库函数实现strcpy的题目做成了实现strcat,我怎么了……o(︶︿︶)o 唉

最后贴一个简化版的代码,结果应该是199981。

#include <stdio.h>

int main()
{
    unsigned int count,num,temp;
    count = num = temp = 0;
    
    while(1)
    {
        temp = num;
        while(temp)
        {
            if(temp%10==1) count++;
            temp /= 10;
        }
        
        if(num==count) printf("%u\n",num);
        num++;
    }
    
    return 0;
}
标签: 面试经验

已有 61 条评论

  1. 败笔
    败笔

    转化字符串后
    两层for循环
    找出所有1 不是很简单 icon_eek.gif

    时间: 2015-06-24 01:01
  2. gallium
    gallium

    递归的效率要比循环高吧,只要搞清规律,就很好写了,用循环的效率太低,毕竟1出现的次数不高。从0到9,1只出现一次,只就是递归的结束条件,首位是1的,1出现的次数等于尾数+1,就是找规律,假设数字321,百位数,那么求出0-99的1出现的次数就很好求,百位是三,就有0-99,100-199,200-299,再加上尾数21的1出现的次数,0-99和0-21的1出现的次数也一样,看0-9中1出现的次数,然后在看特殊状况下,那就是首位为1,100-199,10-19,1出现的次数是00-99和0-9即分别是100次和10次
    然后是首位为1的特殊情况,1出现的次数是尾数+1次,这样就写出了如下函数,编程菜鸟,写的不太好,请多指教。
    int fun(int end)
    {

    char tmp[32]; int count = 0; int len,num,n,m; if (end < 0) end *= -1; else if(end == 0) return 0; sprintf_s(tmp,"%d",end); len = strlen(tmp); cout<<tmp<<endl; if(len == 1) return 1; num = tmp[0] - '0'; cout<<num<<endl; n = (int) pow(10,len - 1); m = end - num*n; count += num*( fun(n - 1) ) + fun(m); if (num > 1) count += n; else count += m+1; return count;

    }

    时间: 2015-11-04 21:56

评论已关闭