Open In App

Minimum rotations that have maximum elements with value at most its index

Last Updated : 12 Dec, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] of size N, the array can be rotated any number of times such that after rotation, each element of the array arr[] that is less than or equal to its index will get 1 point. The task is to find the rotation index K that corresponds to the highest score. If there are multiple answers, return the smallest among all.

Examples:

Input: arr[] = {2, 3, 1, 4, 0}
Output: 3
Explanation: 
k = 0, arr = [2,3,1,4,0], score 2
k = 1, arr = [3,1,4,0,2], score 3 [num index: 3>1, 1==1(1 point), 4>2, 0<3 (1 point), 2<4 (1 point)]
k = 2, arr = [1,4,0,2,3], score 3
k = 3, arr = [4,0,2,3,1], score 4
k = 4, arr = [0,2,3,1,4], score 3
therefore K = 3, gives the highest score.

Input: arr[] = {0, 0, 2, 4, 6}
Output: 4

 

Naive Approach: Calculate the scores for each rotation. Then find the highest score among the total scores calculated and return the lowest index if there are multiple scores.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to rotate the array
void rotate(vector<int>& arr, int N)
{
    int temp = arr[0], i;
    for (i = 0; i < N - 1; i++)
        arr[i] = arr[i + 1];
    arr[N - 1] = temp;
    return;
}
 
// Function to calculate the
// total score of a rotation
int calculate(vector<int>& arr)
{
    int score = 0;
    for (int i = 0; i < arr.size(); i++) {
        if (arr[i] <= i) {
            score++;
        }
    }
    return score;
}
 
// Function to find the rotation index k
// that corresponds to the highest score
int bestIndex(vector<int>& nums)
{
    int N = nums.size();
    int high_score = -1;
    int min_idx = 0;
 
    for (int i = 0; i < N; i++) {
        if (i != 0)
            // Rotates the array to left
            // by one position.
            rotate(nums, N);
 
        // Stores score of current rotation
        int cur_score = calculate(nums);
 
        if (cur_score > high_score) {
            min_idx = i;
            high_score = cur_score;
        }
    }
    return min_idx;
}
 
// Driver code
int main()
{
    vector<int> arr = { 2, 3, 1, 4, 0 };
    cout << bestIndex(arr);
    return 0;
}


Java




// Java program for the above approach
import java.io.*;
public class GFG {
 
  // Function to rotate the array
  static void rotate(int[] arr, int N) {
    int temp = arr[0], i;
    for (i = 0; i < N - 1; i++)
      arr[i] = arr[i + 1];
    arr[N - 1] = temp;
    return;
  }
 
  // Function to calculate the
  // total score of a rotation
  static int calculate(int[] arr) {
    int score = 0;
    for (int i = 0; i < arr.length; i++) {
      if (arr[i] <= i) {
        score++;
      }
    }
    return score;
  }
 
  // Function to find the rotation index k
  // that corresponds to the highest score
  static int bestIndex(int[] nums) {
    int N = nums.length;
    int high_score = -1;
    int min_idx = 0;
 
    for (int i = 0; i < N; i++) {
      if (i != 0)
 
        // Rotates the array to left
        // by one position.
        rotate(nums, N);
 
      // Stores score of current rotation
      int cur_score = calculate(nums);
 
      if (cur_score > high_score) {
        min_idx = i;
        high_score = cur_score;
      }
    }
    return min_idx;
  }
 
  // Driver code
  public static void main(String args[]) {
    int[] arr = { 2, 3, 1, 4, 0 };
    System.out.println(bestIndex(arr));
  }
}
 
// This code is contributed by Saurabh Jaiswal


Python3




# Python program for the above approach
 
# Function to rotate the array
def rotate(arr, N):
 
    temp = arr[0]
    for i in range(0, N-1):
        arr[i] = arr[i + 1]
    arr[N - 1] = temp
    return
 
# Function to calculate the
# total score of a rotation
def calculate(arr):
 
    score = 0
    for i in range(0, len(arr)):
        if (arr[i] <= i):
            score = score + 1
 
    return score
 
# Function to find the rotation index k
# that corresponds to the highest score
def bestIndex(nums):
 
    N = len(nums)
    high_score = -1
    min_idx = 0
 
    for i in range(0, N):
        if (i != 0):
           
            # Rotates the array to left
            # by one position.
            rotate(nums, N)
 
        # Stores score of current rotation
        cur_score = calculate(nums)
 
        if (cur_score > high_score):
            min_idx = i
            high_score = cur_score
 
    return min_idx
 
