【力扣刷题】第三天:有效三角形的个数、快乐数

1、快乐数

        原题202. 快乐数 - 力扣(LeetCode)

题目解析

        这道题的难度并不算高,重点是需要看清楚题目的描述,根据题目描述我们可以知道这个快乐数在计算过程中只会进入两种状态,一种是进入循环且进入循环的节点值不为1。第二种是某一轮计算出结果为1 。通过观察我们可以发现,这两种情况可以合并为一种情况,可以将它们都看作循环,只不过第二种的循环里只有1这个节点而已。所以我们只需要判断这个计算过程种什么时候进入循环,且进入循环时的节点为几就行了。

解题思路

        如果大家有写过链表的算法题,应该会知道这道题和其中一道题很像,就是判断一个链表是否存在循环,在那道题里,我们可以通过设置快慢指针的方式,当快慢指针指向同一节点时就代表这个链表为带环链表。

        在这道题中,我们也可以利用双链表的思想来解决问题,但是并不是真的定义两个指针,而是定义两个变量,两个变量最开始都等于初始值,快的变量一次计算两次,慢的变量一次计算一次,循环计算,一直计算到两个变量相等为止,退出循环,判断是否为1,为1则返回true,否则返回false。

        需要注意的是,因为我们退出循环的条件是两个变量相等,而一开始它们的值都是初始值,所以在进入循环之前需要先计算一次再进入循环。

        完整代码如下

class Solution {
public:
    bool isHappy(int n) {
        int slow = 0;
        int fast = 0;
        while (n)
        {
            fast += (n % 10) * (n % 10);
            n /= 10;
        }
        n = slow = fast;
        fast = 0;
        while (n)
        {
            fast += (n % 10) * (n % 10);
            n /= 10;
        }

        while (slow != fast)
        {
            int time = 0;
            while (slow != fast && time <2)
            {
                int tmp = fast;
                fast = 0;
                while (tmp)
                {
                    fast += (tmp % 10) * (tmp % 10);
                    tmp /= 10;
                }
                time++;
            }
            if (slow == fast)
            {
                break;
            }
            else
            {
                int tmp = slow;
                slow = 0;
                while (tmp)
                {
                    slow += (tmp % 10) * (tmp % 10);
                    tmp /= 10;
                }
            }
        }
        return fast == 1;
    }
};

2、有效三角形的个数

        原题611. 有效三角形的个数 - 力扣(LeetCode)

题目解析

        这个题目比快乐数的题目还要简单,只需要计算出这个数组里总共有多少组数字可以组成一个三角形就行了,唯一需要注意的是数字可以重复。

解题思路

        相信大家都知道该怎么判断三条边是否能组成一个三角形,就是任意两边之长大于第三边。但是其实有一个更简单的方法,我们只要先获取三个数中最大的那个数字,再计算出剩下两个数之和是否大于第三边就行了,因为最大的数无论和哪一个数相加都肯定大于另一个数,就不用再计算了。

        得出了上面的结论,那我们应该如何把算法思想转化为代码呢?首先第一步,既然每次我都要获取一个三元组里最大的值,那我为什么不干脆先将整个数组都变得有序呢?这样数组的最后一个元素就是最大值了,然后再定义两个变量,一个变量left指向数组的第一个元素,第二个变量right指向最大值的前一个元素,然后进行计算,如果left和right之和小于最大值,则left向右移动,值变大;如果和大于最大值,那说明left和right中间这一块区域的所有元素与right组合都满足题意,记录下left和right之间的元素个数,right向左移动,left重新回到第一个元素位置,开始一轮新的筛选。当第一轮筛选结束,最大值指向的位置向左移动,开始新的一轮,直到最大值指向的位置下标小于2为止,然后返回全部满足的个数。

        完整代码如下

class Solution {
public:
    int triangleNumber(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int fir = 0, tir = nums.size() - 1, sec = tir - 1;
        int sum = 0;
        while (tir >= 2)
        {
            while (fir != sec)
            {
                if (nums[fir] + nums[sec] > nums[tir])
                {
                    sum += sec - fir;
                    sec--;
                }
                else
                {
                    fir++;
                }
            }
            tir--;
            fir = 0;
            sec = tir - 1;
        }
        return sum;
    }
};
评论 19
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值