zoukankan      html  css  js  c++  java
  • 课堂作业——找1

    题目:

      给定一个十进制的正整数,写下从1开始,到N的所有整数,然后数一下其中出现“1”的个数。

    要求:

      写一个函数 f(N) ,返回1 到 N 之间出现的 “1”的个数。例如 f(12) = 5;

      在32位整数范围内,满足条件的“f(N) =N”的最大的N是多少?

     

    设计思想:

    (解法一)

      开始想到了一个最简单的方法来计算f(N),那就是从1开始遍历,直到N结束,把其中每一个数中含有“1”的个数加起来,结果就是从1到N所有“1”的个数的和。这个方法很简单,但算法的实现效率是个大问题,如果N很大,则需要很长的运算时间才能得到计算结果。

    (解法二)

       找了一些资料,发现这也是编程之美里的一道题,得到一点启发。首先列出一些数字的情况,来找到其中隐藏的规律:

    一位数: f(0)=0、f(1)=1、f(2~9)=1

    两位数(以位数是3的为例,[十位]+[个位]):

    f(13)=4+2=6、f(23)=10+3=13 …… f(93)=10+10=20

     通过分析发现,个位数出现1 的个数和个位数字与十位数有关:如果N的个位数大于等于1 ,则个位出现1的个数为十位数的数字加1;如果N的个位数的数字小于1,则个位出现1的个数为十位数的数字。十位出现1的次数:如果十位数字等于1,则十位出现1的个数为个位数字加1;如果十位数大于1,则十位出现1的个数为10次。

    三位数([百位]+[十位]+[个位]):

    f(103)=4+10+11=25、f(113)=14+14+12=40、f(123)=24+20+13=57……

    f(193)=94+20+20=134、f(203)=100+20+21……

    同理分析四位数、五位数……

    (1)

    源代码:

    #include<iostream.h>
    int f(int n)
    {
        int i,unit,decade;
        int count=0;
        for(i=1;i<=n;i++)
        {
            decade=i;
            while(decade!=0)
            {
                unit=decade%10;
                decade=decade/10;
                if(unit==1) 
                {
                    count++;
                }
            }
        }
        return count;
    }
    
    void main()
    {
        int n,count;
        cout<<"Please input N: ";
        cin>>n;
        count=f(n);
        cout<<"From 1 to "<<n<<",there are "<<count<<" ones."<<endl;
    }
    View Code

    运行结果:

     

     

    (2)

    源代码:

    #include <iostream>
    #include <cstdio>
    using namespace std;
    
    int f(int n)
    {
        int factor=1;
        int count=0;
        int high=0;
        int current=0;
        int low=0;
        while(n/factor)
        {
            low=n%factor;
            current=n/factor%10;
            high=n/factor/10;
            switch(current)
            {
                case 0:
                count+=high*factor;
                break;
                case 1:
                count+=high*factor+low+1;
                break;
                default:
                count+=(high+1)*factor;
                break;
            }
            factor*=10;
        }
        return count;
    }
    int main()
    {
        int n ;
        while(scanf("%d",&n)!=EOF)
        {
            cout<<f(n)<<endl;
        }
        return 0;
    }
    View Code

    运行结果:

     

     

    总结:

       如果只要求实现基本功能,那实际并不是很难,关键在于当N变得很大时,遍历绝对不是一个好方法,那么就要找到其中隐藏的规律,就像小学奥数一样,在一列数字中,把每个情况都拆开,然后分析,找到隐含的规律。在发现d过程可能要列举很多情况才能发现,也才能肯定最先找到的规律是否正确。不是到确认为止,还要继续扩展,四位数、五位数、六位数……甚至更大,再者就是不确定的N,需要它具有任意性、通用性,而不是单单的特殊的一个数字,类似“abcde”。

       最近老师给的题目都来自《编程之美》里面,题目很典型,主要都是讲究思路和算法,有机会要看看这本书。

     

  • 相关阅读:
    Redis-Sp:Redis主要功能
    Redis-Sp:Redis介绍
    阿里云-Redis-Help-连接实例-Redis客户端连接:C#客户端StackExchange.Redis
    Samba通过ad域进行认证并限制空间大小《转载》
    SQL函数简述
    SELECT--UNION,UNION ALL,MINUS, INTERSECT,EXISTS
    oracle数据库常用查询一
    oracle以web方式登录EM、ISQLPlus
    关于sys、system、sysman等在EM中登录的问题
    top 命令SQLServer-sybase-oracle
  • 原文地址:https://www.cnblogs.com/mumulucky/p/4464067.html
Copyright © 2011-2022 走看看