263. Ugly Number

本文提供了一段Java代码,用于判断给定的正整数是否为丑数。丑数定义为只包含质因数2、3、5的正整数,其中1通常被视为丑数。
题目:

Write a program to check whether a given number is an ugly number.

Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. For example, 6, 8 are ugly while 14 is not ugly since it includes another prime factor 7.

Note that 1 is typically treated as an ugly number.

思路:num是且都是(2,3,5)中的因数,所以可以每次除以其中的一个数字,如都不能被整除则return false
          当找到一个可被整除的数,那么继续利用它的商,递归下去。

public static boolean isUgly(int num) {
        // 是 且 都是
        // if 都不能被整除,则false
        // else 找出一个可被整除,其商也可以被(2,3,5)整除
        // 如发现,不能被整除 return false
        if (num <= 0) return false;
        int tmp = canDiv(num);
        if (tmp == 1) {
            return true;
        } else if (tmp == -1) {
            return false;
        } else {
            return isUgly(tmp);
        }
    }

    private static int canDiv(int num) {
        if (num % 2 == 0) return num / 2;
        else if (num % 3 == 0) return num / 3;
        else if (num % 5 == 0) return num / 5;
        else if (num == 1) return 1;
        else return -1;
    }

    // clean code
    public boolean isUglyBetter(int num) {
        if (num == 1) return true;
        if (num == 0) return false;
        while (num % 2 == 0)
            num = num / 2;
        while (num % 3 == 0)
            num = num / 3;
        while (num % 5 == 0)
            num = num / 5;
        return num == 1;
    }




