java私塾 代码_【Java】思维私塾——一行代码解决算法

有些算法题目,只要掌握了思路就可以用很短的代码来实现它。比如下面这几道题目:

二的幂

问题

判断一个数字是否是2的n次方

解答

遇到2的幂次方,要建立位移操作的思想,如果n是二的幂,即最高位为1其他位置为0,那么n-1就是最高位为0,其余位置为1,那么n&(n-1)就是0

1boolean isPowerOfTow(int n){

2    return (n>0)%%(n&(n-1))==0;

3}

三的幂

问题

判断一个数字是否为3的n次方

解答

int类型中不溢出情况下3的最高次方即为1162261467,那么只要这个数去约n为0,那么说明n的约数只有三,即为3的n次方.

同样的做法也可以适用于5的幂,7的幂,X的幂(X是一个素数)之类的题目。

1boolean isPowerOfThree(int n){

2    return (n>0)&&(116261467%n)==0;

3}

二进制1的个数

问题

给定一个数字n,求n转换为二进制表示中1的个数

解答

JDK大法好,直接使用自带的方法:

  • bitCount:返回二进制中1的个数
  • lowestOneBit:返回二进制表示中最低位1的位置
  • highestOneBit:返回二进制表示中最高位1的位置
  • numberOfLeadingZeros:返回二进制表示中高位0的数目
  • numberOfTrailingZeros:返回二进制表示中低位0的数目
1 int bitCount(int num) {

2        return Integer.bitCount(num);

3    }

或者也可以不使用jdk类库的解法

1int bitOfOne(int num) {

2        return num == 0 ? 0 : 1 + bitOfOne(num & (num - 1));

3    }

阶乘后的零

问题

给定一个数字n,求n!位数中的0的个数。

解答

这种问题我们要分析0的产生原因,因为10=52,对于一个n!的数字而言,末尾为0的数字即n!的约数中包含的52的次数,因为2的次数是足够的,也就是说这道题等价于求n!中约数5的个数(注意诸如25这种数字,约数中包括了2个5)。

1int zeroAtTheEndCount(int num) {

2        return num / 5 + zeroAtTheEndCount(num / 5);

3    }

熄灭的灯

问题

有x个灯,一个开关控制一个灯,按下开关会使灯熄灭或者打开,现在灯都是熄灭的状态,我们进行n次操作,每次操作都把编号为i的倍数的开关全部按下,即

  • 将编号为1的倍数的开关全部按下
  • 将编号为2的倍数的开关全部按下
  • 将编号为x的倍数的开关全部按下

已知灯的总数为x,求最后灯亮起来状态的数量

解答

首先任意取灯的编号n,会有几次操作会影响这个灯的状态呢?答案是n的所有约数的个数次。

好比说编号为12的灯,12的约数有1,2,3,4,6,12。也就是说编号为12的灯的状态会被切换6次,分别在第1,2,3,4,6,12次切换开关的时候。

那么从下面2种情况考虑:

  • 假设n是一个非完全平方的数:因为为一个非平方的数的约数个数为偶数个,也就是说会切换偶数次状态,也就是说状态不会变。
  • 假设n是一个完全平方数:完全平方数的约数是奇数个,其状态会发生改变。

那么按照题目的要求,一开始全是熄灭状态的,求亮起来状态的灯数目,就是说求会发生变化的编号的数目,也就是相当于求1~x之间完全平方数的个数。

1int lightCount(int num) {

2        return (int) Math.sqrt(num);

3    }

奇怪的数

问题

给定一个非空数组,其中除了一个元素只出现一次外,其他元素都出现了两次,求这个只出现一次的元素

解答

这里的一个关键运算符是^ 异或运算符,主要是利用到了异或运算a^b满足的如下规律:

  • a^b=b^a 交换律
  • a^b^c=a^(b^c)结合律
  • a^a=0,同时0^0=0
  • 0^a=a
1int loseNumber(int[] num) {

2        return Arrays.stream(num).reduce(0, (n1, n2) -> n1 ^ n2);

3    }

约瑟夫环问题

问题

编号为1-n的n个战士围成一圈,从编号1的战士开始依次报数,数到m的战士会淘汰,以后的战士再重新报数,直到剩下一个士兵,求这个士兵的编号

解答
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值