LeetCode 上一行代码就能解决的智力算法题

第一道:除数博弈

题目来源于 LeetCode 上第 1025 号问题:除数博弈java

题目解析

对于这种博弈类的题目,若是没有思路的话咱们不妨多举几个例子,尝试着从中找寻规律。算法

  • 假设 N = 1,爱丽丝没得选择,直接失败,即 鲍勃获胜
  • 假设 N = 2,爱丽丝有选择,她能够选择 x = 1,鲍勃面对的就是 N = 2 - 1 = 1,没法操做,爱丽丝获胜
  • 假设 N = 3,爱丽丝只能选择 x = 1,由于选 x = 2 不知足 3 % 2 = 0,鲍勃面对的就是 N = 3 - 1 = 2,参考上面 N = 2 的情形,此时鲍勃为 N = 2 的先手,鲍勃获胜
  • 假设 N = 4,爱丽丝能够选择 x = 1 来使鲍勃遇到 N = 3 的状况,爱丽丝获胜

貌似有个规律:N 为奇数时, 鲍勃获胜;N 为偶数时, 爱丽丝获胜编程

是这样吗?code

是的。索引

事实上,不管 N 为多大,最终都是在 N = 2 这个临界点结束的。谁最后面对的是 N = 2 的情形,谁就能获胜(这句话不太理解的话,仔细看看 N = 二、N = 3 这两种情形)。three

接下来,咱们得知道一个数学小知识:奇数的因子(约数)只能是奇数,偶数的因子(约数)能够是奇数或偶数游戏

千万不要忽略 1 也是因子!leetcode

爱丽丝是游戏开始时的先手。get

  • 当她面对的 N 为偶数时,她 必定能够 选到一个 N 的奇数因子 x(好比 1 ),将 N - x 这个奇数传给鲍勃;用 N - x 替换黑板上的数字 N ,鲍勃面对的就是奇数 N,只能选择 N 的奇数因子 x,奇数 - 奇数 = 偶数,此时传给爱丽丝的又是偶数。这样轮换下去爱丽丝会遇到 N = 2 的情形,而后获胜;
  • 当爱丽丝遇到的 N 是奇数时,只能传给鲍勃偶数或没法操做 (N = 1) ,没法获胜。

代码实现

//@五分钟学算法
class Solution {
    public boolean divisorGame(int N) {
        return N % 2 == 0;
    }
}

第二道:灯泡开关

题目来源于 LeetCode 上第 319 号问题:灯泡开关数学

题目分析

首先,由于电灯一开始都是关闭的,因此某一盏灯最后若是是点亮的,必然要被按奇数次开关。

咱们假设只有 6 盏灯,并且咱们只看第 6 盏灯。须要进行 6 轮操做对吧,请问对于第 6 盏灯,会被按下几回开关呢?这不可贵出,第 1 轮会被按,第 2 轮,第 3 轮,第 6 轮都会被按。

为何第 一、二、三、6 轮会被按呢?由于 6 = 1×6 = 2×3。通常状况下,因子都是成对出现的,也就是说开关被按的次数通常是偶数次。可是有特殊状况,好比说总共有 16 盏灯,那么第 16 盏灯会被按几回?

16 = 1 × 16 = 2 × 8 = 4 × 4

其中因子 4 重复出现,因此第 16 盏灯会被按 5 次,奇数次。如今你应该理解这个问题为何和平方根有关了吧?

不过,咱们不是要算最后有几盏灯亮着吗,这样直接平方根一下是啥意思呢?稍微思考一下就能理解了。

就假设如今总共有 16 盏灯,咱们求 16 的平方根,等于 4,这就说明最后会有 4 盏灯亮着,它们分别是第 1 × 1 = 1 盏、第 2 × 2=4 盏、第 3 × 3 = 9 盏和第 4 × 4 = 16盏。

咱们不是想求有多少个可开方的数吗,4 是最大的平方根,那么小于 4 的正整数的平方都是在 1~16 内的,是会被按奇数次开关,最终亮着的灯。

就算有的 n 平方根结果是小数,强转成 int 型,也至关于一个最大整数上界,比这个上界小的全部整数,平方后的索引都是最后亮着的灯的索引。因此说咱们直接把平方根转成整数,就是这个问题的答案。

代码实现

class Solution {
    public int bulbSwitch(int n) {
         return (int)Math.sqrt(n);
    }
}

第三道:3的幂

题目来源于 LeetCode 上第 326 号问题:3的幂

题目解析

正常的思路是不停地去除以 3,看最后的迭代商是否为 1。这种思路的代码使用到了循环,逼格不够高。

这里取巧的方法 用到了数论的知识:3 的幂次的质因子只有 3

题目要求输入的是 int 类型,正数范围是 0 - 231,在此范围中容许的最大的 3 的次方数为 319 = 1162261467 ,那么只要看这个数可否被 n 整除便可。

代码实现

//@五分钟学算法
class Solution {
    public boolean isPowerOfThree(int n) {
         return n > 0 && 1162261467 % n == 0;
    }
}

