Back to Arrays
Q81Question 81 of 109

Rotation Count (How Many Times a Sorted Array Was Rotated)

Key Concepts
  • Array traversal, search, and manipulation
  • Common patterns: two-pointer, prefix sum, sliding window
  • Find max/min, reverse, rotate, remove duplicates
  • Time complexity: O(n) traversal, O(1) access by index
  • We binary-search with `start = 0` and `end = n - 1`.
  • At each step `mid = start + (end - start) / 2`.
  • We compare `arr[mid]` with `arr[end]`: if `arr[mid] > arr[end]` the minimum must be to the right of the middle, so `start = mid + 1`; otherwise the minimum is at the middle or to its left, so `end = mid`.

Definition

The rotation count equals the index of the minimum, so binary-search for the smallest element and return its index.

Rotation Count is a Modified Binary Search problem equivalent to finding the index of the smallest element in a rotated sorted array, because the number of rotations equals that index. We binary-search comparing the middle element with its neighbours to locate the single point where an element is smaller than its predecessor, which is the minimum, and its index is the rotation count.

At the National Bank of India, a sorted list of cheque serial numbers was rotated some unknown number of times when batches were re-queued, and we need to know how many rotations happened. That count is exactly where the smallest serial sits, so we binary-search for the minimum and report its index.

Understanding the Concepts

What is the problem?

Rotation Count (How Many Times a Sorted Array Was Rotated). Given an ascending sorted array that has been rotated an unknown number of times, count how many times it was rotated, which equals the index of its smallest element. Explain how binary search locates the minimum.

How does the approach work?

We binary-search with start = 0 and end = n - 1. At each step mid = start + (end - start) / 2. We compare arr[mid] with arr[end]: if arr[mid] > arr[end] the minimum must be to the right of the middle, so start = mid + 1; otherwise the minimum is at the middle or to its left, so end = mid. For example, if (arr[mid] > arr[end]) start = mid + 1; else end = mid;. The loop runs while start < end, and when it ends start points at the minimum, so start is the rotation count.

Comparing with the right end rather than the left end is the robust choice because it correctly handles the case where the array is not rotated at all, in which case the minimum is at index zero and the comparison keeps moving end left until start equals zero. If the array is fully sorted and un-rotated, the answer is zero rotations.

A senior nuance is that with duplicate values the arr[mid] > arr[end] test can be inconclusive when they are equal, in which case we decrement end by one, which can degrade to O(n); with distinct values the search is strictly logarithmic. Returning start directly gives both the minimum's index and the rotation count in one value. Complexity is O(log n) time with distinct values and O(1) space.

What is the banking use case?

Problem 1 — The National Bank of India re-queues cheque batches, which rotates a sorted array of serial numbers an unknown number of times, and reconciliation needs to know exactly how many rotations occurred. This is exactly how Rotation Count works: the count equals the index of the smallest serial.
Problem 2 — Scanning the whole array to find the minimum is wasteful for large batches. This is why we binary-search by comparing the middle serial with the last serial to converge on the minimum, staying logarithmic.

The code defines a RotationCountService exposing countRotations(serials) returning the rotation count. A Demo counts rotations of a rotated serial array and logs the result.

How do you implement this in Java?

JAVA
// ─── File: src/main/java/com/bank/rotate/service/RotationCountService.java ───
package com.bank.rotate.service;

import java.util.logging.Logger;

// Counts rotations = index of the minimum in a rotated sorted array.
public class RotationCountService {
    private static final Logger log = Logger.getLogger(RotationCountService.class.getName());

    public int countRotations(int[] serials) {
        int start = 0, end = serials.length - 1;
        while (start < end) {
            int mid = start + (end - start) / 2;
            if (serials[mid] > serials[end]) start = mid + 1; // min is to the right
            else end = mid;                                    // min is here or left
        }
        final int count = start; // index of minimum == rotation count
        log.info(() -> "Array rotated " + count + " times (min at index " + count + ")");
        return count;
    }
}
JAVA
// ─── File: src/main/java/com/bank/rotate/RotationCountApplication.java ───
package com.bank.rotate;

import com.bank.rotate.service.RotationCountService;
import java.util.logging.Logger;

public class RotationCountApplication {
    private static final Logger log = Logger.getLogger(RotationCountApplication.class.getName());

    public static void main(String[] args) {
        RotationCountService service = new RotationCountService();
        int[] serials = {40, 50, 60, 10, 20, 30}; // rotated 3 times
        log.info("Cheque serials rotation count: " + service.countRotations(serials));
    }
}

What is the project structure?

DIAGRAM
rotation-count-service/
├── pom.xml
├── src/
│   ├── main/
│   │   ├── java/com/bank/rotate/
│   │   │   ├── RotationCountApplication.java     (main class)
│   │   │   └── service/
│   │   │       └── RotationCountService.java
│   │   └── resources/
│   │       └── application.yml
│   └── test/
│       └── java/com/bank/rotate/
│           └── RotationCountServiceTest.java

