第一题(二进制中1的个数)
- 问题描述:请实现一个函数,输入一个整数,输出该数二进制表示中 1 的个数。例如,把 7表示成二进制是 0111,有 3 位是 1。因此,如果输入 7,则该函数输出 3。

法一:获取二进制最右边的1位,判断其是否为1,然后丢弃,继续判断直到数字为0.
代码实现:
int Bits(unsigned int n)
{
int count = 0;//统计1的个数
while(n != 0)
{
count += n&1;//获取n二进制最右边一位
n >>= 1;//丢弃n二进制最右边一位
}
return count;
}
法二:利用n &= n-1 总是丢弃最右边的1可以更快速的得到答案
代码实现:
int Bits(unsigned int n)
{
int count = 0;//统计1的个数
while(n != 0)
{
n &= n-1;//将最右边的1变为0
count++;
}
return count;
}
第二题(将数字变成0的操作次数)
- 问题描述:给你一个非负整数 num ,请你返回将它变成 0 所需要的步数。 如果当前数字是偶数,你需要把它除以 2 ;否则,减去 1 。

法一:按照步骤直接实现
代码实现:
int NumberOfSteps(int num)
{
int count = 0;//统计次数
while(num != 0)
{
if((num&1) != 0)//奇数
{
--num;
}
else//偶数
{
num >>= 1;//除以2
}
++count;
}
return count;
}
法二:全部使用位运算符
int NumberOfSteps(int num)
{
int count = 0;
while(num != 0)
{
count++;
num = (num&1) != 0 ? num&0xfffffffe : num >> 1;
}
return count;
}
第三题(求平方根)
- 问题描述:给你一个正整数,求出其正平方根的值,如果其正平方根的值不为整数则取其整数部分.不允许使用库函数.

法一:利用循环依次遍历
int MySqrt(int n)
{
int i;
for(i = 0; i*i <= n; i++)
{
;
}
return i-1;
}
第四题(统计十进制数字位数)
- 问题描述:统计一个整数是个几位数字?整数可以是负数,零或者正数.
法一:每次丢弃个位数字,直到0,统计丢弃的次数即可.
代码实现:
unsigned char GetFigure(int n)
{
unsigned char count = 0;
if(n == 0)
return 1;
while(n != 0)
{
count++;
n /= 10;//丢弃个位
}
return count;
}
第五题(特殊进制的位数)
- 问题描述:给定一个正整数,如果把它转为十六进制,那么它是个几位数字呢?

法一:每个丢弃十六进制的”个位“,直到0,统计丢弃的次数即可,其它进制的处理过程类似
代码实现:
unsigned char GetFiguresHex(unsigned int n)
{
unsigned char tmp = 0;//统计次数
if(n == 0)
return 1;
while(n != 0)
{
tmp++;
n /= 16;//丢弃十六进制的”个位“
}
return tmp;
}
第六题:顺序输出数字的每一位
- 问题描述:给定一个整数,输出数字的每一位,例如 123456 输出结果为 1 2 3 4 5 6.
法一:利用循环,获取最高位的数字,输出,然后再丢弃,直到为0
代码实现:
void PrintOrder(int n)
{
if(n == 0)
{
printf("0\n");
return ;
}
int m = n;
int count = 0;//统计n的位数
while(m != 0)
{
m /= 10;//丢弃个位
count++;
}
int power = (int)pow(10.0,count-1);
while(n != 0)
{
printf("%d ",n/ppower);//输出最高位
n %= power;//丢弃最高位
power /= 10;
}
}
法二:利用递归输出数据
void PrintOrder(int n)
{
if(n >= 10)
{
PrintOrder(n / 10);//递归输出高位数据
}
printf("%d ",n%10);//输出个位
}
第七题(逆序输出数字的每一位)
- 给定一个整数,逆序输出数字的每一位,例如 123456 输出结果为 6 5 4 3 2 1
法一:得到个位,输出个位,再丢弃个位直到0
void PrintReverse(int n)
{
do
{
printf("%d ",n%10);//得到并输出个位
n /= 10;//丢弃个位
}while(n != 0);
printf("\n");
}
第八题(整数的各位积和之差)
- 问题描述:给你一个整数 n ,请你帮忙计算并返回该整数「各位数字之积」与「各位数字之和」的差。

法一:得到个位做相应的处理,然后丢弃个位,直到0
int subtractProductAndSum(int n)
{
if(n == 0)
return 0;
int sum = 0;//和
int mul = 1;//积
int tmp;
while(n != 0)
{
tmp = n%10;//得到个位数字
sum += tmp;
mul *= tmp;
n /= 10;//丢弃个位数字
}
return mul-sum;
}
第九题(1~n中1的次数)
- 问题描述:输入一个整数 n ,求 1~n 这 n 个整数的十进制表示中 1 出现的次数。
例如,输入 12,1~12 这些整数中包含 1 的数字有 1、10、11 和 12,1 一共出现了 5
次。
把每个数字中包含1的数量计算出来,然后把1~n的1的数量全部加起来
代码实现:
int One(int n)
{
int count = 0;
while(n != 0)
{
if(n%10 == 1)
{
count++;
}
n /= 10;
}
return count;
}
int countDigitOne(int n)
{
int tmp = 0;
for(int i = 1; i <= n; i++)
{
tmp += One(i);
}
return tmp;
}
该算法效率很低,但目前我也没有更快的方法
这篇博客探讨了与数字进制相关的算法问题,包括计算二进制中1的个数、将数字变为0的操作次数、求平方根、统计数字位数、特殊进制位数、顺序和逆序输出数字、计算各位积和之差以及1在1~n中出现的次数。通过多种解题方法和代码实现,深入解析每道题目。
921

被折叠的 条评论
为什么被折叠?



