798. Smallest Rotation with Highest Score   这道题其实没什么特别的算法,主要还是找规律与优化,暴力解法时间复杂度为O(n2),就是直接模拟题目解释,肯定是效率不够的,代码如下

Problem:

 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].

Solution:

  这道题其实没什么特别的算法,主要还是找规律与优化,暴力解法时间复杂度为O(n2),就是直接模拟题目解释,肯定是效率不够的,代码如下

 1 class Solution {
 2 public:
 3     int bestRotation(vector<int>& A) {
 4         int result = 0;
 5         int maxScore = 0;
 6         for(int k = 0;k != A.size();++k){
 7             int count = 0;
 8             for(int i = 0;i != A.size();++i){
 9                 if(A[i] <= (i+A.size()-k)%A.size())
10                     count++;
11             }
12             if(count > maxScore){
13                 maxScore = count;
14                 result = k;
15             }
16         }
17         return result;
18     }
19 };

  现在来思考下线性时间复杂度的解法。通过观察规律可知,对于每个元素A[i],都有一个集合k使得对于k中的每个元素ki,当A旋转ki后A[i]都满足条件,以Example1为例,对于[2, 3, 1, 4, 0],我们得到[1,4),[2,4),[0,2)||[3,5),[4,5),[0,5),解释一下这是什么意思,比如说A[0]=2,当k取[1,4)中的任意值,2这个值和其对应转移后的位置满足条件,score加一。所以我们现在把问题抽象为当k取什么值的时候,满足条件的区间个数最多。这个问题是不是很眼熟?它和Leetcode 732 My Calendar III的解法完全一样,用一个哈希表轻松解决。考虑到题目特殊性,可以用数组代替哈希表,效率会提高不少。

Code:

 1 class Solution {
 2 public:
 3     int bestRotation(vector<int>& A) {
 4         vector<int> m(A.size()+1,0);  //Or unordered_map<int,int> m;
 5         int result = 0;
 6         int maxScore = 0;
 7         int score = 0;
 8         for(int i = 0;i != A.size();++i){
 9             if(i >= A[i]){
10                 m[0]++;
11                 m[i-A[i]+1]--;
12                 m[i+1]++;
13                 m[A.size()]--;
14             }
15             else{
16                 m[i+1]++;
17                 m[i+A.size()-A[i]+1]--;
18             }
19         }
20         for(int i = 0;i != A.size();++i){
21             score += m[i];
22             if(score > maxScore){
23                 maxScore = score;
24                 result = i;
25             }
26         }
27         return result;
28     }
29 };

猜你喜欢

转载自www.cnblogs.com/haoweizh/p/10358629.html