收集足够苹果的最小花园周长(LeetCode日记)

LeetCode-1954-收集足够苹果的最小花园周长

题目信息:

给你一个用无限二维网格表示的花园,每一个 整数坐标处都有一棵苹果树。整数坐标 ( i , j ) (i, j) (i,j) 处的苹果树有 ∣ i ∣ + ∣ j ∣ |i| + |j| i+j 个苹果。
你将会买下正中心坐标是 ( 0 , 0 ) (0, 0) (0,0) 的一块 正方形土地 ,且每条边都与两条坐标轴之一平行。
给你一个整数 n e e d e d A p p l e s neededApples neededApples ,请你返回土地的 最小周长 ,使得 至少 有 n e e d e d A p p l e s neededApples neededApples 个苹果在土地 里面或者边缘上。
∣ x ∣ |x| x 的值定义为:

  • 如果 x > = 0 x >= 0 x>=0 ,那么值为 x x x
  • 如果 x < 0 x < 0 x<0 ,那么值为 − x -x x

收集足够苹果的最小花园周长(LeetCode日记)_第1张图片

  • 示例1:

输入: n e e d e d A p p l e s neededApples neededApples = 1
输出:8
解释:边长长度为 1 的正方形不包含任何苹果。 但是边长为 2 的正方形包含 12 个苹果(如上图所示)。
周长为 2 * 4 = 8 。

  • 示例2:

输入: n e e d e d A p p l e s neededApples neededApples = 13
输出:16

  • 示例3:

输入: n e e d e d A p p l e s neededApples neededApples = 1000000000
输出:5040

提示:

  • 1 < = n e e d e d A p p l e s < = 1 0 15 1 <= neededApples <= 10^{15} 1<=neededApples<=1015

相关标签 :数学,二分查找

题解

首先我们要承认这样一个事实:如果正方形土地的右上角坐标为 ( n , n ) (n,n) (n,n),即边长为 2 n 2n 2n,周长为 8 n 8n 8n,那么其中包含的苹果总数为: S n = 2 n ( n + 1 ) ( 2 n + 1 ) S _n=2n(n+1)(2n+1) Sn=2n(n+1)(2n+1)
下面我们来证明一下这个公式:
对于坐标为 ( x , y ) (x,y) (x,y) 的树,它有 ∣ x ∣ + ∣ y ∣ ∣x∣+∣y∣ x+y 个苹果。因此,一块右上角坐标为 ( n , n ) (n,n) (n,n) 的正方形土地包含的苹果总数为:(x与y对称)
S n = 2 ∑ x = − n n ∑ y = − n n ∣ x ∣ + ∣ y ∣ = 2 ∑ x = − n n ∑ y = − n n ∣ x ∣ = 2 ∑ x = − n n ( 2 n + 1 ) ∣ x ∣ = 2 ( 2 n + 1 ) ∑ x = − n n ∣ x ∣ = 2 n ( n + 1 ) ( 2 n + 1 ) \begin{aligned}S_{n} & =2 \sum_{x=-n}^{n} \sum_{y=-n}^{n}|x|+|y| \\& =2 \sum_{x=-n}^{n} \sum_{y=-n}^{n}|x| \\& =2 \sum_{x=-n}^{n}(2 n+1)|x| \\& =2(2 n+1) \sum_{x=-n}^{n}|x| \\& =2 n(n+1)(2 n+1)\end{aligned} Sn=2x=nny=nnx+y=2x=nny=nnx=2x=nn(2n+1)x=2(2n+1)x=nnx=2n(n+1)(2n+1)
基于这样的思路,我们可以有两种方法来实现算法:暴力枚举与二分查找。

方法1:暴力枚举

从小到大枚举 n n n,直到 2 n ( n + 1 ) ( 2 n + 1 ) ≥ n e e d e d A p p l e s 2n(n+1)(2n+1)≥neededApples 2n(n+1)(2n+1)neededApples 为止。

实现代码(Python)
class Solution:
    def minimumPerimeter(self, neededApples: int) -> int:
        n = 1
        while 2 * n * (n + 1) * (2 * n + 1) < neededApples:
            n += 1
        l = n * 8
        return l
复杂度分析:
  • 时间复杂度: O ( m 1 / 3 ) O(m ^{1/3} ) O(m1/3) 其中 ,m为题目中所提到的 n e e d e d A p p l e s neededApples neededApples
  • 空间复杂度: O ( 1 ) O(1) O(1)
方法2:二分查找

由于 S n S_n Sn是随着 n n n 单调递增的,那么我们可以通过二分查找的方法,找出最小的满足 S n ≥ n e e d e d A p p l e s S 的 Sn≥neededApplesS的 SnneededApplesSn值即为答案。
​通过提示我们可知: 1 < = n e e d e d A p p l e s < = 1 0 15 1 <= neededApples <= 10^{15} 1<=neededApples<=1015 , 我们计算的坐标 ( n , n ) (n,n) (n,n)一定会存在一个上界,可以使用我们上文计算的式子 S n = 2 n ( n + 1 ) ( 2 n + 1 ) S _n=2n(n+1)(2n+1) Sn=2n(n+1)(2n+1)来进行推理得到最大的n。

实现代码(Python)
class Solution:
    def minimumPerimeter(self, neededApples: int) -> int:
        low, high, n = 1, 100000, 0
        while left <= right:
            mid = (low + high) // 2
            if 2 * mid * (mid + 1) * (mid * 2 + 1) >= neededApples:
                n = mid
                high = mid - 1
            else:
                low = mid + 1
        return n * 8
复杂度分析:
  • 时间复杂度: O ( l o g 2 m ) O(log_2m) O(log2m) 其中 ,m为题目中所提到的 n e e d e d A p p l e s neededApples neededApples
  • 空间复杂度: O ( 1 ) O(1) O(1)

题记:


  • 研究生在读,我会尽量保持LeetCode每日一题的思路和代码输出。希望大家多多支持。
  • 水平有限,希望各位大佬能够批评指正。您的教诲是我进步的船帆。
  • 希望各位跟我一样的小白能跟我一起参与到做题和讨论中来。共同进步是我所能期盼的最高愿想。
  • 您的点赞和关注是我坚持分享的动力泉源,希望能将这件简单平凡的事一直做下去。感谢大家。

你可能感兴趣的:(LeetCode每日一题,leetcode,算法,python)