//首先题目的意思是末尾有几个0
// 比如6! = 【1* 2* 3* 4* 5* 6】
// 其中只有2*5末尾才有0,所以就可以抛去其他数据 专门看2 5 以及其倍数 毕竟 4 * 25末尾也是0
// 比如10! = 【2*4*5*6*8*10】
// 其中 4能拆成2*2 10能拆成2*5
// 所以10! = 【2*(2*2)*5*(2*3)*(2*2*2)*(2*5)】
// 一个2和一个5配对 就产生一个0 所以10!末尾2个0
// 转头一想 2肯定比5多 所以只数5的个数就行了
// 假若N=31 31里能凑10的5为[5, 2*5, 3*5, 4*5, 25, 6*5] 其中 25还能拆为 5**2
// 所以 里面的5的个数为 int(31/(5**1)) + int(31/(5**2))
// 所以 只要先找个一个 5**x < n 的x的最大数 然后按上面循环加起来
public int trailingZeroes(int n) {
return n == 0 ? 0 : n / 5 + trailingZeroes(n / 5);
}
如果统计的是 N! 的二进制表示中最低位 1 的位置,只要统计有多少个 2 即可 。和求解有多少个 5 一样,2 的个数为 N/2 + N/2^2 + N/2^3 + …
Input:
[1,2,3]
Output:
2
Explanation:
Only two moves are needed (remember each move increments or decrements one element):
[1,2,3] => [2,2,3] => [2,2,2]
我最开始想到的是用平均数,结果发现不对,参考别人的答案后发现应该使用中位数,随便举个例子如数组长度为奇数2n+1 则中位数两边各有n个数 设左边所有数和中位数的差值和为x 右边所有数和中位数的差值和为y 则所有需要移动的次数为x+y 如果不选择中位数 例如选择中位数-1 这样总的移动次数就变成了 >= ((x-n) + (y+n) + 1) 最好的情况下比中位数大1 如果数组长度是偶数 有两个中位数 选择两个中位数的任何一个或者两个中位数的平均数 都是可以的。
设 m 为中位数。a 和 b 是 m 两边的两个元素,且 b > a。要使 a 和 b 相等,它们总共移动的次数为 b - a,这个值等于 (b - m) + (m - a),也就是把这两个数移动到中位数的移动次数。
public int minMoves2(int[] nums) {
Arrays.sort(nums);
int move = 0;
int l = 0, h = nums.length - 1;
while (l <= h) {
move += nums[h] - nums[l];
l++;
h--;
}
return move;
}
public boolean isPowerOfThree(int n) {
if (n == 0) {
return false;
}
while (n % 3 == 0) {
n /= 3;
}
return n == 1;
}
另外还有一种比较巧妙的方法,因为3的幂次的质因子只有3,而所给出的n如果也是3的幂次,故而题目中所给整数范围内最大的3的幂次的因子只能是3的幂次,1162261467是3的19次幂,是整数范围内最大的3的幂次:
public boolean isPowerOfThree(int n) {
return n > 0 && (1162261467 % n == 0);
}
!!!!我们可以联想到&&的短路特性即在第一个条件语句为 false 的情况下不会去执行第二个条件语句。
利用这一特性,将递归的返回条件取非然后作为 && 的第一个条件语句,递归的主体转换为第二个条件语句,那么当递归的返回条件为 true 的情况下就不会执行递归的主体部分,递归返回。
本题的递归返回条件为 n <= 0,取非后就是 n > 0;递归的主体部分为 sum += Sum_Solution(n - 1),转换为条件语句后就是 (sum += Sum_Solution(n - 1)) > 0。
public int Sum_Solution(int n) {
int sum = n;
boolean b = (n > 0) && ((sum += Sum_Solution(n - 1)) > 0);
return sum;
}
public int Add(int a, int b) {
return b == 0 ? a : Add(a ^ b, (a & b) << 1);
}