C++求1到n中1出现的次数以及数的二进制表示中1的个数

所属分类: 软件编程 / C 语言 阅读数: 82
收藏 0 赞 0 分享

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

题目:

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

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

代码实现(GCC编译通过):

#include "stdio.h"
#include "stdlib.h"
 
int count1(int n);
int count2(int n);
 
int main(void)
{
  int x;
 
  printf("输入一个数:");
  scanf("%d",&x);
  printf("\n从0到%d一共遇到%d(%d)个1\n",x,count1(x),count2(x));
   
  return 0;
}
 
//解法一
int count1(int n)
{
  int count = 0;
  int i,t;
   
  //遍历1到n
  for(i=1;i<=n;i++)
  {
    t=i;
    //依次处理当前遍历到的数字的各个位
    while(t != 0)
    {
        //若为1则统计加一
      count += (t%10 == 1)?1:0;
      t/=10;
    }
  }
   
  return count;
}
 
//解法二:
int count2(int n)
{
  int count = 0;//统计变量
  int factor = 1;//分解因子
  int lower = 0;//当前处理位的所有低位
  int higher = 0;//当前处理位的所有高位
  int curr =0;//当前处理位
   
  while(n/factor != 0)
  {
    lower = n - n/factor*factor;//求得低位
    curr = (n/factor)%10;//求当前位
    higher = n/(factor*10);//求高位
     
    switch(curr)
    {
      case 0:
        count += higher * factor;
        break;
      case 1:
        count += higher * factor + lower + 1;
        break;
      default:
        count += (higher+1)*factor;
    }
     
    factor *= 10;
  }
   
  return count;
}


分析:

方法一就是从1开始遍历到N,将其中的每一个数中含有“1”的个数加起来,比较好想。

方法二比较有意思,核心思路是这样的:统计每一位上可能出现1的次数。

比如123:

个位出现1的数字:1,11,13,21,31,...,91,101,111,121

十位出现1的数字:10~19,110~119

百位出现1的数字:100~123

总结其中每位上1出现的规律即可得到方法二。其时间复杂度为O(Len),Len为数字长度

整数的二进制表示中 1 的个数
题目:整数的二进制表示中 1 的个数

要求:

输入一个整数,求该整数的二进制表达中有多少个 1。

例如输入 10,由于其二进制表示为 1010,有两个 1,因此输出 2。

分析:

解法一是普通处理方式,通过除二余二统计1的个数;

解法二与解法一类似,通过向右位移依次处理,每次与1按位与统计1的个数

解法三比较奇妙,每次将数字的最后一位处理成0,统计处理的次数,进而统计1的个数

代码实现(GCC编译通过):

#include "stdio.h"
#include "stdlib.h"
 
int count1(int x);
int count2(int x);
int count3(int x);
 
int main(void)
{
  int x;
  printf("输入一个数:\n");
  setbuf(stdin,NULL);
  scanf("%d",&x);
  printf("%d转二进制中1的个数是:",x);
  printf("\n解法一:%d",count1(x));
  printf("\n解法二:%d",count2(x));
  printf("\n解法三:%d",count3(x));
   
  printf("\n");
  return 0;
}
 
//除二、余二依次统计每位
int count1(int x)
{
  int c=0;
  while(x)
  {
    if(x%2==1)
      c++;
    x/=2;
  }
  return c;
}
 
//向右移位,与1按位与统计每位
int count2(int x)
{
  int c=0;
  while(x)
  {
    c+=x & 0x1;
    x>>=1;
  }
  return c;
}
 
//每次将最后一个1处理成0,统计处理次数
int count3(int x)
{
  int c=0;
  while(x)
  {
    x&=(x-1);
    c++;
  }
  return c;
}

更多精彩内容其他人还在看

用标准c++实现string与各种类型之间的转换

这个类在头文件中定义, < sstream>库定义了三种类:istringstream、ostringstream和stringstream,分别用来进行流的输入、输出和输入输出操作。另外,每个类都有一个对应的宽字符集版本
收藏 0 赞 0 分享

C++如何通过ostringstream实现任意类型转string

再使用整型转string的时候感觉有点棘手,因为itoa不是标准C里面的,而且即便是有itoa,其他类型转string不是很方便。后来去网上找了一下,发现有一个好方法
收藏 0 赞 0 分享

C/C++指针小结

要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区
收藏 0 赞 0 分享

C++ 类的静态成员深入解析

在C++中类的静态成员变量和静态成员函数是个容易出错的地方,本文先通过几个例子来总结静态成员变量和成员函数使用规则,再给出一个实例来加深印象
收藏 0 赞 0 分享

C++类的静态成员初始化详细讲解

通常静态数据成员在类声明中声明,在包含类方法的文件中初始化.初始化时使用作用域操作符来指出静态成员所属的类.但如果静态成员是整型或是枚举型const,则可以在类声明中初始化
收藏 0 赞 0 分享

C++类静态成员与类静态成员函数详解

静态成员不可在类体内进行赋值,因为它是被所有该类的对象所共享的。你在一个对象里给它赋值,其他对象里的该成员也会发生变化。为了避免混乱,所以不可在类体内进行赋值
收藏 0 赞 0 分享

C++中的friend友元函数详细解析

友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类。友元函数的特点是能够访问类中的私有成员的非成员函数。友元函数从语法上看,它与普通函数一样,即在定义上和调用上与普通函数一样
收藏 0 赞 0 分享

static全局变量与普通的全局变量的区别详细解析

以下是对static全局变量与普通的全局变量的区别进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助
收藏 0 赞 0 分享

C++ explicit关键字的应用方法详细讲解

C++ explicit关键字用来修饰类的构造函数,表明该构造函数是显式的,既然有"显式"那么必然就有"隐式",那么什么是显示而什么又是隐式的呢?下面就让我们一起来看看这方面的知识吧
收藏 0 赞 0 分享

教你5分钟轻松搞定内存字节对齐

随便google一下,人家就可以跟你解释的,一大堆的道理,我们没怎么多时间,讨论为何要对齐.直入主题,怎么判断内存对齐规则,sizeof的结果怎么来的,请牢记以下3条原则
收藏 0 赞 0 分享
查看更多