快乐数【题目讲解】

题目链接:202. 快乐数 - 力扣(LeetCode)

审题

 题目会给我们一个int型的数,如果在经过有限次的迭代后结果为1,则说明该数是快乐数,如果一直迭代都变不成1,则说明不是快乐数,迭代的方式是计算自身各位上的平方的和。

思考方案

乍一看像是要解决著名的不可解问题----停机问题,不是已经证明为不可解的问题吗?难道是leetcode的出题人在整活???

非也非也!我们可以大胆地猜测在迭代的过程中会出现一定的规律,比如出现一个循环......

大胆猜测后就小心地试着来证明一下:

既然n是一个常数范围内的数,每次迭代的结果又与自身各位上的大小有关系,大小?要不试试求迭代结果的最大值和最小值看看,有范围的话可以试着暴力穷举一下;

既然是平方和,那一定是非负数,要使迭代结果最小,那么就是各位上都是最小的即可,比如0,但是n的最小值是1,所以迭代结果的最小值不会是0,那只能是将最高位写成1了,那么迭代后的最小值就是1了;

要使迭代结果的最大,一个数的各个数都是最大的9就好了,n最大是2^31 - 1 ,即一个十位数:2,147,483,647,那么其迭代的最大值也不会超过9^2 * 10,即810,这也就说明,对于一个int型的数,其迭代变化的范围只会在[1,810),即对于任意一个int数,迭代后的所有结果都不会超过810,那么在810次的变化后,一定会出现一个出现过的数并进入循环,为什么出现一个出现过的数后就会进入循环呢?那是因为每个数都对应只有一个迭代结果,对于迭代结果同理也是固定只有一个迭代结果...由此可以推断出每个数都有固定的迭代链,简单举例如下:

对于快乐数,最后的循环肯定都是1,而非快乐数,最后的循环里肯定没有1,这就是很关键的一点,那么在确定已经走进循环后,只需要判断自身的值就可以判断是否为快乐数了。 

 代码实现

解法一:暴力穷举

不多想,直接暴力穷举,既然810次变化后一定进入循环,那么就直接进行810次循环,判断最后一个迭代结果,即循环中的数是否为1即可:

class Solution {
public:
    int sum_digit_double(int n) // 用于计算数字 n 的每一位的平方和
    {
        int sum = 0;
        while (n != 0)
        {
            int digit = n % 10;
            sum += digit*digit;
            
            n /= 10;
        }

        return sum;
    }

    bool isHappy(int n) {
        int nums[812]; // 由n<=2^31 - 1 可知,经一次变换后最大的数一定小于9^2 * 10, 即810,根据抽屉原理,在第810次变化后一定会出现循环
        nums[0] = n;
        for (int i = 1; i<812; i++) 
        {
            nums[i] = sum_digit_double(nums[i-1]);
        }

        if (nums[811] == 1) // 可以确定第810之后一定进入循环,所以判断即可
        {
            return true;
        }
        else
        {
            return false;
        }
    }

};

 解法二:双指针法

看到直线进循环的形状,有读者可能想到了判断链表是否有环用到的快慢指针的解法,快慢指针相遇的地方就是循环的里边了,虽然在这题里面都是常数级的时间复杂度,但是双指针的方法兼容性较前者好,双指针法基本上可以无视n的范围。

要想在这里套用双指针,就需要一定的抽象能力了,这里的指针不再是地址和下标,而是将对象本身抽象为“指针”,因为每个数的迭代链只有固定的唯一的一条,也就是说值的大小就决定了自己所在的位置了,所以这里可以用对象自己来作为指针。

给第一次接触的读者科普一下快慢指针,顾名思义,就是有两个指针,一个走的快,一个走的慢,注意,这里的快慢都是相对而言的,为了能使它俩尽可能快地相遇,普遍是让快指针每次走两个单位长度,慢的走一个单位长度,当然,具体情况具体分析:

