力扣解题思路:脑筋急转弯系列

172. 阶乘后的零


思路:给定一个整数 n,返回 n! 结果尾数中零的数量。
我们知道,尾部的 0 由 2 * 5 得来,2 的数量明显多于 5 的数量,因为2永远先于5出现,因此只要统计有多少个 5 即可。
对于一个数 N,它所包含 5 的个数为:N/5 + N/5^2 + N/5^3 + …,其中 N/5 表示不大于 N 的数中 5 的倍数贡献一个 5,N/5^2 表示不大于 N 的数中 5^2 的倍数再贡献一个 5 …。

//首先题目的意思是末尾有几个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 + …

462. 最少移动次数使数组元素相等 II


思路:给定一个非空整数数组,找到使所有数组元素相等所需的最小移动数,其中每次移动可将选定的一个元素加1或减1。 您可以假设数组的长度最多为10000。

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;
}

326. 3的幂


思路:给定一个整数,写一个函数来判断它是否是 3 的幂次方。
这一题比较简单,先用最规矩的方法,不断地除以3,最后为1则一定是3的幂次方:

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);
}

nowCoder:求 1+2+3+...+n


思路:题目要求不能使用乘除法、for、while、if、else、switch、case 等关键字及条件判断语句 A ? B : C。
常规方法是不断调用递归函数累加,但是无论如何递归的出口还是需要if判断的,所以还有什么别的方式吗?

!!!!我们可以联想到&&的短路特性即在第一个条件语句为 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;
}

nowCoder:不用加减乘除做加法


思路:要求不得使用 +、-、*、/ 四则运算符号,那么我们就可以使用位运算。a ^ b 表示没有考虑进位的情况下两数的和,(a & b) << 1 就是进位。递归会终止的原因是 (a & b) << 1 最右边会多一个 0,那么继续递归,进位最右边的 0 会慢慢增多,最后进位会变为 0,递归终止。

public int Add(int a, int b) {
     
    return b == 0 ? a : Add(a ^ b, (a & b) << 1);
}

你可能感兴趣的:(力扣解题思路:脑筋急转弯系列)