来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/smallest-rotation-with-highest-score

题目描述

给你一个数组 nums,我们可以将它按一个非负整数 k 进行轮调,这样可以使数组变为 [nums[k], nums[k + 1], ... nums[nums.length - 1], nums[0], nums[1], ..., nums[k-1]] 的形式。此后,任何值小于或等于其索引的项都可以记作一分。

例如,数组为 nums = [2,4,1,3,0],我们按 k = 2 进行轮调后,它将变成 [1,3,0,2,4]。这将记为 3 分,因为 1 > 0 [不计分]、3 > 1 [不计分]、0 <= 2 [计 1 分]、2 <= 3 [计 1 分],4 <= 4 [计 1 分]。
在所有可能的轮调中,返回我们所能得到的最高分数对应的轮调下标 k 。如果有多个答案,返回满足条件的最小的下标 k 。

示例 1:

输入:nums = [2,3,1,4,0]
输出:3
解释:
下面列出了每个 k 的得分:
k = 0, nums = [2,3,1,4,0], score 2
k = 1, nums = [3,1,4,0,2], score 3
k = 2, nums = [1,4,0,2,3], score 3
k = 3, nums = [4,0,2,3,1], score 4
k = 4, nums = [0,2,3,1,4], score 3
所以我们应当选择 k = 3,得分最高。
示例 2:

输入:nums = [1,3,0,2,4]
输出:0
解释:
nums 无论怎么变化总是有 3 分。
所以我们将选择最小的 k,即 0。

提示:

1 <= nums.length <= 105
0 <= nums[i] < nums.length

解题思路

根据题目最容易想到的是暴力法,尝试用暴力法做,将每个k下的nums数组求出来,统计所有得分,时间复杂度为O(n2),不出所料超时了。

根据题意寻找规律,可以得出结论,每次k加1后,下标会-1,这个时候,原来比下标小的数会继续得分,下标比原来大的数会继续不得分,下标与原来相同的数,会从得分变成失分,下标为0的那个数,下标从0变成了n-1,会变得得分,那么递推公式就可以表示为Vali= Vali-1 - Count下标相同 + 1,只需要初始时候找到最初的val,找到k时候与k下标相同的元素数目,就可以通过一次遍历将所有的得分求出来,时间复杂度为O(n)。这里注意每一个元素必然有且只有一个k使得其下标与元素值相同,所以对于每一个元素值,可以直接找到使得其下标与元素值相同的k,时间复杂度为O(n).

本题还可以通过上下界和差分的方法来做,假设原坐标为i,那么修改后的坐标应该满足0 <= i - k <= n -1 可以推出,k的取值范围为[i - n + 1, i],又从得分条件来说得到 i - k >= x,及k <= i - x,因为x取值范围是[0, n),所以k的取值范围[a ,b]为[i - n + 1, i - x],但是由于存在上下界会出现负数,需要取模为正,所以k的上下界可能出现 a > b的情况,这个时候,可得分的k范围应该为[0, i - n + 1],[i - x, n - 1]。那么,对于i 来说,k在区间[a,b]将会得分,所以可以有一个数组sk来记录每个k的得分情况,遍历每个i将对应区间的k分数分别+1,最终得分最高的k就是最终的解,但是如果这样做的话,时间复杂度仍然为O(n2)。可以使用前缀和+差分的思想,由于是区间修改,所以可以记录sk的一个差分数组diff,diff[i] = sk[i] - sk[i - 1],那么区间[a, b]范围内同时+1的情况,可以将diff[a] +=1, diff[b + 1] -= 1,便可以得到与sk在[a,b]范围内均+1的记录效果,在计算完成后,计算diff的[0, i]前缀和就是sk[i]的结果。

代码展示

暴力法:

