算法思想——数字进制

这篇博客探讨了与数字进制相关的算法问题,包括计算二进制中1的个数、将数字变为0的操作次数、求平方根、统计数字位数、特殊进制位数、顺序和逆序输出数字、计算各位积和之差以及1在1~n中出现的次数。通过多种解题方法和代码实现,深入解析每道题目。

第一题(二进制中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;
}

该算法效率很低,但目前我也没有更快的方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值