798. 得分最高的最小轮调【每日一题】

本文探讨了一种高效算法,通过动态规划避免了N^2复杂度,针对数组 nums 的旋转操作,计算在最少轮调次数下能得到的最大得分。核心思路是利用 step 数组记录每个位置经过不同轮调后相等元素的数量,从而快速确定最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

798. 得分最高的最小轮调

思路

思路1

遍历所有下标,计算对应的分,选最高的,每次就是先构造新的nums出来,然后放到函数里面计算得分,这个得分也要遍历, N^2 估计不能过

a=0
b= len(nums)
        
nums[0:b-1,],temp[b] = nums[1:b], nums[0]

思路二

  1. 我们注意到 0 <= nums[i] < nums.length,那么换句话说每次吧最前面的那个数移到最后,必然得分,

  2. 移位前和移位后有啥联系呢,ennnm,移位后每个数对应的下标都减一(第一个数除外)。移位前比下标小的,必然还是得分(减一最多也就还是相等嘛),移位前相等的丢分,移位前大于的,那前后都不得分

  3. 所以,我们似乎只需要找到移位前有多少值等于下标的就行了,就有 dp[k+1] = dp[k]- 当前值等于下标个数 +1 # 加一是因为第一点说的最前面的那个数移到最后,必然得分

  4. ???那咋晓得每次移位时候等于下标的数字个数呢,又遍历?那不又是n^2了,必不能是这样

  5. 我们可不可以一开始就知道你在多少次移位i后有几个相等的,仔细想了还真可以
    对于 位置i nums[i],有三种可能:
              a           i = nums[i]           必然移位0次时是相等的,只要移位了一次,就不行了,再也遇不到了
              b           i > nums[i]           必然往左移位 i-nums[i] 次就相等了 以后再移位不就成了a情况了
              c           i < nums[i]           必然往左移位 n-(nums[i]-i) 次就相等了 以后再移位不就成了a情况了

  6. 那么我们用一个step数组来记录移位i后有多少相等的,setp[i]代表移位i次数组里面 值等于下标的 个数 根据上面三种情况 有
              a           i = nums[i]           step[0]++
              b           i > nums[i]           step[i-nums[i]]++
              c           i < nums[i]           step[n-(nums[i]-i)]++

    ps:
    a、b 我们稍稍看看就可以发现两种情况可以合并 nums[i] step[i-nums[i]]++。不过我个人觉得不合并更好懂,跟着思路来,所以俺的代码就不合并了

代码

class Solution:
    def bestRotation(self, nums: List[int]) -> int:
        # 思路1
        '''
        遍历所有下标,计算对应的分,选最高的,每次就是先构造新的nums出来,然后放到函数里面计算得分,这个得分也要遍历, N^2 估计不能过
        a=0
        b= len(nums)
        
        temp[0:b-1,],temp[b] = nums[1:b], nums[0]
        '''

        # 思路二
        """
        1 我们注意到  0 <= nums[i] < nums.length,那么换句话说每次吧最前面的那个数移到最后,必然得分,
        2 移位前和移位后有啥联系呢,ennnm,移位后每个数对应的下标都减一(第一个数除外)。移位前比下标小的,必然还是得分(减一最多也就还是相等嘛),移位前相等的丢分,移位前大于的,那前后都不得分
        3 所以,我们似乎只需要找到移位前有多少值等于下标的就行了,就有 dp[k+1] = dp[k]- 当前值等于下标个数 +1 # 加一是因为第一点说的最前面的那个数移到最后,必然得分

        4 ???那咋晓得每次移位时候等于下标的数字个数呢,又遍历?那不又是n^2了,必不能是这样

        我们可不可以一开始就知道你在多少次移位i后有几个相等的,仔细想了还真可以
        对于 位置i nums[i],有三种可能:
            a  i = nums[i]  必然移位0次时是相等的,只要移位了一次,就不行了,再也遇不到了  
            b  i > nums[i]  必然往左移位 i-nums[i] 次就相等了 以后再移位不就成了a情况了
            c  i < nums[i]  必然往左移位 n-(nums[i]-i) 次就相等了 以后再移位不就成了a情况了

        那么我们用一个step数组来记录移位i后有多少相等的,setp[i]代表移位i次数组里面  值等于下标的 个数 根据上面三种情况 有
            a  i = nums[i]  step[0]++
            b  i > nums[i]  step[i-nums[i]]++
            c  i < nums[i]  step[n-(nums[i]-i)]++
        
        ps:
           a、b 我们稍稍看看就可以发现两种情况可以合并   nums[i]  step[i-nums[i]]++。不过我个人觉得不合并更好懂,跟着思路来,所以俺的代码就不合并了
        """ 
        n = len(nums)
        step = [0]*n
        for i in range(n):
            if i==nums[i]:
               step[0] += 1
            elif i>nums[i]:
                step[i-nums[i]] += 1
            else:
                step[n-(nums[i]-i)] += 1

        val = 0
        for i in range(n):
            if i >=nums[i]:
                val += 1
        
        maxval = val
        ans = 0
        for i in range(1,n):
            val = val - step[i-1] +1
            if val >maxval:
                maxval = val
                ans =i

        return ans

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

中南自动化学院至渝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值