第四道:2的幂

题目来源于 LeetCode 上第 231 号问题:2的幂

题目解析

若是一个数是 2 的次方数的话,那么它的二进数必然是最高位为 1,其它都为 0 ,那么若是此时咱们减 1 的话,则最高位会降一位,其他为 0 的位如今都为变为 1,那么咱们把两数相与,就会获得 0。

代码实现

//@五分钟学算法
class Solution {
public:
    bool isPowerOfTwo(int n) {
          return n > 0 && ((n & (n - 1)) == 0);
    } 
};

第五道:阶乘后的零

题目来源于 LeetCode 上第 172 号问题:阶乘后的零

题目解析

题目很好理解,数阶乘后的数字末尾有多少个零。

最简单粗暴的方法就是先乘完再说,而后一个一个数。

事实上,你在使用暴力破解法的过程当中就能发现规律: 这 9 个数字中只有 2(它的倍数) 与 5 (它的倍数)相乘才有 0 出现

因此,如今问题就变成了这个阶乘数中能配 多少对 2 与 5

举个复杂点的例子:

10! = 【 2 *( 2 * 2 )* 5 *( 2 * 3 )*( 2 * 2 * 2 )*( 2 * 5)】

在 10!这个阶乘数中能够匹配两对 2 * 5 ,因此10!末尾有 2 个 0。

能够发现,一个数字进行拆分后 2 的个数确定是大于 5 的个数的,因此能匹配多少对取决于 5 的个数。(比如如今男女比例悬殊,最多能有多少对异性情侣取决于女生的多少)。

那么问题又变成了 统计阶乘数里有多少个 5 这个因子

须要注意的是,像 25,125 这样的不仅含有一个 5 的数字的状况须要考虑进去。

好比 n = 15。那么在 15! 中 有 35 (来自其中的5, 10, 15), 因此计算 n/5 就能够 。

可是好比 n=25,依旧计算 n/5 ,能够获得 55,分别来自其中的5, 10, 15, 20, 25,可是在 25 中实际上是包含 2 5 的,这一点须要注意。

因此除了计算 n/5 , 还要计算 n/5/5 , n/5/5/5 , n/5/5/5/5 , ..., n/5/5/5,,,/5直到商为0,而后求和便可。

代码实现

//@五分钟学算法
public class Solution {
    public int trailingZeroes(int n) {
        return n == 0 ? 0 : n / 5 + trailingZeroes(n / 5);
    }
}

第六道:Nim 游戏

题目来源于 LeetCode 上第 292 号问题:Nim 游戏

题目解析

咱们解决这种问题的思路通常都是反着思考:

若是我能赢,那么最后轮到我取石子的时候必需要剩下 1~3 颗石子,这样我才能一把拿完。

如何营造这样的一个局面呢?显然,若是对手拿的时候只剩 4 颗石子,那么不管他怎么拿,总会剩下 1~3 颗石子,我就能赢。

如何逼迫对手面对 4 颗石子呢?要想办法,让我选择的时候还有 5~7 颗石子,这样的话我就有把握让对方不得不面对 4 颗石子。

如何营造 5~7 颗石子的局面呢?让对手面对 8 颗石子,不管他怎么拿,都会给我剩下 5~7 颗,我就能赢。

这样一直循环下去,咱们发现只要踩到 4 的倍数,就落入了圈套,永远逃不出 4 的倍数,并且必定会输。

代码实现

public class Solution {
   bool canWinNim(int n) {
    // 若是上来就踩到 4 的倍数,那就认输吧
    // 不然,能够把对方控制在 4 的倍数,必胜
    return n % 4 != 0;
    }
}

第七道:石子游戏

题目来源于 LeetCode 上第 877 号问题:石子游戏

题目解析

显然,亚历克斯老是赢得 2 堆时的游戏。 经过一些努力,咱们能够获知她老是赢得 4 堆时的游戏。

若是亚历克斯最初得到第一堆,她老是能够拿第三堆。 若是她最初取到第四堆,她老是能够取第二堆。第一 + 第三,第二 + 第四 中的至少一组是更大的,因此她总能获胜。

咱们能够将这个想法扩展到 N 堆的状况下。设第1、第3、第5、第七桩是白色的,第2、第4、第6、第八桩是黑色的。 亚历克斯老是能够拿到全部白色桩或全部黑色桩,其中一种颜色具备的石头数量一定大于另外一种颜色的。

所以,亚历克斯总能赢得比赛。

代码实现

class Solution {
    public boolean stoneGame(int[] piles) {
        return true;
    }
}

❤️ 看完三件事:
若是你以为这篇内容对你挺有启发,我想邀请你帮我三个忙:

点赞,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓 -_-)关注我和专栏,让咱们成为长期关系关注公众号「五分钟学算法」,第一时间阅读最新的算法文章,公众号后台回复 1024 送你 50 本 算法编程书籍。

相关文章
相关标签/搜索