LeetCode – 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], A{K+2], ... A[A.length - 1], A[0], A[1], ..., A[K-1]. Afterward, any entries that are less than or equal to their index are worth 1 point.
For example, if we have [2, 4, 1, 3, 0], and we rotate by K = 2, it becomes [1, 3, 0, 2, 4]. This is worth 3 points because 1 > 0 [no points], 3 > 1 [no points], 0 <= 2 [one point], 2 <= 3 [one point], 4 <= 4 [one point].
Over all possible rotations, return the rotation index K that corresponds to the highest score we could receive. If there are multiple answers, return the smallest such index K.
Example 1:
Input: [2, 3, 1, 4, 0]
Output: 3
Explanation:
Scores for each K are listed below:
K = 0, A = [2,3,1,4,0], score 2
K = 1, A = [3,1,4,0,2], score 3
K = 2, A = [1,4,0,2,3], score 3
K = 3, A = [4,0,2,3,1], score 4
K = 4, A = [0,2,3,1,4], score 3
So we should choose K = 3, which has the highest score.
Example 2:
Input: [1, 3, 0, 2, 4]
Output: 0
Explanation: A will always have 3 points no matter how it shifts.
So we will choose the smallest K, which is 0.
Note:
A will have length at most 20000.
A[i] will be in the range [0, A.length].
暴力解法会超时
class Solution {
public int bestRotation(int[] A) {
if(A == null || A.length == 0){
return 0;
}
int k = 0;
int max = 0;
int[] points = new int[A.length];
for(int i = 0; i < A.length; i++){
for(int j = 0; j < A.length; j++){
int newIndex = (A.length - (j-i)) % A.length;
if(newIndex >= A[i]){
points[j]++;
}
}
}
for(int i = 0; i < points.length; i++){
if(points[i] > max){
max = points[i];
k =i;
}
}
return k;
}
}
这道题给了我们一个长度为N的数组,说是数组中的数字的范围都在[0, N]之间,然后定义了一个旋转操作,比如在位置K进行旋转,数组在K位置断开,新数组以A[k]为开头数字,断开的前半段数组直接拼到末尾即可。然后又定义了一种积分规则,说是如果某个坐标位置大于等于其数字的话,得1分,让我们求出某个旋转位置K,使得其积分最大,如果积分相同的话,取位置小的K。通过分析题目中的例子,发现题目并不难理解。博主首先尝试了暴力搜索的方法,就是遍历每个K值,生成旋转后的数组,然后再统计得分,不幸挂掉了。那么我们必须要想出更好的解法才行。首先我们想,如果数组中的每个数字都跟其坐标值相同的话,比如[0, 1, 2, 3, 4],那么肯定得分最高,即K=0。但实际上并不会是有序的,而且并不是每个数字都会出现,题目中只给了数字的范围,有可能会有重复数字哦。说实话这道题博主研究大神lee215的帖子,都研究了好久,最后终于有些明白了,就大概讲讲吧,如果有不对的地方欢迎大家指正。
这道题博主感觉还是很有难度的,而且答案的思路也十分巧妙,并没有采用brute force那种直接求每一个K值的得分,而是反其道而行之,对于每个数字,探究其跟K值之间的联系。首先我们要讨论一下边界情况,那么就是当A[i] = 0 或 N 的情况,首先如果A[i] = 0的话,那么0这个数字在任何位置都会小于等于坐标值,所以在任何位置都会得分的,那么其实可以忽略之,因为其不会对最大值产生任何影响,同理,如果A[i] = N的时候,由于长度为N的数组的坐标值范围是[0, N-1],所以数字N在任何位置都不得分,同样也不会对最大值产生任何影响,可以忽略之。那么我们关心的数字的范围其实是[1, N-1]。在这个范围内的数字在旋转数组的过程中,从位置0变到N-1位置的时候,一定会得分,因为此范围的数字最大就是N-1。这个一定得的分我们在最后统一加上,基于上面的发现,我们再来分析下题目中的例子 [2, 3, 1, 4, 0],其中红色数字表示不得分的位置:
A: 1 0 (K = 0)
A: 1 0 2 (K = 1)
A: 0 2 3 (K = 2)
A: 0 2 3 1 (K = 3)
A: 0 1 4 (K = 4)
idx: 0 1 2 3 4
对于某个数字A[i],我们想知道其什么时候能旋转到坐标位置为A[i]的地方,这样就可以得分了。比如上面博主标记了红色的数字3,最开始时的位置为1,此时是不得分的,我们想知道其什么时候能到位置3,答案是当K=3的时候,其刚好旋转到位置3,K再增加的时候,其又开始不得分了。所以这个最后能得分的临界位置是通过 (i - A[i] + N) % N 得到,那么此时如果K再增加1的话,A[i]就开始不得分了(如果我们suppose每个位置都可以得分,那么不得分的地方就可以当作是失分了),所以我们可以在这个刚好开始不得分的地方标记一下,通过-1进行标记,这个位置就是 (i - A[i] + 1 + N) % N。我们用一个长度为N的change数组,对于每个数字,我们都找到其刚好不得分的地方,进行-1操作,那么此时change[i]就表示数组中的数字在i位置会不得分的个数,如果我们仔细观察上面红色的数字,可以发现,由于是左移,坐标在不断减小,所以原先失分的地方,在K+1的时候还是失分,除非你从开头位置跑到末尾去了,那会得分,所以我们要累加change数组,并且K每增加1的时候,要加上额外的1,最后change数组中最大数字的位置就是要求的K值了,参见代码如下:
public int bestRotation(int[] A) {
int N = A.length;
int change[] = new int[N];
for (int i = 0; i < N; ++i) change[(i - A[i] + 1 + N) % N] -= 1;
int max_i = 0;
for (int i = 1; i < N; ++i) {
change[i] += change[i - 1] + 1;
max_i = change[i] > change[max_i] ? i : max_i;
}
return max_i;
}
LeetCode – Smallest Rotation with Highest Score的更多相关文章
- [LeetCode] 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 ...
- 75th LeetCode Weekly Contest 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】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], ...
- [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] Smallest Rectangle Enclosing Black Pixels 包含黑像素的最小矩阵
An image is represented by a binary matrix with 0 as a white pixel and 1 as a black pixel. The black ...
- LeetCode Smallest Rectangle Enclosing Black Pixels
原题链接在这里:https://leetcode.com/problems/smallest-rectangle-enclosing-black-pixels/ 题目: An image is rep ...
- [LeetCode] Smallest Range 最小的范围
You have k lists of sorted integers in ascending order. Find the smallest range that includes at lea ...
- [LeetCode] Smallest Good Base 最小的好基数
For an integer n, we call k>=2 a good base of n, if all digits of n base k are 1. Now given a str ...
- LeetCode 856. 括号的分数(Score of Parentheses)
856. 括号的分数 856. Score of Parentheses 题目描述 给定一个平衡括号字符串 S,按下述规则计算该字符串的分数: () 得 1 分. AB 得 A + B 分,其中 A ...
随机推荐
- CF712E [Memort and Casinos]
题意 每次询问一段区间[l,r],求从最左边走到最右边(r+1)的概率(若走到l-1,则GG了),每个点上写有向右走的概率.支持单点修改. 思考 若只查询一次,那只要知道每个点在不走到l-1的情况下, ...
- 深入理解Connector
上一篇主要是从各个容器的生命周期的角度讲了一下整个tomcat的运行流程,说明了各个容器之间的调用关系.但并没有太过详细的说明每一个组件并区分他们. 下面从功能的角度上详细的分析一下connector ...
- Java获取系统时间的四种方法
1.Date day=new Date(); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); ...
- Cracking The Coding Interview4.8
//You are given a binary tree in which each node contains a value. Design an algorithm to print all ...
- 3.9 C++多继承
参考:http://www.weixueyuan.net/view/6366.html 总结: C++中一个派生类中允许有两个及以上的基类,我们称这种情况为多继承 使用多继承可以描述事物之间的组合关系 ...
- String类的常用方法总结
一.String类String类在java.lang包中,java使用String类创建一个字符串变量,字符串变量属于对象.java把String类声明的final类,不能有类.String类对象创建 ...
- APC注入(Ring3)
首先简单介绍一下APC队列和Alertable. 看看MSDN上的一段介绍(https://msdn.microsoft.com/en-us/library/ms810047.aspx): The s ...
- codeforce150A(简单的求质数问题)
A. Win or Freeze time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...
- Mybaties学习
基于现在Mybatis 我没有学习太多,就基于简单的增删改查进行基础学习. 学习资源来自 http://www.cnblogs.com/xdp-gacl/p/4261895.html 1 引入 ...
- 20165214 预备作业3 Linux安装及学习
一.VirtualBox和Ubuntu的安装 点进VirtualBox的官网后,不知道为什么,我只看到了5.2.6版本...又看到同学反映说5.2.7版本会出现问题,我想可能是工作人员正在补5.2.7 ...