# Driver code
arr = [2, 3, 1, 4, 0]
print(bestIndex(arr))
 
# This code is contributed by Taranpreet


C#




// C# program for the above approach
using System;
class GFG
{
 
  // Function to rotate the array
  static void rotate(int[] arr, int N)
  {
    int temp = arr[0], i;
    for (i = 0; i < N - 1; i++)
      arr[i] = arr[i + 1];
    arr[N - 1] = temp;
    return;
  }
 
  // Function to calculate the
  // total score of a rotation
  static int calculate(int[] arr)
  {
    int score = 0;
    for (int i = 0; i < arr.Length; i++) {
      if (arr[i] <= i) {
        score++;
      }
    }
    return score;
  }
 
  // Function to find the rotation index k
  // that corresponds to the highest score
  static int bestIndex(int[] nums)
  {
    int N = nums.Length;
    int high_score = -1;
    int min_idx = 0;
 
    for (int i = 0; i < N; i++) {
      if (i != 0)
        // Rotates the array to left
        // by one position.
        rotate(nums, N);
 
      // Stores score of current rotation
      int cur_score = calculate(nums);
 
      if (cur_score > high_score) {
        min_idx = i;
        high_score = cur_score;
      }
    }
    return min_idx;
  }
 
  // Driver code
  public static void Main()
  {
    int[] arr = { 2, 3, 1, 4, 0 };
    Console.Write(bestIndex(arr));
  }
}
 
// This code is contributed by Samim Hossain Mondal.


Javascript




<script>
       // JavaScript code for the above approach
 
       // Function to rotate the array
       function rotate(arr, N) {
           let temp = arr[0], i;
           for (i = 0; i < N - 1; i++)
               arr[i] = arr[i + 1];
           arr[N - 1] = temp;
           return arr;
       }
 
       // Function to calculate the
       // total score of a rotation
       function calculate(arr) {
           let score = 0;
           for (let i = 0; i < arr.length; i++) {
               if (arr[i] <= i) {
                   score++;
               }
           }
           return score;
       }
 
       // Function to find the rotation index k
       // that corresponds to the highest score
       function bestIndex(nums) {
           let N = nums.length;
           let high_score = -1;
           let min_idx = 0;
 
           for (let i = 0; i < N; i++) {
               if (i != 0)
                   // Rotates the array to left
                   // by one position.
                   nums = [...rotate(nums, N)];
 
               // Stores score of current rotation
               let cur_score = calculate(nums);
 
               if (cur_score > high_score) {
                   min_idx = i;
                   high_score = cur_score;
               }
           }
           return min_idx;
       }
 
       // Driver code
 
       let arr = [2, 3, 1, 4, 0];
       document.write(bestIndex(arr));
 
      // This code is contributed by Potta Lokesh
   </script>


Output

3

Time Complexity: O(N2)
Auxiliary Space: O(1)

Efficient approach: In this approach, 

  • first calculate the score of input and then make a priority queue (q) in ascending order.
  • Then put all non-negative differences of i – arr[i], say diff into the priority queue.
  • After this, traverse from 1 to (N -1). Every time the shift is done, since it is a left shift, arr[i-1] becomes the tail of arr, and arr[i-1] becomes arr[N-1].
  • Also, all the diff[i] becomes diff[i] -1 by the decrease of map index (caused by left-shift).
  • Then score will be changed by 2 cases after each rotation:

Case 1: 
arr[i-1] <= N -1, then score++;

Case 2: 
i > q.front(), then score–

because it means the shift makes some diff values become negative (originally which are non-negative). 

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the rotation index k
// that corresponds to the highest score
int bestIndex(vector<int>& nums)
{
    int N = nums.size();
    int gain = 0;
    int idx;
    priority_queue<int, vector<int>, greater<int> > q;
 
    for (int i = 0; i < N; i++) {
        int diff = i - nums[i];
        if (diff >= 0) {
            gain++;
            q.push(diff);
        }
    }
 
    int current = gain;
    idx = 0;
 
    for (int i = 1; i <= N - 1; i++) {
        while (!q.empty() && (i > q.top())) {
            q.pop();
            current--;
        }
        if (nums[i - 1] <= (N - 1)) {
            current++;
            q.push(i + (N - 1) - nums[i - 1]);
        }
        if (current > gain) {
            idx = i;
            gain = current;
        }
    }
    return idx;
}
 
// Driver Code
int main()
{
    vector<int> arr = { 2, 3, 1, 4, 0 };
    cout << bestIndex(arr);
    return 0;
}