How do you build and run?

BASH
# Build
mvn clean package -DskipTests

# Run
java -jar target/rotation-count-service-1.0.0.jar

# See convergence at FINE level
java -Djava.util.logging.ConsoleHandler.level=FINE \
  -jar target/rotation-count-service-1.0.0.jar

What is the step-by-step walkthrough?

Input: serials 40, 50, 60, 10, 20, 30.

Step 1: start is 0, end is 5, mid is 2, serial at 2 is 60 and at end is 30; since 60 is greater than 30, the minimum is to the right, so start becomes 3.
Step 2: start is 3, end is 5, mid is 4, serial at 4 is 20 and at end is 30; since 20 is not greater than 30, the minimum is here or left, so end becomes 4.
Step 3: start is 3, end is 4, mid is 3, serial at 3 is 10 and at end is 20; since 10 is not greater than 20, end becomes 3.
Step 4: start equals end at index 3, the loop ends, and index 3 is both the minimum's position and the rotation count, so the array was rotated three times.
CODE
Oct 27, 2026 10:39:07 PM com.bank.rotate.service.RotationCountService countRotations
INFO: Array rotated 3 times (min at index 3)
INFO: Cheque serials rotation count: 3

What is the high-level design?

DIAGRAM
  ═══ HLD — Cheque Serial Rotation Count (Banking) ═══

  ┌────────────┐ HTTPS ┌──────────────┐ REST ┌─────────────────────┐
  │ Recon Tool │──────→│ API Gateway  │─────→│ Rotation Count ×2   │
  └────────────┘       │ (JWT, rate)  │      │ (Spring Boot)       │
                       └──────────────┘      └─────────┬───────────┘
                                                      │ load serial batch
                                                      ▼
                                           ┌─────────────────────┐
                                           │ PostgreSQL serials   │
                                           └─────────────────────┘

What is the low-level design?

DIAGRAM
  ═══ LLD — Rotation Count ═══

  ┌─ Design Patterns Used ──────────────────────────────────┐
  │  Binary search for minimum via compare-with-right-end    │
  │     WHY: min index equals the rotation count             │
  └──────────────────────────────────────────────────────────┘

  ┌─ SOLID Principles Applied ──────────────────────────────┐
  │  S: service only counts rotations                        │
  │  O: any rotation amount works unchanged                  │
  │  D: depends only on primitive int array                  │
  └──────────────────────────────────────────────────────────┘

  ── Class Diagram ──────────────────────────────────────────
  ┌──────────────────────────────────────┐
  │ RotationCountService                  │
  │ ───────────────────────────────────── │
  │ + countRotations(serials): int        │
  └──────────────────────────────────────┘

  ── State: [start,end] converge on min index ──────────────
  compare mid with end to pick the half holding the min

  Contract for countRotations(serials):
    Pre:  distinct, ascending then rotated
    Post: index of minimum = number of rotations (0 if none)

What is the time and space complexity?

Analyze the solution based on the algorithm used. Consider both the time to process input and the space required for any data structures.

What are common mistakes?

Common mistakes include off-by-one errors, not handling edge cases like empty input, and not considering the constraints of the problem.

What are the edge cases?

Edge cases include empty input, single element input, all identical elements, and boundary values.

What should a senior engineer know?

A senior engineer should understand the time-space tradeoffs, be able to explain the algorithm clearly, and know when this technique applies versus alternatives.

Visual Overview

DIAGRAM
  serials:[40,50,60,10,20,30]
    │
    ▼
  compare serials[mid] vs serials[end]
    ├─ mid > end → min on right → start = mid+1
    └─ mid <= end → min here/left → end = mid
    ▼
  start==end=3 → rotation count = 3

Key Takeaway

Rotation Count asks how many times a sorted array was rotated, and the elegant reframing is that the answer equals the index of the smallest element, because rotating a sorted array moves the minimum to the position equal to the number of rotations. So I binary-search for the minimum. At each step I compare the middle element with the element at the right end: if the middle is larger than the right end, the break point and therefore the minimum must lie to the right, so I move the start pointer past the middle; otherwise the minimum is at the middle or to its left, so I move the end pointer to the middle.

I deliberately compare against the right end rather than the left, because that handles the un-rotated case cleanly: when the array was never rotated the comparison keeps pulling the end leftward and the pointers converge on index zero, correctly reporting zero rotations. When the loop finishes, the start pointer sits on the minimum, and that index is my answer.

At the National Bank of India I used this during reconciliation of cheque batches that were re-queued, which rotated a sorted array of serial numbers an unknown number of times. By binary-searching for the minimum serial I recovered the exact rotation count in logarithmic time even for large batches. I would also note the duplicate-values caveat, where equal middle and end values force me to step the end inward and the worst case becomes linear, which shows an interviewer I understand both the clean case and its boundary.

Remember one sentence: understand the core algorithm and apply it to banking domain problems.

---

Share
Use ← → arrow keys to navigate