题目:
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
思路:
对于二进制数,有左移右移这样的位操作。可以判断当前数的最后一位是否为1,如果是,个数加1,不是则右移一位,继续判断。
这种方法的弊端是如果输出一个负数,会出现死循环。因为在负数中,二级制的第一位也是符号位,也就是1,右移之后不可以直接将符号位的1右移,还需要将第二位补为1.
(>>右移运算符将一个运算对象的各二进制位全部右移若干位,正数左补0,负数左补1.)
(<<左移运算符将一个运算对象的各二进制位全部左移若干位(左边的二进制丢弃,右边补0))
常规解法:
首先把1和n做与运算,判断n的最低位是不是1.再把1左移以为得到2,再和n做与运算,如此往复.
循环次数为二进制的位数,所以时间复杂度为O(n)
优秀的解法:
一个整数减去1 都是把最右边的1变成0,
如果它的右边还有0,则所有的0都变成1
而它左边的所有位都保持不变 之后把这个n与(n-1) 进行与运算
就会把该整数最右边的1变成0
n中有几个1 该过程就会进行几次
例子:
对于 10 二进制为 1010
10-1=9 二进制 为 1001
1010
1001
与的结果 为 1000 也就是8
1000 (8)
0111 (7)
与的结果为 0000 就是 0
也就是给定数的二进制数有几个1 那么就能做几次这样的操作.
代码:
public int NumberOf1(int n) {
int count = 0;
long flag =1;
while (flag!=0)
{
if( (n&flag)!=0)
{
count++;
}
flag =flag<<1;
}
return count;
}
// public int NumberOf1(int n) {
// int count =0;
// while (n!=0)
// {
// count++;
// n=(n-1)&n;
// }
// return count;
// }
题目:
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
保证base和exponent不同时为0
思路:
整数,分为0,正数,负数
对于 0 ,直接返回1
对于负数,求其绝对值,然后取倒数返回
对于正数,若指数为1,则返回其本身。
对于大于1 的数,起码是2,3…,不断累乘,时间复杂度为O(n)
可以使用递推公式:
若n为偶数 则a^ n = a ^ (n/2) * a ^ (n/2)
若n为奇数 则a^ n= a^((n-1)/2) * a ^ ((n-1)/2) * a
即 求 2 的7次方 等于 2^3 * 2^3 * 2
代码:
public double Power(double base, int exponent) {
if (base<0||base==0)
{
return 0;
}
if (exponent==1)
{
return base;
}
if (exponent<0)
{
exponent = -exponent;
}
boolean flag=false;//记录次方数是否为负数
if(exponent<0)
{
flag=true;
exponent=-exponent;//若为负数 则取绝对值后 计算取倒数
}
double temp = Power(base*base,exponent>>1);
//如果exponent 为 偶数 那就是每次除2 得到偶数次方的结果 递归调用
if (((exponent)&0x1)==1)
//0x0和0x1分别表示十六进制的数的0和1
//奇数的情况 余 1 所以在乘一次
{
temp=temp*base;
}
return flag ? 1/temp:temp;
}