LeetCode-798 得分最高的最小论调 及差分和前缀和的学习
来源:力扣(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 得分最高的最小论调 及差分和前缀和的学习的更多相关文章
- Java实现 LeetCode 798 得分最高的最小轮调 (暴力分析)
798. 得分最高的最小轮调 给定一个数组 A,我们可以将它按一个非负整数 K 进行轮调,这样可以使数组变为 A[K], A[K+1], A{K+2], - A[A.length - 1], A[0] ...
- [差分数组] LeetCode789 得分最高的最小轮调
LeetCode 得分最高的最小轮调 今天当然CV了因为今天比较忙,所以直接走算法,因为什么都不做的话并不符合社会主义核心价值观,今天小学一手查分数组. 题目:并不存在CV了还写什么题解 算法背景: ...
- [LeetCode] 727. Minimum Window Subsequence 最小窗口子序列
Given strings S and T, find the minimum (contiguous) substring W of S, so that T is a subsequenceof ...
- [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 ...
- LeetCode之Min Stack 实现最小栈
LeetCode相关的网上资源比较多,看到题目一定要自己做一遍,然后去学习参考其他的解法. 链接: https://oj.leetcode.com/problems/min-stack/ 题目描述: ...
- LeetCode 155 Min Stack(最小栈)
翻译 设计支持push.pop.top和在常量时间内检索最小元素的栈. push(x) -- 推送元素X进栈 pop() -- 移除栈顶元素 top() -- 得到栈顶元素 getMin() -- 检 ...
- LeetCode 939. Minimum Area Rectangle (最小面积矩形)
题目标签:HashMap 题目给了我们一组 xy 上的点坐标,让我们找出 能组成矩形里最小面积的那个. 首先遍历所有的点,把x 坐标当作key 存入map, 把重复的y坐标 组成set,当作value ...
- LeetCode 1255 得分最高的单词集合 Maximum Score Words Formed by Letters
地址 https://leetcode-cn.com/problems/maximum-score-words-formed-by-letters/ 题目描述你将会得到一份单词表 words,一个字母 ...
- [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 ...
- [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 ...
随机推荐
- 【基于OpenAI的ChatGPT】搭建属于自己的微信聊天机器人(附带注册英国手机号码方式)
前言:这几天 OpenAI的聊天机器人很火,前两天也爆发了很多关于ChatGPT接入微信的文章.我就顺便[借用别人已有的项目],来部署一个属于自己的微信聊天机器人.项目地址见下文. 1.首先需要有一个 ...
- 填坑日志-云网络智慧课堂双网卡Mac地址读取错误的问题及解决
云网络智慧课堂的双网卡问题记录及解决方案 教师端 其实这里双网卡的问题一直没有解决,分为了两部分,一部分是教师端,一部分是学生端.症状类似,问题也类似,都是在设计之初因为硬件限制可能没有考虑到双网卡的 ...
- context状态树
provider customer 父组件 创建context对象并导出 export const AddContext = React.createContext<any>({}) 导出 ...
- SpringCloud微服务框架复习笔记
SpringCloud微服务框架复习笔记 什么是微服务架构? 微服务是一种软件开发技术,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值.每个服务运行在其独立的进 ...
- java中json字符串与实体类对象相互转换
1.问题描述 有一个需求是这样的,把实体类转为Json字符串存入redis中,然后再把redis中存放的实体类Json字符串插入数据库中.因此需要涉及到json字符串与实体类对象的相互转换. 2.产生 ...
- centos更新glibc-2.28
vps安装alist时提示glibc版本太老,找了一圈教程,就这个解决了问题. 原文: https://www.cnblogs.com/FengZeng666/p/15989106.html
- [数据结构]深度优先搜索算法(Depth-First-Search,DFS)
深度优先搜索算法的概念 与广度优先搜索算法不同,深度优先搜索算法类似与树的先序遍历.这种搜索算法所遵循的搜索策略是尽可能"深"地搜索一个图.它的基本思想如下:首先访问图中某一个起始 ...
- effective-c 条款2理解与思考
尽量使用const,enum,inline替换 #define 因为,#define 替换发生在预处理阶段,编译器对这个替换内容就缺少了类型检测,并且不利于错误信息的查看 编译器再声明数组时必须知道数 ...
- 【Django drf】视图类APIView之五层封装 ApiView的类属性 drf配置文件
目录 ApiView的类属性 drf 配置文件之查找顺序 drf之请求 APIView之请求相关配置 drf之响应 APIView之响应相关配置 Response对象属性 视图类 序列化类 路由 基于 ...
- Windows 映射网络驱动器及删除-此网格连接不存在
将共享目录,映射到本地磁盘,可以方便快速访问 添加 点击[此电脑]菜单栏中,选择[计算机]->[映射网格驱动器]-> 文件夹中输入 共享目录地址,如下图 删除 右击,网格映射盘,右击[断开 ...