leetcode讲讲暴力解决「 263.丑数」过程中暴露出来的问题

Posted 妙七先生

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode讲讲暴力解决「 263.丑数」过程中暴露出来的问题相关的知识,希望对你有一定的参考价值。

最开始,我是直接暴力求解丑数的。抛开时间上的限制,我没想到会出现这么多意料之外的错误。在这个过程中,暴露了一些问题。这篇博客记录一下。

问题描述

给你一个整数 n ,请你判断 n 是否为 丑数 。如果是,返回 true ;否则,返回 false 。

丑数 就是只包含质因数 2、3 、 5 的正整数

简单分析

根据丑数的定义,一个数如果是丑数,那么它将满足两个条件:

  1. 该数是一个正整数
  2. 该数的因子只会是 2、3、5,没有其他的因数存在。
  3. 1 是丑数

错误一

相比于后面两个问题,这个问题让我学到的东西最多。先把代码放下来:

class Solution 
    public boolean isUgly(int n) 
        if(n == 1)
            return true;        
        for(int i = 2; i < n; ++i)
            if(n % i == 0)
                if(i != 2 || i != 3 || i != 5)
                    return false;
            
        
        return true;
    


错误是在输入 6 的时候出错的。我不太明白问题出在哪?所以我便debug了一下。发现在 第二层 if 语句中便出现了错误。

在因子为2 的时候,程序竟然会执行到 if 里面?按照我的逻辑

在该因子不是2 或者 不是3 或者 不是5的时候才会返回 false。

但是,在因子是2的情况下,竟然还会输出false。慢慢地,我发现,这程序在运算 i != 2 之后还会运行 i != 3…我当时脑子一下子就瓦特了。不对呀,||会短路呀,i!=2是false, 为什么还会执行 i!=3。于是,我便重新搜索了一下 ||

「短路」运算符

&&、|| 都是一个短路 的逻辑运算符。如果该表达式可以通过一侧的运算结果确定「最终的结果」的情况下,那么另一侧的表达式将不会运行。

对于 || 来说, 左侧的表达式为 false,并不能说明最终的结果究竟是 true 还是 false。所以,程序最终还会执行 i !=3

aba||b
truefalsetrue
truetruetrue
falsetruetrue
falsefalsefalse

总结一下:对于 || 来说,只有当左侧为true时,才会短路

我把它和 && 搞混了:

aba&&b
truetruetrue
truefalsefalse
falsefalsefalse
falsetruefalse

总结一下:对于&&来说,只有当左侧为false时,才会短路。

正是因为当 i=2时,i!=2false,所以才会执行 i!=3
那么,对于我这个程序来说,只要输入的 n 是 2 的倍数,那么该程序一定会输出 false。
修改后的程序为:

class Solution 
    public boolean isUgly(int n) 
        if(n == 1)
            return true;
        
        for(int i = 2; i < n; ++i)
            if(n % i == 0)
                if(i == 2 || i == 3 || i == 5)
                    continue;
                else
                    return false;
                
            
        

        return true;

    


这样简单的修改,直接导致了 错误二的诞生。

错误二

由于我是直接枚举每一个数,进行遍历,所以在遇见 2、3、5的倍数时,便不会达到预期结果。修改很简单:

class Solution 
    public boolean isUgly(int n) 
        if(n == 1)
            return true;
        
        for(int i = 2; i < n; ++i)
            if(n % i == 0)
                if(i % 2 == 0 || i % 3 == 0|| i % 5 == 0)
                    continue;
                else
                    return false;
                
            
        

        return true;

    

错误三

我一开始并没有意识到「丑数是一个正整数」这一个条件,最终导致的结果便是在处理负数的时候出现了错误。

由于这个数值的特殊性,我最开始以为,这是由于代码溢出造成的。看了半天代码之后,没有发现会导致溢出的地方。我没有做任何的加或者乘运算,怎么可能会出现这种错误?代码如下:

class Solution 
    public boolean isUgly(int n) 
        if(n == 1)
            return true;
        
        for(int i = 2; i < n; ++i)
            if(n % i == 0)
                if(i % 2 == 0 || i % 3 == 0|| i % 5 == 0)
                    continue;
                else
                    return false;
                
            
        

        return true;

    

所以,我又去猜测 % 在处理负数时不太一样。然后发现并没有什么不同。
(羞耻~ 后来发现,负数连for循环都进不去,怎么可能会执行 % 操作)

那么,到底问题出现在哪儿?我最终看了一遍题目,发现 丑数是一个正整数
修改后的代码如下:

class Solution 
    public boolean isUgly(int n) 
        if(n <= 0)
            return false;
        if(n == 1)
            return true;
        
        for(int i = 2; i < n; ++i)
            if(n % i == 0)
                if(i % 2 == 0 || i % 3 == 0|| i % 5 == 0)
                    continue;
                else
                    return false;
                
            
        

        return true;

    

错误三


这个错误出现的原因很简单:7是素数。因为我遍历的范围是[2,n),所以,输入7之后,程序不会进入 if 语句中,更别说输出 false 了。
为了修正这个错误,我把范围改为[2,n]。

class Solution 
    public boolean isUgly(int n) 
        if(n <= 0)
            return false;
        if(n == 1)
            return true;
        
        for(int i = 2; i <= n; ++i)
            if(n % i == 0)
                if(i % 2 == 0 || i % 3 == 0|| i % 5 == 0)
                    continue;
                else
                    return false;
                
            
        
        return true;

    


暴力成功,虽然时间超出了。

正确的代码——非暴力求解

class Solution 
    public boolean isUgly(int n) 
        if(n <= 0)
            return false;
        if(n == 1)
            return true;
        int[] factors = 2,3,5;

        for(int factor : factors)
            while(n % factor == 0)
                n /= factor;
            
        
        return n == 1;

    

总结

  1. 基础知识掌握的不牢固,或者说,只会纸上谈兵。

以上是关于leetcode讲讲暴力解决「 263.丑数」过程中暴露出来的问题的主要内容,如果未能解决你的问题,请参考以下文章

leetcode讲讲暴力解决「 263.丑数」过程中暴露出来的问题

LeetCode--263--丑数

LeetCode263. Ugly Number 丑数判断

Leetcode:263

263 Ugly Number 丑数

LeetCode 0263. 丑数