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 ...
随机推荐
- hook 无限debugger(猿人学第十四题)
猿人学第十四题 检测太多了,debugger fiddler替换无法实现.置空也不行.推荐使用hook Function原生的构造 var func_ = Function.prototype.c ...
- 笑死,面试官又问我SpringBoot自动配置原理
面试官:好久没见,甚是想念.今天来聊聊SpringBoot的自动配置吧? 候选者:嗯,SpringBoot的自动配置我觉得是SpringBoot很重要的"特性"了.众所周知,Spr ...
- 利用Git同步思源笔记
旧文章从语雀迁移过来,原日期为2022-10-22 思源笔记是一款优秀的本地优先的双链大纲笔记软件,拥有强大的笔记编辑功能且都是免费,唯一付费的就是云同步等一些服务了.但如果暂时还用不着云同步的,我们 ...
- 万字长文详解 YOLOv1-v5 系列模型
一,YOLOv1 Abstract 1. Introduction 2. Unified Detectron 2.1. Network Design 2.2 Training 2.4. Inferen ...
- .NET性能优化-使用RecyclableMemoryStream替代MemoryStream
提到MemoryStream大家可能都不陌生,在编写代码中或多或少有使用过:比如Json序列化反序列化.导出PDF/Excel/Word.进行图片或者文字处理等场景.但是如果使用它高频.大数据量处理这 ...
- NW js 打包入门教程
NW js 打包入门教程 NW.JS的安装与打包_u013288292的博客-CSDN博客_nwjs打包
- 腾讯出品小程序自动化测试框架【Minium】系列(一)环境搭建之第一个测试程序
一.什么是Minium? minium是为小程序专门开发的自动化框架,使用minium可以进行小程序UI自动化测试. 当然,它的能力不仅仅局限于UI自动化, 比如: 使用minium来进行函数的moc ...
- 快速排序——C++左闭右开区间实现
代码 #include<iostream> #include<vector> using namespace std; class Solution { public: //快 ...
- pycham debug 专辑
遇到大量代码的项目时怎么迅猛的调代码今天将交给大家几个方法 配置环境: 环境的统一是一切的基础,因为不同的版本不同步之间会造成很多各式各样的报错 然后选择现有环境进行配置 上面的路径进行默认环境变量的 ...
- 特殊input框需求,粘贴文字或者扫码筛选检查后加密为password格式,否则正常显示/假如用户输入的信息是以mima开头,就切换输入框为密码类型
1.angular8粘贴文字或者扫码筛选检查后加密为password格式,否则正常显示 <input [type]="myInputType" (keyup.enter)=& ...