class Solution {
public:
    int sum_digit_double(int n) // 用于计算数字 n 的每一位的平方和
    {
        int sum = 0;
        while (n != 0)
        {
            int digit = n % 10;
            sum += digit*digit;
            
            n /= 10;
        }

        return sum;
    }
    // 双指针法:
    bool isHappy(int n) {
        int slow = n; 
        int fast = sum_digit_double(n); // 这是为了让slow一开始与fast来开差距,顺应后续的逻辑
        while (slow != fast)
        {
            slow = sum_digit_double(slow);  // 等价于指针向后走一步
            fast = sum_digit_double(sum_digit_double(fast));
        }

        return fast == 1;
    }

};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 华为性格测试题目是一种用来评估人们个人性格特点的工具。twc829是其中的一道题目,在测试中扮演着重要的角色。 这道题目是由三个词组组成的: 1. TWC:这是缩写词,代表的是“Team Work Collaboration”,意思是团队合作协作。这个词组旨在测试被试者是否懂得团队合作的重要性以及是否擅长合作。 2. 8:代表字“8”,这个字在中国文化中通常被认为是带有吉祥和好运的意义。这个字反映了华为文化中强调的重视人际关系和沟通。 3. 29:代表日期“29日”,在中国文化中,29日也被认为是一个吉祥的字。它强调了华为所追求的事业理念,即不仅仅关注短期的业绩和利润,更关注长期的战略和价值。 通过twc829这个题目,华为希望了解被试者的个性特征,如能否合作,注重人际关系,有长远的眼光等。这有助于华为招聘到适合公司文化的人才,提升团队合作效率和表现。而对被试者来说,通过参与此测试,也能更好地理解自身的个性特质和适合的职业方向。 ### 回答2: 华为性格测试题目讲解twc829,是针对华为公司的员工进行性格测评的一种方式。该测试题目共分为七大部分,用于测评员工的领导能力、团队合作能力、抗压能力、沟通能力、学习能力、责任心以及创新能力。 第一部分:领导能力。通过测试员工的领导能力,测评员工是否有领导集体的能力,是否适合担任领导。 第二部分:团队合作能力。通过测试员工的团队合作能力,测评员工是否能够与其他员工协同工作,共同完成任务。 第三部分:抗压能力。通过测试员工的抗压能力,测评员工是否能够在压力之下,保持良好的心态和工作状态。 第四部分:沟通能力。通过测试员工的沟通能力,测评员工与其他员工的合作沟通是否有效、是否能够良好沟通协作。 第五部分:学习能力。通过测试员工的学习能力,测评员工是否具有自我学习的能力,是否能够刻苦钻研,提高个人素质。 第六部分:责任心。通过测试员工的责任心,测评员工是否认真负责,做事情认真、细致、规范。 第七部分:创新能力。通过测试员工的创新能力,测评员工是否具有开拓创新、不断追求进步的精神和意愿。 通过华为性格测试题目讲解twc829,可更好的帮助华为公司了解员工个人性格特点和优劣势,帮助员工提高个人能力素质,更好的适应公司的工作要求,从而为公司的发展做出贡献。 ### 回答3: 华为性格测试题目是华为公司为了选拔优秀人才而设立的一个测试,主要考察应聘者的心理素质、智商、情商以及个性特征等方面,是华为公司招聘流程中不可或缺的一个环节。在华为性格测试题目中,每道题目都有其特定的意义和考察目的,应聘者需要认真阅读题目并思考,进行准确的回答。 其中,“twc829”是华为性格测试题目中的一个具有代表性的问题,也是比较具有挑战性的一道题目。它要求应聘者从个选项中选择出一个最符合自己的答案,并用一句话来形容自己。 这道题目的意义在于考察应聘者对自己性格的认识和理解,以及应聘者是否具备言简意赅的表达能力。同时,这道题目涉及到多个选项,每个选项都有着不同的特征和个性,需要应聘者灵活运用自己的思维和分析能力,选择一个最符合自己的答案。 在回答这道题目时,应聘者可以根据自己的实际情况选择最符合自己的选项,并用简洁的语言表达自己的性格特点,展现自己的个性魅力和优势。同时,应聘者还需要注意语言表达的流畅度和准确度,以便给面试官留下深刻的印象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值