class Solution {
public:
int bestRotation(vector<int>& nums) {
int iRet = 0, iMax = 0, n = nums.size();
for(int i = 0; i < n; i++)
{
nums[i] -= i;
}
for (int i = 0; i < n; i++)
{
if (nums[i] <= 0)
{
iMax++;
}
}
for(int i = 1; i < n; i++)
{
int iCount = 0;
for(int j = 0; j < n; j++)
{
if(j == i - 1)
{
nums[j] = nums[j] - n + 1;
}
else
{
nums[j] = nums[j] + 1;
}
if(nums[j] <= 0)
{
iCount++;
}
}
if(iCount > iMax)
{
iMax = iCount;
iRet = i;
}
}
return iRet;
}
};

找规律DP

class Solution {
public:
int bestRotation(vector<int>& nums) {
int iRet = 0, iMax = 0, n = nums.size(), iVal = 0;
for(int i = 0; i < n; i++)
{
if(nums[i] <= i)
{
iMax++;
}
}
vector<int> steps(n, 0);
for(int i = 0; i < n; i++)
{
if(i - nums[i] >= 0)
{
steps[i - nums[i]]++;
}
else
{
steps[i - nums[i] + n]++;
}
}
iVal = iMax;
for(int i = 1; i < n; i++)
{
iVal = iVal - steps[i - 1] + 1;
if(iVal > iMax)
{
iMax = iVal;
iRet = i;
}
}
return iRet;
}
};

上下界+差分数组

class Solution {
public:
int bestRotation(vector<int>& nums) {
int n = nums.size();
vector<int> diff(n, 0);
int iRet = 0;
for(int i = 0; i < n; i++)
{
int a = ((n - i + 1) + n) % n;
int b = ((i - nums[i]) + n) % n;
if(a <= b)
{
diff[a] += 1;
if (b + 1 < n)
{
diff[b + 1] -= 1;
}
}
else
{
diff[0] += 1;
diff[b + 1] -= 1;
diff[a] += 1;
}
}
for(int i = 1; i < n; i++)
{
diff[i] += diff[i - 1];
}
for(int i = 1; i < n; i++)
{
if(diff[iRet] < diff[i])
{
iRet = i;
}
}
return iRet; }
};

运行结果