<think>我们有两个类:Swan 和 UglyDuck(丑小鸭)。UglyDuck 继承自 Swan。 两个类都有静态变量 `msg` 和静态方法 `fly()`。 注意:静态方法和静态变量是与类相关联的,而不是与对象实例。因此,它们不具有多态性。 在 main 方法中: Swan swan = new Swan(); // 创建 Swan 实例 Swan uglyDuck = new UglyDuck(); // 创建 UglyDuck 实例,但声明为 Swan 类型 然后调用: swan.fly(); // 调用 Swan 类的 fly 方法 uglyDuck.fly(); // 虽然对象是 UglyDuck 类型,但声明为 Swan,且 fly 是静态方法,所以调用的是 Swan 类的 fly 方法? 但是,我们需要注意:静态方法是根据编译时类型来调用的,而不是运行时类型。 所以: swan.fly():编译时类型是 Swan,所以调用 Swan.fly() uglyDuck.fly():编译时类型是 Swan,所以也调用 Swan.fly()? 等等,我们再看一下代码。 实际上,在 UglyDuck 类中,我们定义了一个同名的静态方法 fly()。这实际上是隐藏(hide)了父类的静态方法,而不是重写(override)。 然而,当我们通过一个声明为 Swan 类型的变量去调用 fly() 时,不管这个变量实际指向什么对象,都会调用 Swan 类中定义的静态方法。 因此: swan.fly() 执行 Swan 类的 fly 方法:它定义了一个局部变量 msg(注意:这里有一个错误,在 Swan 的 fly 方法中,第4行是 String msg = ...,这是一个局部变量,与静态变量无关),然后打印这个局部变量,即 "swan can not fly ..."。 uglyDuck.fly() 同样调用的是 Swan 类的 fly 方法,因为变量 uglyDuck 的编译时类型是 Swan。所以也会打印 "swan can not fly ..."? 但是,我们再看一下选项: 选项A: swan can not fly ... ugly duck can't fly 选项B: swan can fly ... ugly duck can't fly 选项C: swan can fly ... ugly duck can fly 选项D: swan can not fly swan can not fly 实际上,由于静态方法不具有多态性,所以两个调用都是 Swan 类的 fly 方法。那么输出应该是两次 "swan can not fly ..."。 然而,在 UglyDuck 类中,我们也定义了一个静态方法 fly,但是当我们使用 Swan 类型的引用去调用时,并不会调用子类的静态方法。 但是,这里有一个陷阱:在 UglyDuck 类中,我们确实定义了一个静态方法 fly,但是我们在调用 uglyDuck.fly() 时,因为 uglyDuck 的声明类型是 Swan,所以调用的是 Swan.fly()。 所以,输出应该是: swan.fly() -> 打印局部变量msg: "swan can not fly ..." uglyDuck.fly() -> 因为编译时类型是Swan,所以调用Swan.fly(),同样打印 "swan can not fly ..." 因此,选项D:两次都输出 "swan can not fly ..."(注意选项D的文本是“swan can not fly”和“swan can not fly”,但代码中输出的是“swan can not fly ...”,所以选项D的文本可能不完整?) 但是,我们再看一下选项D的原文: D.swan can not fly swan can not fly 而我们的输出是带省略号的:在Swan类的fly方法中,输出的字符串是 "swan can not fly ..."(注意有三个点),而选项D中没有省略号。那么选项D可能是简写了?或者我们再看一下代码。 代码中: Swan类的fly方法:String msg = "swan can not fly ..."; // 注意这里有省略号 输出这个msg。 选项D写的是“swan can not fly”和“swan can not fly”,没有省略号。所以可能选项D并不匹配? 但是,我们再看选项A、B、C,它们也没有完全匹配省略号?实际上,我们打印的是完整的字符串。 然而,题目中的选项可能是简写。我们关注的是内容。 不过,这里还有一个问题:在Swan类中,有一个静态变量msg,初始化为"swan can fly",但是在fly方法中,它定义了一个同名的局部变量,这个局部变量覆盖了静态变量吗?是的,在fly方法内部,局部变量msg将隐藏同名的静态变量。所以,在fly方法中,打印的是局部变量msg的值。 因此,输出: swan.fly() -> "swan can not fly ..." uglyDuck.fly() -> "swan can not fly ..." 所以,选项D应该是正确的,尽管它没有写省略号,但可能是题目选项的省略写法。或者选项D的文本是: D.swan can not fly swan can not fly 而我们实际输出有省略号,但题目中选项可能省略了省略号?或者我们再看一下题目选项: 题目中选项D是:D.swan can not fly swan can not fly 但我们的输出是带三个点的:所以严格来说,选项中没有完全匹配的。但是,我们再看一下其他选项,也没有带省略号。 所以,我们按照逻辑选择:两次都是输出Swan的fly方法中的字符串,即两个相同的字符串。 另外,在UglyDuck类中,我们也有一个静态方法fly,但它没有被调用,因为通过Swan类型的引用调用的是Swan的fly方法。 因此,答案应该是D,即使省略号没有写,但意思相同。 但是,等一下:在UglyDuck的fly方法中,我们定义了一个局部变量msg,并打印了它。但是,这个方法没有被调用。 所以,最终输出: 第一行:swan can not fly ... 第二行:swan can not fly ... 因此对应选项D:两个“swan can not fly”(省略了省略号)。 然而,选项D写的是两行都是“swan can not fly”,而选项A的第二行是“ugly duck can't fly”,所以D更符合。 但是,我们再看一下选项D的原文: D.swan can not fly swan can not fly 所以,我们选择D。 但是,我们不要忘记,在Swan类中,还有一个静态变量msg,在UglyDuck类中也有一个静态变量msg,但是我们没有打印它们,我们打印的是局部变量。 所以,结论:两个调用都执行了Swan类的fly方法,输出两行相同的字符串。 因此,正确答案是选项D。 但是,我们还需要验证一下:在Swan类的fly方法中,我们定义了一个局部变量msg,然后打印它。这个方法被调用了两次。 所以,输出: 第一次:swan can not fly ... 第二次:swan can not fly ... 因此,答案是D。 然而,题目中的选项D的文本是“swan can not fly”两次,没有省略号。可能是题目在选项里省略了省略号,或者我们看题目的实际输出。 但是,在题目中,Swan类的fly方法中,字符串是“swan can not fly ...”,所以实际输出是带省略号的。而选项中没有带,这可能是题目设计的瑕疵。但我们只能选择最接近的。 另外,还有一个选项B:第一行是“swan can fly ...”,这是静态变量msg的值,但是我们并没有打印静态变量,而是打印了局部变量。所以选项B是不对的。 因此,我们选择D。 但是,我们再看一下代码,有没有可能输出其他情况? 注意:在Java中,静态方法是通过类来调用的,而不是实例。虽然这里我们使用了实例来调用静态方法,但实际上在编译时,编译器会将其转换为类名调用。所以,上面两个调用实际上都是 Swan.fly()。 因此,两次都是调用同一个方法。 所以,最终答案是D。 但是,我们再看一下题目中的选项,选项D是: D.swan can not fly swan can not fly 而我们的输出是带省略号的,所以严格来说,没有一个选项完全匹配。但题目可能认为省略号不重要,或者选项是简写。 因此,我们选择D。 然而,在题目中,选项A、B、C、D的文本如下: A.swan can not fly ... ugly duck can't fly B.swan can fly ... ugly duck can't fly C.swan can fly ... ugly duck can fly D.swan can not fly swan can not fly 注意:选项A的第一行有省略号,第二行没有;选项B的第一行有省略号;选项C没有省略号;选项D没有省略号。 而我们的输出是两次“swan can not fly ...”,也就是两次都有省略号。那么选项A的第一行和我们输出的第一行一致,但第二行不一致;选项D的两行都没有省略号,但是内容都是“swan can not fly”(没有省略号)。 所以,如果严格按照字符串匹配,没有一个选项正确。但题目可能期望的是D,因为选项D是两次相同的字符串,并且是“swan can not fly”,只是省略了省略号。 但是,我们再看一下代码,在Swan的fly方法中,输出的字符串是“swan can not fly ...”,所以实际输出肯定有省略号。那么在选项中,只有选项A的第一行有省略号,其他选项要么没有,要么部分有。 然而,选项A的第二行是“ugly duck can't fly”,而我们实际输出的是“swan can not fly ...”,所以选项A不对。 那么,题目可能是有错误的?或者我们理解有误? 重新思考:在调用uglyDuck.fly()时,虽然uglyDuck变量的声明类型是Swan,但实际上对象是UglyDuck类型。那么,在Java中,静态方法的调用只与编译时类型有关,所以还是调用Swan.fly()。所以输出两次“swan can not fly ...”。 但是,如果我们直接使用UglyDuck类型的变量来调用,就会调用UglyDuck.fly()。但这里没有,所以还是两次Swan的fly方法。 所以,输出两个相同的字符串。那么,选项D虽然省略了省略号,但内容上最接近(都是两次相同的且是swan can not fly)。 因此,我们选择D。 综上所述,正确答案应该是D。 </think>### 代码分析 给定的代码涉及 Java 的静态方法调用和变量作用域,关键在于理解 **静态绑定(编译时绑定)** 的特性: ```java class Swan { static String msg = "swan can fly"; // 静态变量 public static void fly() { String msg = "swan can not fly ..."; // 局部变量 System.out.println(msg); // 输出局部变量 } } class UglyDuck extends Swan { static String msg = "ugly duck can fly"; // 隐藏父类静态变量 public static void fly() { // 隐藏父类静态方法(非重写) String msg = "ugly duck can't fly ..."; // 局部变量 System.out.println(msg); } } public class TestFly { public static void main(String[] args) { Swan swan = new Swan(); Swan uglyDuck = new UglyDuck(); // 编译时类型为 Swan swan.fly(); // 调用 Swan.fly() uglyDuck.fly(); // 调用 Swan.fly()(静态绑定) } } ``` ### 执行结果详解 1. **`swan.fly()` 的执行** - 调用 `Swan.fly()` 方法 - 方法内局部变量 `msg` 覆盖静态变量,输出: `"swan can not fly ..."` 2. **`uglyDuck.fly()` 的执行** - `uglyDuck` 的 **编译时类型是 `Swan`** - Java 的静态方法使用 **编译时绑定**(而非运行时多态) - 实际调用 `Swan.fly()`,输出: `"swan can not fly ..."` ### 最终输出 ``` swan can not fly ... swan can not fly ... ``` ### 选项解析 - **A 错误**:第二行实际调用 `Swan.fly()`,非 `UglyDuck.fly()` - **B 错误**:`Swan.fly()` 输出局部变量,非静态变量 `"swan can fly"` - **C 错误**:未调用 `UglyDuck` 的逻辑 - **D 正确**:两次调用均执行 `Swan.fly()`,输出相同字符串 (选项 D 省略了输出字符串末尾的 `...`,但内容一致) ### 关键概念说明 1. **静态方法隐藏(Hiding)** - 子类定义同名静态方法时,会隐藏(非重写)父类方法 - 调用取决于 **编译时类型**(此处 `Swan uglyDuck`) 2. **变量作用域优先级** ```java String msg = "local"; // 局部变量优先于静态变量 System.out.println(msg); // 始终输出局部变量 ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值