收集巧克力(LeetCode日记)

LeetCode-2735-收集巧克力

题目信息:

给你一个长度为

n

n

n 、下标从

0

0

0 开始的整数数组

n

u

m

s

nums

nums ,表示收集不同巧克力的成本。每个巧克力都对应一个不同的类型,最初,位于下标

i

i

i 的巧克力就对应第

i

i

i 个类型。

在一步操作中,你可以用成本

x

x

x 执行下述行为:

同时修改所有巧克力的类型,将巧克力的类型

i

t

h

i^{th}

ith 修改为类型

(

(

i

+

1

)

m

o

d

n

)

t

h

((i + 1) mod n)^{th}

((i+1)modn)th

假设你可以执行任意次操作,请返回收集所有类型巧克力所需的最小成本。

  • 示例1:

输入:nums = [20,1,15], x = 5
输出:13
解释:最开始,巧克力的类型分别是 [0,1,2] 。我们可以用成本 1 购买第 1 个类型的巧克力。
接着,我们用成本 5 执行一次操作,巧克力的类型变更为 [1,2,0] 。我们可以用成本 1 购买第 2 个类型的巧克力。
然后,我们用成本 5 执行一次操作,巧克力的类型变更为 [2,0,1] 。我们可以用成本 1 购买第 0 个类型的巧克力。
因此,收集所有类型的巧克力需要的总成本是 (1 + 5 + 1 + 5 + 1) = 13 。可以证明这是一种最优方案。

  • 示例2:

输入:nums = [1,2,3], x = 4
输出:6
解释:我们将会按最初的成本收集全部三个类型的巧克力,而不需执行任何操作。因此,收集所有类型的巧克力需要的总成本是 1 + 2 + 3 = 6 。

提示:

  • 1 <= nums.length <= 1000
  • 1 <= nums[i] <= 109
  • 1 <= x <= 109

相关标签 :数组、枚举、动态规划

题解

今天的问题属于中等难度,初见这道题,我认为动态规划将是一个很好的思路。对于每次操做,都可以比较当前情况下,直接收集权值最小的蛋糕 或者 先进行操做在进行购买权值最小的蛋糕。可是尝试后发现这样并不成功。下面我们来看一下正确的方法。

方法:枚举收集的次数

对于初始类型为

i

i

i 的巧克力,如果我们一共进行了

k

k

k

kkk

kkk 次操作,相当于我们可以用:

n

u

m

s

[

i

]

,

n

u

m

s

[

(

i

+

1

)

m

o

d

n

]

,

,

n

u

m

s

[

(

i

+

k

)

m

o

d

n

]

            

(

1

)

nums[i],nums[(i+1)modn],⋯,nums[(i+k)modn] (1)

nums[i],nums[(i+1)modn],,nums[(i+k)modn]            (1)

中的任意成本去购买它。由于我们希望成本最小,那么我们一定选择上述

k

+

1

k+1

k+1 个成本中的最小值。同时我们发现,当进行了第

n

n

n 次操作后,它的价格又会回到

n

u

m

s

[

i

]

nums[i]

nums[i] 并继续开始循环,因此操作的次数不会超过

n

1

n−1

n1

这样一来,我们就可以枚举操作次数了,它的范围为

[

0

,

n

1

]

[0,n−1]

[0,n1] 。当操作次数为

k

k

k 时,初始类型为

i

i

i 的巧克力需要的成本就是

(

1

)

(1)

(1) 中的最小值,我们就可以使用一个二维数组

f

(

i

,

k

)

f(i,k)

f(i,k) 记录该值,它有如下的递推式:

{

f

(

i

,

0

)

=

n

u

m

s

[

i

]

f

(

i

,

k

)

=

min

{

f

(

i

,

k

1

)

,

n

u

m

s

[

(

i

+

k

)

m

o

d

n

]

}

left{begin{array}{l}f(i, 0)=n u m s[i] \f(i, k)=min {f(i, k-1), n u m s[(i+k) bmod n]}end{array}right.

{f(i,0)=nums[i]f(i,k)=min{f(i,k1),nums[(i+k)modn]}

f

(

i

,

k

)

f(i,k)

f(i,k) 相较于

f

(

i

,

k

1

)

f(i,k−1)

f(i,k1) ,多了一个

n

u

m

s

[

(

i

+

k

)

m

o

d

n

]

nums[(i+k) mod n]

nums[(i+k)modn] 的选择。此时,操作次数为

k

k

k 时的最小成本即为:

k

x

+

i

=

0

n

1

f

(

i

,

k

)

            

(

2

)

k cdot x+sum_{i=0}^{n-1} f(i, k) (2)

kx+i=0n1f(i,k)            (2)

最终的答案即为所有

k

[

0

,

n

1

]

k∈[0,n−1]

k[0,n1] 中式

(

2

)

(2)

(2) 的最小值。

实现代码(Python)
class Solution:
    def minCost(self, nums: List[int], x: int) -> int:
        n = len(nums)
        f = nums[:]  # 初始化 f 数组,表示当前位置开始的最小成本
        ans = sum(f)  # 初始化结果为 f 的总和

        for k in range(1, n):
            # 更新 f 数组,每次将当前位置的值更新为当前位置和右侧位置的最小值
            for i in range(n):
                f[i] = min(f[i], nums[(i + k) % n])

            # 更新结果,计算当前成本并加上操作次数乘以 x
            ans = min(ans, k * x + sum(f))
        
        return ans
复杂度分析:
  • 时间复杂度:

    O

    (

    n

    2

    )

    O(n^2)

    O(n2)

  • 空间复杂度:

    O

    (

    n

    )

    O(n)

    O(n)

题记:


  • 研究生在读,我会尽量保持LeetCode每日一题的思路和代码输出。希望大家多多支持。
  • 水平有限,希望各位大佬能够批评指正。您的教诲是我进步的船帆。
  • 希望各位跟我一样的小白能跟我一起参与到做题和讨论中来。共同进步是我所能期盼的最高愿想。
  • 您的点赞和关注是我坚持分享的动力泉源,希望能将这件简单平凡的事一直做下去。感谢大家。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇

)">
下一篇>>