Java




// Java program for the above approach
import java.io.*;
 
public class GFG
{
 
  // Function to find the rotation index k
  // that corresponds to the highest score
  static int bestIndex(int[] nums)
  {
    int N = nums.length;
    int gain = 0;
    int idx = 0;
    PriorityQueue<Integer> q
      = new PriorityQueue<Integer>();
 
    for (int i = 0; i < N; i++) {
      int diff = i - nums[i];
      if (diff >= 0) {
        gain++;
        q.add(diff);
      }
    }
 
    int current = gain;
    idx = 0;
 
    for (int i = 1; i <= N - 1; i++) {
      while (q.isEmpty() == false && (i > q.peek())) {
        q.remove();
        current--;
      }
      if (nums[i - 1] <= (N - 1)) {
        current++;
        q.add(i + (N - 1) - nums[i - 1]);
      }
      if (current > gain) {
        idx = i;
        gain = current;
      }
    }
    return idx;
  }
 
  // Driver Code
  public static void main(String args[])
  {
    int[] arr = { 2, 3, 1, 4, 0 };
    System.out.print(bestIndex(arr));
  }
}
 
// This code is contributed by Samim Hossain Mondal.


Python3




# Python code for the above approach
import array as arr
 
# Function to find the rotation index k
# that corresponds to the highest score
def bestIndex(nums):
    N = len(nums)
    gain = 0
    idx = 0
    q = arr.array('i', [])
 
    for i in range(0, N):
        diff = i - nums[i]
        if diff >= 0:
            gain = gain+1
            q.append(diff)
 
    current = gain
    idx = 0
 
    for i in range(1, N):
        while len(q) == 0 & (i > (q[len(q) - 1])):
            q.shift()
            current = current-1
 
        if nums[i - 1] <= (N - 1):
            current = current+1
            q.append(i + (N - 1) - nums[i - 1])
 
        if (current > gain):
            idx = i
            gain = current
 
    return idx - 1
 
# Driver Code
a = arr.array('b', [2, 3, 1, 4, 0])
print(bestIndex(a))
 
# This code is contributed by adityamaharshi21.


C#




// C# program of the above approach
using System;
using System.Collections.Generic;
 
class GFG
{
 
  // Function to find the rotation index k
  // that corresponds to the highest score
  static int bestIndex(int[] nums)
  {
    int N = nums.Length;
    int gain = 0;
    int idx = 0;
    List<int> q = new List<int>();
 
    for (int i = 0; i < N; i++) {
      int diff = i - nums[i];
      if (diff >= 0) {
        gain++;
        q.Add(diff);
        q.Sort();
        q.Reverse();
      }
    }
 
    int current = gain;
    idx = 0;
 
    for (int i = 1; i <= N - 1; i++) {
      while (i > q[0]) {
        q.RemoveAt(0);
        current--;
      }
      if (nums[i - 1] <= (N - 1)) {
        current++;
        q.Add(i + (N - 1) - nums[i - 1]);
        q.Sort();
        q.Reverse();
      }
      if (current > gain) {
        idx = i;
        gain = current;
      }
    }
    return idx-1;
  }
 
  // Driver Code
  public static void Main()
  {
    int[] arr = { 2, 3, 1, 4, 0 };
    Console.Write(bestIndex(arr));
  }
}
 
// This code is contributed by sanjoy_62.


Javascript




<script>
    // JavaScript code for the above approach
 
  // Function to find the rotation index k
  // that corresponds to the highest score
  function bestIndex(nums)
  {
    let N = nums.length;
    let gain = 0;
    let idx = 0;
    let q = [];
 
    for (let i = 0; i < N; i++) {
      let diff = i - nums[i];
      if (diff >= 0) {
        gain++;
        q.push(diff);
      }
    }
 
    let current = gain;
    idx = 0;
 
    for (let i = 1; i <= N - 1; i++) {
      while (q.length == false && (i > (q[q.length - 1]))) {
        q.shift();
        current--;
      }
      if (nums[i - 1] <= (N - 1)) {
        current++;
        q.push(i + (N - 1) - nums[i - 1]);
      }
      if (current > gain) {
        idx = i;
        gain = current;
      }
    }
    return idx-1;
  }
 
    // Driver Code
    let arr = [ 2, 3, 1, 4, 0 ];
    document.write(bestIndex(arr));
 
// This code is contributed by code_hunt.
</script>


Output

3

Time Complexity: O(N * logN)
Auxiliary Space: O(N)

 



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads