Leetcode原题-数字的补数(不用位运算)
作者:互联网
对整数的二进制表示取反(0 变 1 ,1 变 0)后,再转换为十进制表示,可以得到这个整数的补数。
例如,整数 5 的二进制表示是 “101” ,取反后得到 “010” ,再转回十进制表示得到补数 2 。 给你一个整数 num ,输出它的补数。
示例 1:
输入:num = 5
输出:2
解释:5 的二进制表示为 101(没有前导零位),其补数为 010。所以你需要输出 2 。
示例 2:
输入:num = 1
输出:0
解释:1 的二进制表示为 1(没有前导零位),其补数为 0。所以你需要输出 0 。
首先,看到这么一个题目首先想到的肯定是位运算,但是在这里不用位运算求解.让我们换一种思路
有没有可能,把这一个数的二进制每位都存在一个数组里,然后让数组里的每一个元素一次取反,接着再把数组中的数取出转换为一个新的十进制数呢?
因此,思路如下:
- 创建存放数的二进制每一位的数组
- 将数组的每一位元素取反
- 取出数组,放到新数中
但是这里需要注意的是,因为数字是取余只能从后往前取的,而数组却是从前往后遍历的,所以,这里还需要一部操作,那就是逆序数组
因此,我们这里要实现三个函数分别为:
- 计算该数字二进制位数
计算位数其实很简单,如十进制让该数/10的操作,二进制只不过是/2罢了
int counttimes(int n)
{
int len=0;
while(n)
{
len++;
n/=2;
}
return len;
}
2.逆序排列数组
逆序排列数组其实就是两个指针,一个指向开头,一个指向数组尾,直到两个指到了同一个元素再停止交换
void reverse(int* arr,int left,int right)
{
while(left<right)
{
int temp=arr[left];
arr[left]=arr[right];
arr[right]=temp;
left++;
right--;
}
}
- 反转数位
反转数位也很简单,直接遍历数组,选择判断即可
void reverse_Nums(int* arr,int len)
{
for(int i=0;i<len;i++)
{
if(arr[i]==1)
{
arr[i]=0;
}
else
{
arr[i]=1;
}
}
}
最后还有一个需要注意的点就是将数组中的元素放入数组中也需要倒着取出元素
下面是完整代码
//计算该数字二进制位数
int counttimes(int n)
{
int len=0;
while(n)
{
len++;
n/=2;
}
return len;
}
//逆序排列数字,因为数字放到数组里和数组下标是反的
void reverse(int* arr,int left,int right)
{
while(left<right)
{
int temp=arr[left];
arr[left]=arr[right];
arr[right]=temp;
left++;
right--;
}
}
//反转数位
void reverse_Nums(int* arr,int len)
{
for(int i=0;i<len;i++)
{
if(arr[i]==1)
{
arr[i]=0;
}
else
{
arr[i]=1;
}
}
}
int findComplement(int num)
{
int len=counttimes(num);//求出该数字二进制位数
int arr[len];
int res=0;//结果数字
int arr_index=0;
//将数字存放入数组
while(num)
{
arr[arr_index++]=num%2;
num/=2;
}
reverse(arr,0,len-1);//将数组中元素和数字二进制位对齐
reverse_Nums(arr,len);
//逆序取数
for(int i=len-1,j=0;i>=0;i--)
{
res+=arr[i]*pow(2,j);
j++;
}
return res;
}
这个题的思路是我目前能想到的最好的了,而且也比较好理解,根据现有知识也能掌握.
标签:arr,right,原题,int,len,Leetcode,数组,补数,left 来源: https://blog.csdn.net/wfy17030212/article/details/120932876