Back to Arrays
Q11Question 11 of 109

Check if an Array Is Sorted

Key Concepts
  • Compare each element with its next neighbour; if any earlier element is greater than the next, the array is not sorted.
  • Fail fast by returning false at the first violation, saving work when the error is near the front.
  • Empty and single-element arrays are trivially sorted because there are no adjacent pairs to violate.
  • Decide deliberately between strict ascending (no duplicates) and non-strict ascending (duplicates allowed).
  • Accept a Comparator parameter to make the method reusable for ascending, descending, or custom orders.
  • Time is O(n) in the worst case (fully sorted) and O(1) space.

Definition

Walk adjacent pairs; if any earlier element is greater than the next, it is not sorted; otherwise it is.
  • Adjacent comparison – check each element against its immediate neighbour.
  • Fail fast – return false at the first violation to avoid unnecessary work.
  • Trivially sorted – empty and single-element arrays pass because there are no pairs to violate.
  • Ordering policy – <= allows duplicates (non-strict); < requires strictly increasing.
  • O(n) time, O(1) space – one pass through the array with no extra data structures.

National Bank of India produces a daily settlement file where transactions must already be ordered by timestamp. A clerk walks down the rows comparing each row's time with the next. The instant a later row has an earlier time, the file is flagged as out of order. If every pair is in order all the way down, the file passes.

Understanding the Concepts

What is the problem?

Given an array, determine whether it is sorted in ascending order. In a banking context, the settlement ingestion pipeline at National Bank of India requires that incoming files are pre-sorted by timestamp. A failed check means the file must be rejected.

How does the algorithm work?

Loop from the first element to the second-to-last. At each position i, compare arr[i] with arr[i+1]. If arr[i] is greater than arr[i+1], return false immediately. If the loop completes, return true.

JAVA
package com.bank.service;

import java.math.BigDecimal;

public class SortOrderValidator {

    public static boolean isSortedAscending(BigDecimal[] arr) {
        if (arr == null || arr.length <= 1) {
            return true;
        }
        for (int i = 0; i < arr.length - 1; i++) {
            if (arr[i].compareTo(arr[i + 1]) > 0) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        BigDecimal[] sorted = {
            new BigDecimal("1000"),
            new BigDecimal("2500"),
            new BigDecimal("2500"),
            new BigDecimal("7800")
        };
        BigDecimal[] unsorted = {
            new BigDecimal("1000"),
            new BigDecimal("7800"),
            new BigDecimal("2500")
        };
        System.out.println("Sorted array:   " + isSortedAscending(sorted));
        System.out.println("Unsorted array: " + isSortedAscending(unsorted));
    }
}
TEXT
Sorted array:   true
Unsorted array: false

What about empty and single-element arrays?

Both are trivially sorted because there are no adjacent pairs to violate the ordering. The loop simply does not execute, and the method returns true.

What is the difference between strict and non-strict ordering?

Non-strict ascending (<=) allows equal neighbours, treating [1000, 2500, 2500, 7800] as sorted. Strict ascending (<) rejects it because 2500 appears twice. Choose based on the requirement: timestamps that can tie need non-strict; unique identifiers need strict.

JAVA
// Non-strict: allows duplicates
if (arr[i].compareTo(arr[i + 1]) > 0) return false;

// Strict: rejects duplicates
if (arr[i].compareTo(arr[i + 1]) >= 0) return false;

How do you make it reusable with a Comparator?

Accepting a Comparator makes the same method work for ascending, descending, or custom orders.

JAVA
import java.util.Comparator;

public static <T> boolean isSorted(T[] arr, Comparator<T> cmp) {
    for (int i = 0; i < arr.length - 1; i++) {
        if (cmp.compare(arr[i], arr[i + 1]) > 0) {
            return false;
        }
    }
    return true;
}

// Usage: check descending order
boolean desc = isSorted(arr, Comparator.reverseOrder());

Why does fail-fast matter?

On a large settlement file with millions of rows, returning false at the first violation avoids scanning the remaining rows. When the file is corrupted near the top, this saves significant time in a batch pipeline.

What is the time and space complexity?

  • Time: O(n) in the worst case when the array is fully sorted (every pair must be checked).
  • Best case: O(1) when the first pair is out of order.
  • Space: O(1) because no extra data structures are needed.

What are common mistakes?

The most common mistake is looping to arr.length instead of arr.length - 1, which causes an ArrayIndexOutOfBoundsException when accessing arr[i + 1]. Another mistake is forgetting to handle the null or empty array.

JAVA
// Wrong: index out of bounds
for (int i = 0; i < arr.length; i++) {
    if (arr[i].compareTo(arr[i + 1]) > 0) // crashes at last element
}

// Correct: stop one before the end
for (int i = 0; i < arr.length - 1; i++) { /* safe */ }

What should a senior engineer know?

A senior engineer uses the Comparator-based approach for reusability and documents the duplicate policy. The senior also mentions that checking whether an array is sorted is often a precondition guard: if the downstream algorithm requires sorted input (like binary search), the check prevents silent wrong results. In the settlement pipeline, Pankaj uses this check as a gate before the reconciliation engine, which assumes sorted input.

Visual Overview

DIAGRAM
  arr[]:  1000  2500  2500  7800
            │     │     │     │
            ▼     ▼     ▼     ▼
  ┌──────────────────────────────────────────┐
  │  i=0: 1000 > 2500?  NO  (ok)            │
  │  i=1: 2500 > 2500?  NO  (equal, ok)     │
  │  i=2: 2500 > 7800?  NO  (ok)            │
  └──────────────────────────────────────────┘
  No violation found → return true

  arr[]:  1000  7800  2500
  ┌──────────────────────────────────────────┐
  │  i=0: 1000 > 7800?  NO  (ok)            │
  │  i=1: 7800 > 2500?  YES → return false   │
  └──────────────────────────────────────────┘
  Fail fast at first violation

Key Takeaway

Checking whether an array is sorted is a single pass over adjacent pairs. For ascending order I compare each element with the next and return false the moment I find a violation. If the scan completes, the array is sorted. It is linear time, constant space, and fails fast.

Empty and single-element arrays are trivially sorted. I decide strict versus non-strict ordering deliberately: non-strict allows equal neighbours, which is right when duplicates are legitimate, while strict enforces uniqueness.

To make it reusable I accept a Comparator so the same loop checks ascending, descending, or any custom order. Fail-fast matters in practice: on a large settlement file that is corrupt near the top, returning at the first violation avoids scanning millions of remaining rows.

In my banking project at National Bank of India I used this as a gate in the settlement ingestion pipeline, because the downstream reconciliation engine assumes sorted input.

Remember one sentence: compare adjacent pairs and return false at the first violation, return true only if every pair passes.

---

Share
Use ← → arrow keys to navigate