刷题日记1——leetcode1954(收集足够苹果的最小花园周长)

本文讲述了如何解决LeetCode中的1954题——最小花园周长问题,通过将花园划分为等腰直角三角形并利用等差数列求和公式,最终实现一次循环优化算法,从O(n²)降低到O(n)。
摘要由CSDN通过智能技术生成

       今天leetcode的每日一题给到了1954——收集足够苹果的最小花园周长,难度中等。

       第一眼看到这道题的时候,我就想到了可以“以小解大”,就是将整个花园分成四等份,每个象限为一份,算出的结果只需要乘以4就可以了,但是随着想法的深入我发现,竟然都已经把他化得这么小了,为什么不直接一条路走到黑,再分成两个三角形呢?就是如下的三角形。,由于题目的特殊性,对角线上的数一定是偶数,于是我把对角线上的树分成两部分,但是x轴上的数没那么好运,并不全是偶数,但是无妨,我还是直接把它“劈成两半”。到此纵观全局来看,所有将树分开的行为,都是为了最后乘以8,才是完美等于原先的数量的。同时,我们选的位置坐标值都是正的,于是就不用考虑绝对值的情。以后在遇到这种题时,都可以采用这种分割求解的办法,减少运算量同时增大成功率。

       又由于分割的三角形是等腰直角三角形,我定义一个x,y,就可以把所有坐标表示出来,于是现在的考虑就是,我要求出比neededApples大的那个x,于是考虑双重循环,由于数值间数据类型不同,所以为了避免数据丢失,我都将其强制转化成double类型。但是这么简单的代码还是超时了,因为是双重循环,该算法的时间复杂度为O(n²),对于很大的数据来说,循环两次一定会超时,但是不可否认的是,这个算法确实是正确的。于是我便重新考虑能不减少一层循环呢?

long long minimumPerimeter(long long neededApples) {
    long long  x,y;
    double sum=0;
    for ( x=0;sum<(double)neededApples/8;x++)
    {
        for ( y=0;y<=x && sum<(double)neededApples/8;y++)
        {
            if (x==y || y==0)
            {
                sum+=(double)(x+y)/2;
            }
            else 
            {
                sum+=(double)x+(double)y;
            }
        }
    }
    return (x-1)*8;
}

       回想一下题目的特殊,这个题目我将其分割成了八份,这八份都是完全相等的等腰直角三角形,基于这个特性,我在想能不能通过数学公式来求解这个问题。回到最初,我们把不属于三角形的部分删去了,导致我看不出来这个规律,现在我又把它加回去,观察是不是有规律。

       相信聪明的你也看出来了,这里的每一列的苹果的和不就是满足等差数列的公式吗?是的,那让我来找出这个等差数列的基本元素。

       ①对于一个首项a1=x,它的末项an=2*x;

       ②对于每一组数据,它的公差d=1;

       ③对于每一组数据,它的项数为n+1;

       结合上述结果,每一个以x为首项的数列的和为sn=n*a1+n(n-1)*d/2,算出来是sn=(3*x*x+3*x)/2,于是每一组数据的和就求完了,但别忘了,刚刚加上去的不属于三角形内的数要减去,也就是减去x/2+x,于是真正的和为Sn=3*x*x/2,下面是代码的实现。

long long minimumPerimeter(long long neededApples) {
    long long  x;
    double sum=0;
    for ( x=0;sum<(double)neededApples/8;x++)
    {
        sum+=(double)x*(double)x*3/2;
    }
    return (x-1)*8;
}

       这个代码过了,我以为这个代码够简单了,因为只用了一层循环,时间复杂度为O(n),但是只打败了20%的人,后面我看题解,发现居然还有两行代码能够完成的大佬。通过刷算法题我感受到了自己不会的还有很多,还是需要认真学。

       如有需要改进的地方,欢迎指出。感谢您看到这里!

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值