LeetCode-798 得分最高的最小论调 及差分和前缀和的学习的更多相关文章

  1. Java实现 LeetCode 798 得分最高的最小轮调 (暴力分析)

    798. 得分最高的最小轮调 给定一个数组 A,我们可以将它按一个非负整数 K 进行轮调,这样可以使数组变为 A[K], A[K+1], A{K+2], - A[A.length - 1], A[0] ...

  2. [差分数组] LeetCode789 得分最高的最小轮调

    LeetCode 得分最高的最小轮调 今天当然CV了因为今天比较忙,所以直接走算法,因为什么都不做的话并不符合社会主义核心价值观,今天小学一手查分数组. 题目:并不存在CV了还写什么题解 算法背景: ...

  3. [LeetCode] 727. Minimum Window Subsequence 最小窗口子序列

    Given strings S and T, find the minimum (contiguous) substring W of S, so that T is a subsequenceof  ...

  4. [Swift]LeetCode798. 得分最高的最小轮调 | Smallest Rotation with Highest Score

    Given an array A, we may rotate it by a non-negative integer K so that the array becomes A[K], A[K+1 ...

  5. LeetCode之Min Stack 实现最小栈

    LeetCode相关的网上资源比较多,看到题目一定要自己做一遍,然后去学习参考其他的解法. 链接: https://oj.leetcode.com/problems/min-stack/ 题目描述: ...

  6. LeetCode 155 Min Stack(最小栈)

    翻译 设计支持push.pop.top和在常量时间内检索最小元素的栈. push(x) -- 推送元素X进栈 pop() -- 移除栈顶元素 top() -- 得到栈顶元素 getMin() -- 检 ...

  7. LeetCode 939. Minimum Area Rectangle (最小面积矩形)

    题目标签:HashMap 题目给了我们一组 xy 上的点坐标,让我们找出 能组成矩形里最小面积的那个. 首先遍历所有的点,把x 坐标当作key 存入map, 把重复的y坐标 组成set,当作value ...

  8. LeetCode 1255 得分最高的单词集合 Maximum Score Words Formed by Letters

    地址 https://leetcode-cn.com/problems/maximum-score-words-formed-by-letters/ 题目描述你将会得到一份单词表 words,一个字母 ...

  9. [LeetCode] 910. Smallest Range II 最小区间之二

    Given an array A of integers, for each integer A[i] we need to choose either x = -K or x = K, and ad ...

  10. [LeetCode] 908. Smallest Range I 最小区间

    Given an array A of integers, for each integer A[i] we may choose any x with -K <= x <= K, and ...

随机推荐

  1. 痞子衡嵌入式:低功耗&高性能边缘人工智能应用的新答案 - MCXN947

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦MCX系列MCU的新品MCXN947. 自 2015 年恩智浦和飞思卡尔合并成新恩智浦之后,关于它们各自的 Arm Cortex- ...

  2. What's new in Dubbo 3.1.4 and 3.2.0-beta.3

    在 12 月 22 日,Dubbo 3.1.4 和 3.2.0-beta.3 正式通过投票发布.本文将介绍发布的变化一览. Dubbo 3.1.4 版本是目前 Dubbo 3 的最新稳定版本,我们建议 ...

  3. 一个简单的rust字符串时钟

    1.简介   用rust写的一个简单的练手的demo,一个字符串时钟,在终端用字符串方式显示当前时间.本质是对图片取灰度,然后每个像素按灰度门限用星号代替灰度值,就把图片变为由星号组成的字符型图案.把 ...

  4. [cocos2d-x]捕鱼达人炮台射击角度的旋转实现

    话不多说,先上图,下面是实现代码(在后面会具体讲解实现过程): //第一步:将炮台的坐标转换为世界坐标下的坐标点 CCPoint location = this->getParent()-> ...

  5. ABC238E Range Sums

    简要题意 有一个长度为 \(N\) 的序列 \(a\),你知道 \(Q\) 个区间的和.求是否可以知道 \([1,n]\) 的和. \(1 \leq N,Q \leq 2 \times 10^5\) ...

  6. SPOJ PHONELST - Phone List | UVA11362 Phone List | LibreOJ10049. 「一本通 2.3 例 1」Phone List

    简要题意 \(t\) 组数据,每组数据给定 \(n\) 个长度不超过 \(10\) 的数字串,判断是否有两个字符串 \(A\) 和 \(B\),满足 \(A\) 是 \(B\) 的前缀,若有,输出 N ...

  7. 快速入门pandas进行数据挖掘数据分析[多维度排序、数据筛选、分组计算、透视表](一)

    1. 快速入门python,python基本语法 Python使用缩进(tab或者空格)来组织代码,而不是像其 他语言比如R.C++.Java和Perl那样用大括号.考虑使用for循 环来实现排序算法 ...

  8. Vue3源码阅读梳理

    简单代码例子 const { createApp, defineComponent, computed, watch, ref, reactive, effect } = Vue const app ...

  9. 亲测有效! TG Pro 实时温度工具 V2.7.6 for mac 破解版

    亲测有效! TG Pro 实时温度工具 V2.7.6 for mac 破解版 TG Pro (Temperature Gauge Pro) 是一款专业显示你的Mac实时温度的软件,可以在系统内的菜单栏 ...

  10. VMware 虚拟机安装 OpenWrt 作旁路由 单臂路由 img 镜像转 vmdk 旁路由无法上网 没网络

    重要注意事项 由于布线原因笔记本只能采用无线的方式连接路由器,在Windows10的环境下使用无线网卡桥接,结果软路由无法上网,翻阅了各种帖子最终发现跟系统底层的协议栈有关系,随即放弃使用有线网卡,不 ...