☕ Java Backend Course

Arrays in Java
Complete Deep Dive

Theory se lekar Memory Model, Algorithms, aur Practice Programs tak — ek hi jagah, sab kuch, depth mein.

11
Chapters
60+
Code Examples
40+
Practice Programs
5
Algorithms
Full
Theory Covered
01

Array Kya Hai?

Complete Theory · Memory Model · Why Arrays · Stack vs Heap · Call by Reference

📖 Core Definition

Array — Ek Naam, Multiple Values

Array ek aisi data structure hai jisme same data type ke multiple values ko ek hi naam se manage kiya jaata hai. Ye values contiguous (lagatar) memory locations mein store hoti hain.

Bina array ke soch lo: agar 100 students ke marks store karne hain, to 100 alag variables likhne padenge — marks1, marks2... marks100. Ye impractical hai. Array se ek line mein kaam hoga: int[] marks = new int[100];

Java mein array ek object hai — ye heap memory pe allocate hota hai, aur uska reference stack pe hota hai. Isliye arrays ka .length property hoti hai (method nahi), aur inhe method mein pass karne pe reference jaata hai, copy nahi.

Formal Definition: Array is a linear data structure that stores a fixed-size, ordered collection of elements of the same data type in contiguous memory locations, accessible via zero-based indexing in O(1) time.
Memory Model — int[] arr = {10, 20, 30, 40, 50}
[Stack] arr → reference address → [Heap Memory — contiguous blocks]
arr (Stack ref) →
10
arr[0]
0x1000
20
arr[1]
0x1004
30
arr[2]
0x1008
40
arr[3]
0x100C
50
arr[4]
0x1010
int = 4 bytes · Addresses har baar 4 badh rahe hain · Index 0 se start · arr.length = 5 · Last index = arr.length - 1 = 4
🧠 Stack vs Heap — Deep Dive

Java Memory Architecture

Stack Memory: Primitive local variables aur object references yahan store hote hain. LIFO order mein kaam karta hai. Method call hone par stack frame create hota hai, method end hone par automatically destroy ho jaata hai. Very fast, limited size.

Heap Memory: Actual objects (including arrays) yahan store hote hain. JVM ka Garbage Collector isko manage karta hai. Larger size, thoda slower. new keyword use karne par heap pe memory allocate hoti hai.

Jab aap likhte ho int[] arr = new int[5];arr ek reference variable hai jo stack pe hai, aur actual 5 integers ki array heap pe hai. arr mein us heap location ka address store hota hai.

⚡ O(1) Random Access — Kaise?

Contiguous Memory Ka Fayda

Array ki sabse badi strength hai ki kisi bhi element ka address calculate kiya ja sakta hai directly:

Address Formula: address(arr[i]) = base_address + (i × element_size)

Example: arr[3] ka address = 0x1000 + (3 × 4) = 0x100C — ek hi calculation, O(1)! Ye linked list se alag hai jahan O(n) traversal lagti hai kisi bhi element tak pahunchne ke liye.

🔒

Fixed Size

Ek baar declare karne ke baad size change nahi hota. Dynamic size ke liye ArrayList use karo.

📦

Homogeneous

Ek array mein sirf ek hi data type — int[], String[], double[]. Mixed types allowed nahi.

O(1) Access

Contiguous memory ki wajah se koi bhi element index se directly ek step mein milta hai.

0️⃣

Zero-Indexed

Pehla element index 0 pe, last element index n-1 pe. Yahi convention Java follow karta hai.

🎯

Object in Java

Java mein array ek object hai. Iska .length property hota hai, .length() method nahi.

🔗

Reference Type

Method mein pass karne pe reference jaata hai — changes original array mein reflect hote hain.

🌐 Real-World Uses in Backend

Arrays in Production Code

  • Database queries: JDBC ResultSet se aya data rows mein hota hai — often arrays mein convert karte hain
  • HTTP Processing: Request parameters, query strings, headers — sab arrays of strings
  • Batch Processing: 1000 records ek saath process karne ke liye arrays efficient hain
  • Caching: Fixed-size lookup tables banane ke liye — O(1) cache hit guaranteed
  • Image Processing: Pixel data 2D int arrays mein store hoti hai (RGB values)
  • Sorting APIs: Java ka Arrays.sort() internally dual-pivot quicksort use karta hai
  • DSA Algorithms: Graphs (adjacency matrix), DP tables, sliding window — sab arrays use karte hain
EX 1.1

Array Banane ke 3 Tarike + .length Property

Declaration, allocation, initialization — teen different ways. Har ek ka alag use case samjho.
public class ArrayCreation {
    public static void main(String[] args) {

        // ── WAY 1: new keyword se allocate, phir values assign ──
        // Default values automatically set hoti hain (int = 0)
        // Use karo: jab size pehle se pata ho lekin values baad mein milenge
        int[] arr1 = new int[5];
        arr1[0] = 10;  arr1[1] = 20;  arr1[2] = 30;
        arr1[3] = 40;  arr1[4] = 50;

        // ── WAY 2: Initializer syntax — direct values ──
        // Size automatically calculate hoti hai (yahan 5)
        // Use karo: jab values pehle se pata hain
        int[] arr2 = {10, 20, 30, 40, 50};

        // ── WAY 3: new keyword + values ──
        // Method return karne ke liye ya anonymous array ke liye
        // Use karo: kisi method ko directly array pass karna ho
        int[] arr3 = new int[]{100, 200, 300};

        // .length — PROPERTY hai, method nahi (isliye parentheses nahi)
        System.out.println("arr1 length: " + arr1.length);  // 5
        System.out.println("arr2 length: " + arr2.length);  // 5
        System.out.println("arr3 length: " + arr3.length);  // 3

        // First aur Last element access karna
        System.out.println("First: " + arr2[0]);                 // index 0
        System.out.println("Last:  " + arr2[arr2.length - 1]);   // index 4

        // Anonymous array — seedha method mein pass karo
        printSum(new int[]{5, 10, 15, 20});
    }

    static void printSum(int[] arr) {
        int sum = 0;
        for (int n : arr) sum += n;
        System.out.println("Sum of anonymous array: " + sum);
    }
}
▶ Output
arr1 length: 5 arr2 length: 5 arr3 length: 3 First: 10 Last: 50 Sum of anonymous array: 50
EX 1.2

Call by Reference — Sabse Important Concept

Java mein arrays reference se pass hote hain — method mein changes original array mein reflect hote hain. Ye Java ka sabse common gotcha hai!
public class CallByReference {

    // Ye method original array ko MODIFY karta hai
    static void doubleAll(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            arr[i] *= 2;  // same memory location pe write kar raha hai
        }
    }

    // Ye method naya array return karta hai (safe way)
    static int[] createSquares(int n) {
        int[] result = new int[n];  // naya array heap pe create hoga
        for (int i = 0; i < n; i++) {
            result[i] = (i + 1) * (i + 1);
        }
        return result;  // reference return hoga, copy nahi
    }

    public static void main(String[] args) {
        int[] nums = {1, 2, 3, 4, 5};

        System.out.print("Before doubleAll: ");
        for (int n : nums) System.out.print(n + " ");

        doubleAll(nums);  // nums ka reference pass hua, copy nahi

        System.out.print("\nAfter doubleAll:  ");
        for (int n : nums) System.out.print(n + " ");
        System.out.println("\n← Original array change ho gaya!");

        int[] sq = createSquares(5);
        System.out.print("\nSquares: ");
        for (int s : sq) System.out.print(s + " ");
    }
}
▶ Output
Before doubleAll: 1 2 3 4 5 After doubleAll: 2 4 6 8 10 ← Original array change ho gaya! Squares: 1 4 9 16 25
EX 1.3

Shallow Copy vs Deep Copy — 4 Ways

= operator sirf reference copy karta hai (shallow). Agar alag independent copy chahiye, deep copy karo. 4 methods hain.
import java.util.Arrays;

public class ShallowVsDeep {
    public static void main(String[] args) {
        int[] original = {1, 2, 3, 4, 5};

        // ── SHALLOW COPY (= operator) ──
        // Dono variables SAME memory location point karte hain!
        int[] shallow = original;       // sirf reference copy hua
        shallow[0] = 999;               // yahan change karo...
        System.out.println("Shallow ne change kiya, original[0] = "
            + original[0]);             // ...original mein bhi aaya!

        original[0] = 1;  // reset

        // ── DEEP COPY Way 1: Manual loop ──
        // Most explicit, sabko clear pata chalta hai kya ho raha hai
        int[] deep1 = new int[original.length];
        for (int i = 0; i < original.length; i++) deep1[i] = original[i];

        // ── DEEP COPY Way 2: Arrays.copyOf() ── RECOMMENDED ──
        // Clean, concise, 2nd param = new length (thoda bada bhi kar sakte ho)
        int[] deep2 = Arrays.copyOf(original, original.length);

        // ── DEEP COPY Way 3: System.arraycopy() ──
        // Fastest for large arrays (native implementation)
        // Params: src, srcPos, dest, destPos, length
        int[] deep3 = new int[original.length];
        System.arraycopy(original, 0, deep3, 0, original.length);

        // ── DEEP COPY Way 4: clone() ──
        // Simple, but only works for 1D arrays (2D ke liye kaam nahi karta)
        int[] deep4 = original.clone();

        // Verify: deep copy se original change nahi hota
        deep2[0] = -100;
        System.out.println("deep2[0] = " + deep2[0]);
        System.out.println("original[0] after deep2 change = " + original[0]); // unchanged!

        System.out.println("Arrays.equals(original, deep3): "
            + Arrays.equals(original, deep3));  // true — same contents
        System.out.println("original == deep3: "
            + (original == deep3));             // false — different objects
    }
}
▶ Output
Shallow ne change kiya, original[0] = 999 deep2[0] = -100 original[0] after deep2 change = 1 Arrays.equals(original, deep3): true original == deep3: false
EX 1.4

ArrayIndexOutOfBoundsException — Handle Karna

Sabse common array exception — boundary conditions samjho, graceful handling karo.
public class BoundaryHandling {
    public static void main(String[] args) {
        int[] arr = {10, 20, 30, 40, 50};  // length = 5, valid: 0 to 4

        // ✅ Safe access — boundary check ke baad
        int index = 3;
        if (index >= 0 && index < arr.length) {
            System.out.println("Safe access: arr[" + index + "] = " + arr[index]);
        }

        // ✅ Try-catch se exception handle karna
        try {
            System.out.println(arr[10]);  // invalid index!
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Exception caught: " + e.getMessage());
        }

        // ✅ Negative index bhi exception deta hai
        try {
            System.out.println(arr[-1]);  // negative index!
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Negative index caught: " + e.getMessage());
        }

        // ✅ Safe last element access
        System.out.println("Last element: " + arr[arr.length - 1]);  // ALWAYS safe

        // ✅ NullPointerException handle karna
        int[] nullArr = null;
        try {
            System.out.println(nullArr.length);
        } catch (NullPointerException e) {
            System.out.println("NullPointerException: array is null!");
        }
    }
}
▶ Output
Safe access: arr[3] = 40 Exception caught: Index 10 out of bounds for length 5 Negative index caught: Index -1 out of bounds for length 5 Last element: 50 NullPointerException: array is null!
02

Declaration & Initialization

Syntax Deep Dive · Runtime Size · String Arrays · Multi-type Arrays

📖 Complete Theory

Array Banana — Step by Step Process

Java mein array banana exactly 2 alag steps mein hota hai — jab ye dono ek saath hote hain, log confuse ho jaate hain. Inhe alag samjho:

  • Step 1 — Declaration: int[] arr; — Sirf ek reference variable create hota hai stack pe. Abhi uski value null hai. Koi memory allocate nahi hui.
  • Step 2 — Instantiation (new): arr = new int[5]; — Ab JVM heap pe 5 integers ke liye memory allocate karta hai aur default values fill karta hai. arr mein us location ka address store ho jaata hai.
  • Step 3 — Initialization: arr[0] = 10; arr[1] = 20; — Actual values assign karna. Ye optional hai agar default values se kaam chal jaye.
Array Creation Flow
STEP 1Declaration
int[] arr;
STEP 2new keyword
new int[5]
STEP 3Values Assign
arr[0] = 10
USEArray Ready
arr[i]
⚠️ Important Rules

Array Declaration ke Rules

  • Array ka size negative nahi ho sakta — new int[-1]NegativeArraySizeException
  • Array ka size zero ho sakta hai — new int[0] valid hai, empty array
  • Declare karte waqt size mention mat karo: int[5] arr — WRONG. Size new ke time di jaati hai
  • Last valid index hamesha arr.length - 1 hai — kabhi bhi arr.length access mat karo
  • Primitive array mein int, double, char etc. directly store hote hain. Object array mein references store hote hain
EX 2.1

Sab Declaration Styles + Different Types

int, double, boolean, String, char — sab types ke arrays declare karne ke ways, aur old vs modern style ka difference.
public class AllDeclarationStyles {
    public static void main(String[] args) {

        // ── Modern Style (PREFERRED) — brackets type ke saath ──
        int[]     intArr  = new int[4];
        double[]  dblArr  = new double[3];
        boolean[] boolArr = new boolean[2];
        char[]    charArr = new char[5];
        String[]  strArr  = new String[3];
        long[]    longArr = new long[3];

        // ── Old C-style (AVOID) — bracket variable ke saath ──
        int oldStyle[] = new int[3];  // valid but not Java convention

        // ── Ek line mein declare + allocate + initialize ──
        int[]    primes = {2, 3, 5, 7, 11, 13};
        String[] fruits = {"Apple", "Mango", "Banana", "Orange"};
        double[] marks  = {85.5, 92.0, 78.3, 96.7};
        char[]   vowels = {'a', 'e', 'i', 'o', 'u'};

        // ── Declaration alag, use alag ──
        int[] delayed;             // sirf reference, abhi null
        delayed = new int[3];     // baad mein allocate
        delayed[0] = 100;

        // ── Sab lengths print karo ──
        System.out.println("primes.length = " + primes.length);
        System.out.println("fruits.length = " + fruits.length);
        System.out.println("vowels.length = " + vowels.length);
        System.out.println("marks.length  = " + marks.length);

        // ── String array access ──
        System.out.println("First fruit: "  + fruits[0]);
        System.out.println("Last fruit:  "  + fruits[fruits.length - 1]);
        System.out.println("Fruit length: " + fruits[1].length());  // "Mango".length()

        // ── Zero size array ──
        int[] empty = new int[0];
        System.out.println("Empty array length: " + empty.length);  // 0, no exception
    }
}
▶ Output
primes.length = 6 fruits.length = 4 vowels.length = 5 marks.length = 4 First fruit: Apple Last fruit: Orange Fruit length: 5 Empty array length: 0
EX 2.2

Runtime Dynamic Size — Scanner se Input

Backend mein aksar pehle count aata hai (database query count, request payload size), phir array. Ye real-world pattern hai.
import java.util.Scanner;

public class DynamicArrayInput {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        System.out.print("Kitne students hain? ");
        int n = sc.nextInt();

        // Runtime pe size decide hota hai — n compile time pe pata nahi tha
        String[] names = new String[n];
        int[]    marks = new int[n];

        for (int i = 0; i < n; i++) {
            System.out.print("Student " + (i+1) + " ka naam: ");
            names[i] = sc.next();
            System.out.print("Marks (0-100): ");
            marks[i] = sc.nextInt();
        }

        // Stats nikalo
        int sum = 0, maxIdx = 0, minIdx = 0, passCount = 0;
        for (int i = 0; i < n; i++) {
            sum += marks[i];
            if (marks[i] > marks[maxIdx]) maxIdx = i;
            if (marks[i] < marks[minIdx]) minIdx = i;
            if (marks[i] >= 35) passCount++;
        }

        System.out.println("\n── RESULT SUMMARY ──");
        System.out.printf("Class Average: %.2f%n", (double) sum / n);
        System.out.println("Topper: " + names[maxIdx] + " (" + marks[maxIdx] + ")");
        System.out.println("Lowest: " + names[minIdx] + " (" + marks[minIdx] + ")");
        System.out.println("Pass: " + passCount + ", Fail: " + (n - passCount));
        sc.close();
    }
}
▶ Sample Output (Input: 3 students)
Kitne students hain? 3 Student 1 ka naam: Rahul Marks: 85 Student 2 ka naam: Priya Marks: 92 Student 3 ka naam: Amit Marks: 48 ── RESULT SUMMARY ── Class Average: 75.00 Topper: Priya (92) Lowest: Amit (48) Pass: 3, Fail: 0
EX 2.3

Char Array — String se Convert aur Back

char[] aur String ke beech conversion — palindrome check, character frequency — interview mein common.
import java.util.Arrays;

public class CharArrayOps {
    public static void main(String[] args) {
        String word = "programming";

        // String → char[]
        char[] chars = word.toCharArray();
        System.out.println("char array: " + Arrays.toString(chars));

        // char[] → String
        String back = new String(chars);
        System.out.println("Back to String: " + back);

        // Palindrome check karo
        String test = "madam";
        char[] t = test.toCharArray();
        boolean isPalin = true;
        for (int i = 0; i < t.length / 2; i++) {
            if (t[i] != t[t.length - 1 - i]) { isPalin = false; break; }
        }
        System.out.println("\"" + test + "\" is palindrome: " + isPalin);

        // Character frequency count karo
        int[] freq = new int[26];  // a-z ke liye
        for (char c : word.toCharArray()) freq[c - 'a']++;
        System.out.println("\nFrequency in \"" + word + "\":");
        for (int i = 0; i < 26; i++) {
            if (freq[i] > 0)
                System.out.println("  " + (char)('a' + i) + ": " + freq[i]);
        }
    }
}
▶ Output
char array: [p, r, o, g, r, a, m, m, i, n, g] Back to String: programming "madam" is palindrome: true Frequency in "programming": a: 1 g: 2 i: 1 m: 2 n: 1 o: 1 p: 1 r: 2
03

Default Values

Automatic Initialization · Type-wise Defaults · NullPointerException Prevention

📖 Complete Theory

Java Arrays Automatically Initialize Hote Hain

Java mein jab bhi new keyword se array create hota hai, JVM automatically sabhi elements ko type-specific default values se fill karta hai. Ye garbage values nahi hain — ye deterministic aur predictable values hain.

Ye behavior C/C++ se alag hai jahan uninitialized variables mein garbage values hoti hain. Java ka ye feature code safety ke liye important hai, especially null checks ke liye.

Kyu important hai: Agar aap String[] arr = new String[5]; banate ho aur phir seedha arr[0].toUpperCase() call karte ho — NullPointerException aayegi! arr[0] null hai by default.

Data TypeDefault ValueMemoryExample
byte01 bytenew byte[3] → [0, 0, 0]
short02 bytesnew short[3] → [0, 0, 0]
int04 bytesnew int[3] → [0, 0, 0]
long0L8 bytesnew long[3] → [0, 0, 0]
float0.0f4 bytesnew float[2] → [0.0, 0.0]
double0.08 bytesnew double[2] → [0.0, 0.0]
booleanfalse1 bit (JVM dependent)new boolean[2] → [false, false]
char'\u0000' (null char)2 bytesnew char[2] → ['\0', '\0']
String, Objectnull4/8 bytes (ref)new String[2] → [null, null]
EX 3.1

Sab Default Values Verify + Null Safety

Har type ke default values dekhkar null safety patterns sikho — production code mein ye bahut zaroori hai.
public class DefaultValues {
    public static void main(String[] args) {

        int[]     intArr  = new int[3];
        double[]  dblArr  = new double[3];
        boolean[] boolArr = new boolean[3];
        char[]    charArr = new char[3];
        String[]  strArr  = new String[3];
        long[]    longArr = new long[3];

        System.out.println("Type      Default");
        System.out.println("──────────────────");
        System.out.println("int:      " + intArr[0]);
        System.out.println("double:   " + dblArr[0]);
        System.out.println("boolean:  " + boolArr[0]);
        System.out.println("char:     '" + charArr[0] + "' (null char = '" + (int)charArr[0] + "')");
        System.out.println("String:   " + strArr[0]);
        System.out.println("long:     " + longArr[0]);

        // ── Null Safety Patterns ──
        System.out.println("\n── Null Safety Patterns ──");

        // Pattern 1: null check before using
        for (int i = 0; i < strArr.length; i++) {
            if (strArr[i] != null) {
                System.out.println(strArr[i].toUpperCase());
            } else {
                System.out.println("[index " + i + " is null]");
            }
        }

        // Pattern 2: Initialize with default value before use
        String[] names = new String[3];
        for (int i = 0; i < names.length; i++) names[i] = "Unknown";
        System.out.println("Pre-initialized: " + names[0]); // "Unknown", not null

        // ── Is int[] array auto-initialized? ──
        // Ye confirm karo: frequency count correctly kaam karega
        int[] freq = new int[10];  // sab 0 hain
        freq[3]++;  freq[7]++;  freq[3]++;
        System.out.println("\nFreq[3] = " + freq[3] + ", Freq[7] = " + freq[7]);
    }
}
▶ Output
Type Default ────────────────── int: 0 double: 0.0 boolean: false char: '' (null char = '0') String: null long: 0 ── Null Safety Patterns ── [index 0 is null] [index 1 is null] [index 2 is null] Pre-initialized: Unknown Freq[3] = 2, Freq[7] = 1
04

Array Traversal

for · for-each · while · do-while · Common Patterns · Algorithms

📖 Theory — Traversal Kya Hai?

Har Element Ko Visit Karna

Array ke har element ko sequentially visit karne ki process ko traversal kehte hain. Java mein 4 loop types se traversal hoti hai, aur har ek ka alag use case hai:

  • for loop (index-based): Jab index chahiye, elements modify karne ho, ya specific range traverse karni ho. Sabse flexible.
  • for-each (enhanced for): Jab sirf read karna ho, code clean aur readable chahiye. Modification ke liye use nahi kar sakte.
  • while loop: Jab condition runtime pe depend karti ho, ya loop se beech mein exit karna ho.
  • do-while loop: Jab kam se kam ek baar execute karna ho (rare for arrays).

Performance: Sab loops ka time complexity O(n) hai — speed mein practically koi difference nahi. Choice readability aur requirement pe based hoti hai.

⚠️
for-each Limitation: for-each loop mein primitive array ke element ko change karne se original array nahi badlega! for (int n : arr) { n = n*2; } — arr unchanged rahega. Modification ke liye index-based for loop use karo.
EX 4.1

Charon Loop Types — Comparison

Same array ko 4 loops se traverse karo — sab ka output same, lekin usage patterns alag.
public class AllLoopTypes {
    public static void main(String[] args) {
        int[] arr = {10, 20, 30, 40, 50};

        // ── 1. for loop (index-based) ──
        // Best: modification, specific range, index chahiye
        System.out.print("for loop:      ");
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println("  | i goes 0 to " + (arr.length-1));

        // ── 2. for-each ──
        // Best: read-only traversal, cleanest syntax
        System.out.print("for-each:      ");
        for (int val : arr) {
            System.out.print(val + " ");
        }
        System.out.println("  | No index available");

        // ── 3. while loop ──
        // Best: condition runtime pe decide ho
        System.out.print("while loop:    ");
        int i = 0;
        while (i < arr.length) {
            System.out.print(arr[i] + " ");
            i++;
        }
        System.out.println("  | i manually manage karo");

        // ── 4. do-while ──
        // At least ek baar chalega, even if condition false ho
        System.out.print("do-while:      ");
        int j = 0;
        do {
            System.out.print(arr[j] + " ");
            j++;
        } while (j < arr.length);
        System.out.println("  | Body pehle, condition baad");

        // ── 5. Reverse traversal ──
        System.out.print("Reverse:       ");
        for (int k = arr.length - 1; k >= 0; k--) {
            System.out.print(arr[k] + " ");
        }
        System.out.println();

        // ── 6. Step-by-2 ──
        System.out.print("Step by 2:     ");
        for (int k = 0; k < arr.length; k += 2) {
            System.out.print(arr[k] + " ");
        }
        System.out.println("  | Only even indices");
    }
}
▶ Output
for loop: 10 20 30 40 50 | i goes 0 to 4 for-each: 10 20 30 40 50 | No index available while loop: 10 20 30 40 50 | i manually manage karo do-while: 10 20 30 40 50 | Body pehle, condition baad Reverse: 50 40 30 20 10 Step by 2: 10 30 50 | Only even indices
EX 4.2

Array Stats — Sum, Avg, Max, Min, Range, Even/Odd

Single pass mein sab stats nikalo — efficient O(n) solution. Backend analytics mein ye daily use hota hai.
public class ArrayStatistics {
    public static void main(String[] args) {
        int[] nums = {5, 12, 3, 8, 17, 24, 9, 6, 15, 2, 11, 19};

        // Single pass mein sab calculate karo — O(n)
        int    sum = 0, max = nums[0], min = nums[0];
        int    evenSum = 0, oddSum = 0, evenCnt = 0, oddCnt = 0;
        int    posCount = 0, negCount = 0;
        long   product = 1;

        for (int n : nums) {
            sum     += n;
            product *= n;
            if (n > max) max = n;
            if (n < min) min = n;
            if (n % 2 == 0) { evenSum += n; evenCnt++; }
            else             { oddSum  += n; oddCnt++;  }
            if (n > 0) posCount++; else if (n < 0) negCount++;
        }

        int n = nums.length;
        System.out.println("Array size:     " + n);
        System.out.println("Sum:            " + sum);
        System.out.printf( "Average:        %.2f%n", (double) sum / n);
        System.out.println("Max:            " + max);
        System.out.println("Min:            " + min);
        System.out.println("Range (max-min):" + (max - min));
        System.out.println("Even count/sum: " + evenCnt + " / " + evenSum);
        System.out.println("Odd  count/sum: " + oddCnt  + " / " + oddSum);
        System.out.println("Positive count: " + posCount);
    }
}
▶ Output
Array size: 12 Sum: 131 Average: 10.92 Max: 24 Min: 2 Range (max-min):22 Even count/sum: 5 / 52 Odd count/sum: 7 / 79 Positive count: 12
EX 4.3

Array Rotation — Left, Right, By K

Circular rotation — circular queue, scheduler, round-robin algorithms ka base hai ye concept.
import java.util.Arrays;

public class ArrayRotation {

    static void leftRotateOne(int[] arr) {
        int first = arr[0];                          // pehla element save karo
        for (int i = 0; i < arr.length - 1; i++)
            arr[i] = arr[i + 1];                     // sab left shift karo
        arr[arr.length - 1] = first;                 // last pe rakh do
    }

    static void rightRotateOne(int[] arr) {
        int last = arr[arr.length - 1];              // aakhri element save
        for (int i = arr.length - 1; i > 0; i--)
            arr[i] = arr[i - 1];                     // sab right shift
        arr[0] = last;                               // pehle pe rakh do
    }

    static void leftRotateByK(int[] arr, int k) {
        k = k % arr.length;  // handle k > length (e.g. rotate by 7 on len 5 = rotate by 2)
        if (k < 0) k += arr.length;  // negative k handle
        for (int i = 0; i < k; i++) leftRotateOne(arr);
    }

    // Efficient rotation using reversal — O(n), O(1) space
    static void reverse(int[] arr, int start, int end) {
        while (start < end) {
            int t = arr[start]; arr[start] = arr[end]; arr[end] = t;
            start++; end--;
        }
    }

    static void leftRotateEfficient(int[] arr, int k) {
        k %= arr.length;
        reverse(arr, 0, k - 1);           // first k reverse
        reverse(arr, k, arr.length - 1);  // rest reverse
        reverse(arr, 0, arr.length - 1);  // whole array reverse
    }

    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        System.out.println("Original:         " + Arrays.toString(arr));

        leftRotateOne(arr);
        System.out.println("Left rotate 1:    " + Arrays.toString(arr));

        arr = new int[]{1, 2, 3, 4, 5};
        rightRotateOne(arr);
        System.out.println("Right rotate 1:   " + Arrays.toString(arr));

        arr = new int[]{1, 2, 3, 4, 5};
        leftRotateByK(arr, 2);
        System.out.println("Left rotate by 2: " + Arrays.toString(arr));

        arr = new int[]{1, 2, 3, 4, 5};
        leftRotateEfficient(arr, 2);
        System.out.println("Efficient rotate 2:" + Arrays.toString(arr));

        arr = new int[]{1, 2, 3, 4, 5};
        leftRotateByK(arr, 7); // 7 % 5 = 2
        System.out.println("Rotate by 7(≡2):  " + Arrays.toString(arr));
    }
}
▶ Output
Original: [1, 2, 3, 4, 5] Left rotate 1: [2, 3, 4, 5, 1] Right rotate 1: [5, 1, 2, 3, 4] Left rotate by 2: [3, 4, 5, 1, 2] Efficient rotate 2:[3, 4, 5, 1, 2] Rotate by 7(≡2): [3, 4, 5, 1, 2]
EX 4.4

Sliding Window — Max Sum Subarray of Size K

Sliding window technique — O(n) solution. Brute force O(n×k) se zyada efficient. Backend data processing mein common.
public class SlidingWindow {
    public static void main(String[] args) {
        int[] arr = {2, 1, 5, 1, 3, 2, 8, 1, 4, 3};
        int k = 3;  // window size

        // ── Brute Force O(n×k) — For comparison ──
        int maxBrute = Integer.MIN_VALUE;
        for (int i = 0; i <= arr.length - k; i++) {
            int winSum = 0;
            for (int j = i; j < i + k; j++) winSum += arr[j];
            if (winSum > maxBrute) maxBrute = winSum;
        }
        System.out.println("Brute Force Max Sum (k=" + k + "): " + maxBrute);

        // ── Sliding Window O(n) — Efficient ──
        // Pehla window calculate karo
        int windowSum = 0;
        for (int i = 0; i < k; i++) windowSum += arr[i];
        int maxSum = windowSum, maxStart = 0;

        // Window slide karo — add new element, remove old
        for (int i = k; i < arr.length; i++) {
            windowSum += arr[i] - arr[i - k];  // add right, remove left
            if (windowSum > maxSum) {
                maxSum = windowSum;
                maxStart = i - k + 1;
            }
        }
        System.out.println("Sliding Window Max Sum: " + maxSum);
        System.out.print("Window: ");
        for (int i = maxStart; i < maxStart + k; i++)
            System.out.print(arr[i] + " ");
    }
}
▶ Output
Brute Force Max Sum (k=3): 15 Sliding Window Max Sum: 15 Window: 8 1 4
05

Multi-Dimensional Arrays

2D Theory · Memory Model · Matrix Operations · 3D Arrays

📖 Deep Theory

2D Array — Array of Arrays

Java mein 2D array actually "array of arrays" hai. Jab aap int[][] mat = new int[3][4]; likhte ho, tab:

  • mat ek reference hai jisme 3 references hain
  • Har reference ek alag 1D array ka reference hai (4 integers wali)
  • Ye 3 inner arrays heap pe alag alag objects hain — isliye har row ki length alag ho sakti hai (jagged arrays)

Access: mat[row][col] — pehle row index (outer), phir column index (inner). Traverse ke liye nested loops: outer = rows, inner = columns.

Real uses: Spreadsheets, chess/tic-tac-toe game boards, image pixel data (RGB), adjacency matrix for graphs, multiplication tables, seating charts.

2D Array Memory — int[][] mat = new int[3][3]
mat[0] → Row 0
1
[0][0]
2
[0][1]
3
[0][2]
mat[1] → Row 1
4
[1][0]
5
[1][1]
6
[1][2]
mat[2] → Row 2
7
[2][0]
8
[2][1]
9
[2][2]
mat.length = 3 (rows) · mat[0].length = 3 (cols) · Har row alag heap object hai · Center [1][1] highlighted
EX 5.1

Matrix — Create, Display, Sums, Diagonal

2D array banao, formatted print karo, row/column sums aur main diagonal sum nikalo.
public class MatrixOperations {

    static void printMatrix(int[][] m, String title) {
        System.out.println("\n── " + title + " ──");
        for (int[] row : m) {
            for (int v : row) System.out.printf("%5d", v);
            System.out.println();
        }
    }

    public static void main(String[] args) {
        int[][] mat = {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12}
        };
        printMatrix(mat, "Original Matrix (3×4)");

        // Row sums
        System.out.println("\nRow Sums:");
        for (int i = 0; i < mat.length; i++) {
            int rowSum = 0;
            for (int j = 0; j < mat[i].length; j++) rowSum += mat[i][j];
            System.out.println("  Row " + i + ": " + rowSum);
        }

        // Column sums
        System.out.println("Column Sums:");
        for (int j = 0; j < mat[0].length; j++) {
            int colSum = 0;
            for (int i = 0; i < mat.length; i++) colSum += mat[i][j];
            System.out.println("  Col " + j + ": " + colSum);
        }

        // Square matrix diagonal sums
        int[][] sq = {{1,2,3},{4,5,6},{7,8,9}};
        int mainDiag = 0, antiDiag = 0, n = sq.length;
        for (int i = 0; i < n; i++) {
            mainDiag += sq[i][i];              // top-left to bottom-right
            antiDiag += sq[i][n - 1 - i];     // top-right to bottom-left
        }
        System.out.println("\nSquare matrix 3×3:");
        System.out.println("  Main Diagonal Sum: " + mainDiag);
        System.out.println("  Anti Diagonal Sum: " + antiDiag);

        // Total sum
        int total = 0;
        for (int[] row : mat) for (int v : row) total += v;
        System.out.println("\nTotal sum of all elements: " + total);
    }
}
▶ Output
── Original Matrix (3×4) ── 1 2 3 4 5 6 7 8 9 10 11 12 Row Sums: Row 0: 10 Row 1: 26 Row 2: 42 Column Sums: Col 0: 15 Col 1: 18 Col 2: 21 Col 3: 24 Square matrix 3×3: Main Diagonal Sum: 15 Anti Diagonal Sum: 15 Total sum of all elements: 78
EX 5.2

Matrix Transpose + Multiplication

Transpose (rows↔cols swap) aur multiplication — ML/graphics mein fundamental. Triple nested loop se multiplication.
public class MatrixMath {

    static int[][] transpose(int[][] mat) {
        int rows = mat.length, cols = mat[0].length;
        int[][] result = new int[cols][rows];
        for (int i = 0; i < rows; i++)
            for (int j = 0; j < cols; j++)
                result[j][i] = mat[i][j];
        return result;
    }

    static int[][] multiply(int[][] A, int[][] B) {
        // A: (r × k), B: (k × c) => Result: (r × c)
        if (A[0].length != B.length) throw new IllegalArgumentException("Invalid dimensions");
        int r = A.length, c = B[0].length, k = B.length;
        int[][] result = new int[r][c];
        for (int i = 0; i < r; i++)
            for (int j = 0; j < c; j++)
                for (int m = 0; m < k; m++)
                    result[i][j] += A[i][m] * B[m][j];
        return result;
    }

    static void print(int[][] mat, String name) {
        System.out.println(name + " (" + mat.length + "×" + mat[0].length + "):");
        for (int[] row : mat) {
            for (int v : row) System.out.printf("%5d", v);
            System.out.println();
        }
    }

    public static void main(String[] args) {
        int[][] A = {{1, 2, 3}, {4, 5, 6}};  // 2×3
        print(A, "A");
        print(transpose(A), "Transpose of A");

        int[][] X = {{1, 2}, {3, 4}};
        int[][] Y = {{5, 6}, {7, 8}};
        print(X, "\nX");
        print(Y, "Y");
        print(multiply(X, Y), "X × Y");
    }
}
▶ Output
A (2×3): 1 2 3 4 5 6 Transpose of A (3×2): 1 4 2 5 3 6 X (2×2): Y (2×2): 1 2 5 6 3 4 7 8 X × Y (2×2): 19 22 43 50
06

Jagged Arrays

Unequal Row Sizes · Memory Efficiency · Pascal's Triangle

📖 Theory

Jagged Array — Irregular Shape

Jagged array (ragged array bhi kehte hain) ek 2D array hai jisme har row ki length alag alag ho sakti hai. Ye possible isliye hai kyunki Java mein 2D array actually "array of arrays" hai — har inner array ek independent object hai.

Syntax: Pehle rows declare karo sirf: int[][] jagged = new int[4][]; — columns ki size nahi di. Phir alag alag: jagged[0] = new int[2];, jagged[1] = new int[5]; etc.

Use cases: Students ke alag alag subjects, triangular matrices (lower/upper), Pascal's Triangle, sparse data structures, variable-length records. Regular 2D array se zyada memory efficient hota hai jab rows ki lengths vary karti hain.

✅ Jagged Array Advantages

  • Memory efficient — sirf jaroori space
  • Variable length rows naturally represent karta hai
  • Triangular/Pascal data ke liye perfect
  • Flexible structure

⚠️ Limitations

  • Code thoda complex hota hai
  • Har row ke length alag-alag track karna padta hai
  • Rectangular operations apply nahi hoti directly
EX 6.1

Jagged Array + Pascal's Triangle

Jagged array ka perfect example — Pascal's Triangle. Row n mein exactly n+1 elements hote hain.
public class JaggedAndPascal {
    public static void main(String[] args) {

        // ── Simple Jagged Array ──
        int[][] jagged = new int[4][];  // 4 rows, column size unknown
        jagged[0] = new int[]{10};                  // row 0: 1 element
        jagged[1] = new int[]{20, 21};              // row 1: 2 elements
        jagged[2] = new int[]{30, 31, 32};          // row 2: 3 elements
        jagged[3] = new int[]{40, 41, 42, 43};      // row 3: 4 elements

        System.out.println("Jagged Array:");
        for (int i = 0; i < jagged.length; i++) {
            System.out.printf("  Row %d (len=%d): ", i, jagged[i].length);
            for (int v : jagged[i]) System.out.printf("%4d", v);
            System.out.println();
        }

        // ── Pascal's Triangle ──
        // Row i mein i+1 elements hote hain
        // pascal[i][j] = pascal[i-1][j-1] + pascal[i-1][j]
        // Edges (first aur last) hamesha 1 hote hain
        int rows = 8;
        int[][] pascal = new int[rows][];

        for (int i = 0; i < rows; i++) {
            pascal[i] = new int[i + 1];     // row i mein i+1 elements
            pascal[i][0] = 1;                // first element = 1
            pascal[i][i] = 1;                // last element = 1
            for (int j = 1; j < i; j++) {   // middle elements
                pascal[i][j] = pascal[i-1][j-1] + pascal[i-1][j];
            }
        }

        System.out.println("\nPascal's Triangle:");
        for (int i = 0; i < rows; i++) {
            for (int sp = 0; sp < rows - i; sp++) System.out.print("   ");
            for (int j = 0; j <= i; j++) System.out.printf("%6d", pascal[i][j]);
            System.out.println();
        }
    }
}
▶ Output
Jagged Array: Row 0 (len=1): 10 Row 1 (len=2): 20 21 Row 2 (len=3): 30 31 32 Row 3 (len=4): 40 41 42 43 Pascal's Triangle: 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1 1 6 15 20 15 6 1 1 7 21 35 35 21 7 1
07

java.util.Arrays

sort · fill · copyOf · toString · binarySearch · stream · deepToString

📖 Theory — Built-in Utility Class

Arrays Class — Kya Hai aur Kyu Use Karo?

java.util.Arrays ek utility class hai jo arrays ke saath kaam karne ke liye static methods provide karta hai. import java.util.Arrays; zaroori hai. Ye methods manually likhne se zyada reliable, tested, aur often faster hain.

Is class ke sare methods static hain — seedha class naam se call karo: Arrays.sort(arr), Arrays.toString(arr) etc. Object banane ki zaroorat nahi.

MethodUseTimeReturn
Arrays.sort(arr)Ascending sortO(n log n)void
Arrays.sort(arr, from, to)Partial sortO(k log k)void
Arrays.binarySearch(arr, key)Search in sorted arrayO(log n)int index
Arrays.fill(arr, val)Sab elements same valueO(n)void
Arrays.fill(arr, from, to, val)Partial fillO(k)void
Arrays.copyOf(arr, len)Copy (expand/shrink)O(n)new array
Arrays.copyOfRange(arr, f, t)Partial copyO(k)new array
Arrays.toString(arr)Readable stringO(n)String
Arrays.deepToString(arr)2D array readable stringO(n×m)String
Arrays.equals(a, b)Content equality checkO(n)boolean
Arrays.stream(arr)Functional stream createO(1)IntStream
EX 7.1

Arrays Methods — Complete Reference

Sab important methods ek saath — sort, fill, copy, toString, equals, deepToString, descending sort.
import java.util.Arrays;
import java.util.Comparator;

public class ArraysClassDemo {
    public static void main(String[] args) {

        // ── toString() — MUST USE for printing ──
        int[] nums = {5, 3, 8, 1, 9, 2, 7};
        System.out.println("Raw print:    " + nums);               // [I@7c30a502 ← garbage!
        System.out.println("toString:     " + Arrays.toString(nums)); // readable

        // ── sort() — Dual-Pivot Quicksort internally ──
        Arrays.sort(nums);
        System.out.println("After sort:   " + Arrays.toString(nums));

        // ── Partial sort (index 1 to 4) ──
        int[] partial = {9, 5, 3, 7, 1, 8};
        Arrays.sort(partial, 1, 4);  // sirf index 1,2,3 sort hoga
        System.out.println("Partial sort: " + Arrays.toString(partial));

        // ── fill() ──
        int[] filled = new int[6];
        Arrays.fill(filled, 42);
        System.out.println("Filled 42:    " + Arrays.toString(filled));
        Arrays.fill(filled, 2, 5, -1);  // index 2,3,4 = -1
        System.out.println("Partial fill: " + Arrays.toString(filled));

        // ── copyOf() — size badha sakte ya ghata sakte ho ──
        int[] orig = {10, 20, 30};
        int[] bigger = Arrays.copyOf(orig, 6);       // 0s se fill hoga
        int[] smaller = Arrays.copyOf(orig, 2);      // truncate hoga
        int[] range = Arrays.copyOfRange(orig, 1, 3);// index 1 to 2 (3 exclusive)
        System.out.println("Bigger:  "  + Arrays.toString(bigger));
        System.out.println("Smaller: "  + Arrays.toString(smaller));
        System.out.println("Range:   "  + Arrays.toString(range));

        // ── equals() — reference vs content ──
        int[] a = {1, 2, 3}, b = {1, 2, 3}, c = {1, 2, 4};
        System.out.println("a == b:          " + (a == b));            // false (ref compare)
        System.out.println("Arrays.equals:   " + Arrays.equals(a, b)); // true (content)
        System.out.println("Arrays.equals c: " + Arrays.equals(a, c)); // false

        // ── deepToString for 2D ──
        int[][] mat = {{1, 2, 3}, {4, 5, 6}};
        System.out.println("deepToString: " + Arrays.deepToString(mat));

        // ── Descending sort (Integer[] needed, not int[]) ──
        Integer[] desc = {5, 3, 8, 1, 9};
        Arrays.sort(desc, Comparator.reverseOrder());
        System.out.println("Descending:   " + Arrays.toString(desc));
    }
}
▶ Output
Raw print: [I@7c30a502 ← memory address, not values! toString: [5, 3, 8, 1, 9, 2, 7] After sort: [1, 2, 3, 5, 7, 8, 9] Partial sort: [9, 3, 5, 7, 1, 8] Filled 42: [42, 42, 42, 42, 42, 42] Partial fill: [42, 42, -1, -1, -1, 42] Bigger: [10, 20, 30, 0, 0, 0] Smaller: [10, 20] Range: [20, 30] a == b: false Arrays.equals: true Arrays.equals c: false deepToString: [[1, 2, 3], [4, 5, 6]] Descending: [9, 8, 5, 3, 1]
EX 7.2

Arrays.stream() — Functional Programming (Java 8+)

Modern Java backend code mein streams common hain. Filter, map, reduce — sab ek line mein.
import java.util.Arrays;

public class StreamOperations {
    public static void main(String[] args) {
        int[] nums = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};

        // ── Aggregate Operations ──
        System.out.println("Sum:          " + Arrays.stream(nums).sum());
        System.out.printf( "Average:      %.2f%n",
            Arrays.stream(nums).average().getAsDouble());
        System.out.println("Max:          " + Arrays.stream(nums).max().getAsInt());
        System.out.println("Min:          " + Arrays.stream(nums).min().getAsInt());
        System.out.println("Count:        " + Arrays.stream(nums).count());

        // ── Filter ──
        System.out.println("Count > 4:    " + Arrays.stream(nums).filter(n -> n > 4).count());
        int[] evens = Arrays.stream(nums).filter(n -> n % 2 == 0).toArray();
        System.out.println("Evens only:   " + Arrays.toString(evens));

        // ── Map ──
        int[] squared = Arrays.stream(nums).map(n -> n * n).toArray();
        System.out.println("Squared:      " + Arrays.toString(squared));

        // ── Sorted + Distinct ──
        int[] sortedUniq = Arrays.stream(nums).sorted().distinct().toArray();
        System.out.println("Sorted Unique:" + Arrays.toString(sortedUniq));

        // ── anyMatch, allMatch, noneMatch ──
        System.out.println("Any negative: " + Arrays.stream(nums).anyMatch(n -> n < 0));
        System.out.println("All positive: " + Arrays.stream(nums).allMatch(n -> n > 0));

        // ── reduce — custom aggregation ──
        int product = Arrays.stream(nums).reduce(1, (a, b) -> a * b);
        System.out.println("Product:      " + product);
    }
}
▶ Output
Sum: 44 Average: 4.00 Max: 9 Min: 1 Count: 11 Count > 4: 4 Evens only: [4, 2, 6] Squared: [9, 1, 16, 1, 25, 81, 4, 36, 25, 9, 25] Sorted Unique:[1, 2, 3, 4, 5, 6, 9] Any negative: false All positive: true Product: 97200
08

Sorting Algorithms

Bubble · Selection · Insertion · Merge · Quick Sort · Complexity Analysis

📖 Why Learn Sorting Algorithms?

Arrays.sort() Kafi Nahi Hai — Kyu?

Production mein hamesha Arrays.sort() use karo — wo best hai. Lekin underlying algorithms samajhna:

  • Interviews: Google, Amazon, Flipkart sab sorting algorithms poochte hain — time/space complexity ke saath
  • Custom Sorting: Partial sort, stable sort, sort by multiple criteria — apna logic likhna padega
  • Debugging: Agar kisi production sort ne unexpected behavior diya, algorithm samajhna zaroori hai
  • Trade-offs: Nearly sorted data pe Insertion Sort, small data pe Bubble/Selection theek hain
AlgorithmBestAverageWorstSpaceStableBest Use
Bubble SortO(n)O(n²)O(n²)O(1)Teaching, small data
Selection SortO(n²)O(n²)O(n²)O(1)Minimum swaps needed
Insertion SortO(n)O(n²)O(n²)O(1)Nearly sorted data
Merge SortO(n log n)O(n log n)O(n log n)O(n)Large data, stable needed
Quick SortO(n log n)O(n log n)O(n²)O(log n)General purpose, fastest avg
EX 8.1

Bubble Sort — Optimized (with swapped flag)

Adjacent elements compare karo, swap karo. Optimized version: already sorted array O(n) mein detect ho jaata hai.
import java.util.Arrays;

public class BubbleSort {

    static void bubbleSort(int[] arr) {
        int n = arr.length;
        int passes = 0, comparisons = 0, swaps = 0;

        for (int i = 0; i < n - 1; i++) {
            boolean swapped = false;  // optimization: early exit
            passes++;
            for (int j = 0; j < n - i - 1; j++) {
                comparisons++;
                if (arr[j] > arr[j + 1]) {
                    // Swap
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    swapped = true;
                    swaps++;
                }
            }
            if (!swapped) break;  // koi swap nahi = already sorted
        }
        System.out.printf("Passes: %d, Comparisons: %d, Swaps: %d%n",
            passes, comparisons, swaps);
    }

    public static void main(String[] args) {
        int[] arr = {64, 25, 12, 22, 11, 90, 47, 36};
        System.out.println("Before: " + Arrays.toString(arr));
        bubbleSort(arr);
        System.out.println("After:  " + Arrays.toString(arr));

        // Already sorted case — O(n)
        int[] sorted = {1, 2, 3, 4, 5};
        System.out.println("\nAlready sorted:");
        bubbleSort(sorted);
    }
}
▶ Output
Before: [64, 25, 12, 22, 11, 90, 47, 36] Passes: 7, Comparisons: 28, Swaps: 11 After: [11, 12, 22, 25, 36, 47, 64, 90] Already sorted: Passes: 1, Comparisons: 4, Swaps: 0 ← O(n) early exit!
EX 8.2

Selection Sort + Insertion Sort

Selection = minimum find karke sahi jagah rakh do. Insertion = playing cards jaisa — ek ek element sahi jagah insert karo.
import java.util.Arrays;

public class SelInsSort {

    static void selectionSort(int[] arr) {
        int n = arr.length;
        for (int i = 0; i < n - 1; i++) {
            int minIdx = i;  // assume i minimum hai
            for (int j = i + 1; j < n; j++) {
                if (arr[j] < arr[minIdx]) minIdx = j;  // actual minimum dhundo
            }
            // Minimum ko sahi jagah pe rakh do
            int temp = arr[minIdx]; arr[minIdx] = arr[i]; arr[i] = temp;
        }
        // Advantage: minimum swaps (n-1 max) — useful jab write ops costly ho
    }

    static void insertionSort(int[] arr) {
        int n = arr.length;
        for (int i = 1; i < n; i++) {
            int key = arr[i];  // current element "haath mein le lo"
            int j = i - 1;
            // Bade elements ko right shift karo jab tak sahi jagah na mile
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];
                j--;
            }
            arr[j + 1] = key;  // "card" sahi jagah rakho
        }
        // Advantage: Nearly sorted data ke liye best O(n), stable sort
    }

    public static void main(String[] args) {
        int[] arr1 = {64, 25, 12, 22, 11};
        int[] arr2 = arr1.clone();

        System.out.println("Original:       " + Arrays.toString(arr1));
        selectionSort(arr1);
        System.out.println("Selection Sort: " + Arrays.toString(arr1));

        insertionSort(arr2);
        System.out.println("Insertion Sort: " + Arrays.toString(arr2));

        // Insertion sort — nearly sorted data advantage
        int[] nearly = {1, 2, 4, 3, 5};  // sirf 3,4 swap out of order
        insertionSort(nearly);
        System.out.println("Nearly sorted:  " + Arrays.toString(nearly));
    }
}
▶ Output
Original: [64, 25, 12, 22, 11] Selection Sort: [11, 12, 22, 25, 64] Insertion Sort: [11, 12, 22, 25, 64] Nearly sorted: [1, 2, 3, 4, 5]
EX 8.3

Merge Sort — Divide & Conquer

O(n log n) guaranteed. Array divide karo, recursively sort karo, sorted halves ko merge karo. Stable sort — equal elements ka original order preserve hota hai.
import java.util.Arrays;

public class MergeSort {

    static void merge(int[] arr, int left, int mid, int right) {
        // Do sorted halves ko merge karo
        int[] L = Arrays.copyOfRange(arr, left, mid + 1);
        int[] R = Arrays.copyOfRange(arr, mid + 1, right + 1);

        int i = 0, j = 0, k = left;
        while (i < L.length && j < R.length) {
            if (L[i] <= R[j]) arr[k++] = L[i++];  // <= makes it stable
            else               arr[k++] = R[j++];
        }
        while (i < L.length) arr[k++] = L[i++];  // remaining
        while (j < R.length) arr[k++] = R[j++];
    }

    static void mergeSort(int[] arr, int left, int right) {
        if (left >= right) return;  // base case: 1 element = sorted
        int mid = left + (right - left) / 2;   // overflow-safe midpoint
        mergeSort(arr, left, mid);             // left half sort karo
        mergeSort(arr, mid + 1, right);        // right half sort karo
        merge(arr, left, mid, right);          // dono merge karo
    }

    public static void main(String[] args) {
        int[] arr = {38, 27, 43, 3, 9, 82, 10, 57};
        System.out.println("Before: " + Arrays.toString(arr));
        mergeSort(arr, 0, arr.length - 1);
        System.out.println("After:  " + Arrays.toString(arr));

        // Large array test
        int[] large = {5,1,8,3,9,2,7,4,6,0};
        mergeSort(large, 0, large.length - 1);
        System.out.println("Large:  " + Arrays.toString(large));
    }
}
▶ Output
Before: [38, 27, 43, 3, 9, 82, 10, 57] After: [3, 9, 10, 27, 38, 43, 57, 82] Large: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
EX 8.4

Quick Sort — Partition + Pivot

Average O(n log n), in-place, fastest in practice. Pivot choose karo, partition karo, recursively sort karo. Last element as pivot.
import java.util.Arrays;

public class QuickSort {

    static int partition(int[] arr, int low, int high) {
        int pivot = arr[high];  // last element pivot hai
        int i = low - 1;        // smaller elements ka boundary

        for (int j = low; j < high; j++) {
            if (arr[j] <= pivot) {
                i++;
                int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp;
            }
        }
        // Pivot ko sahi jagah pe rakho
        int temp = arr[i+1]; arr[i+1] = arr[high]; arr[high] = temp;
        return i + 1;  // pivot ka final index
    }

    static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            int pivotIdx = partition(arr, low, high);
            quickSort(arr, low, pivotIdx - 1);   // left part
            quickSort(arr, pivotIdx + 1, high);  // right part
        }
    }

    public static void main(String[] args) {
        int[] arr = {10, 7, 8, 9, 1, 5, 3};
        System.out.println("Before: " + Arrays.toString(arr));
        quickSort(arr, 0, arr.length - 1);
        System.out.println("After:  " + Arrays.toString(arr));
    }
}
▶ Output
Before: [10, 7, 8, 9, 1, 5, 3] After: [1, 3, 5, 7, 8, 9, 10]
09

Searching Algorithms

Linear Search · Binary Search (Iterative + Recursive) · Two Pointer · Kadane's

📖 Theory

Linear Search vs Binary Search — Kab Kya?

Linear Search — O(n): Har element check karo ek ek karke. Unsorted array mein bhi kaam karta hai. Worst case: poora array traverse. Small arrays ke liye theek hai.

Binary Search — O(log n): Sirf sorted array mein kaam karta hai. Middle element check karo. Target chhhota → left half. Target bada → right half. 1 million elements mein sirf ~20 comparisons! Agar data sorted hai, hamesha binary search use karo.

Rule of thumb: n < 100: linear. n > 100 aur sorted: binary. n > 100 unsorted: sort karo phir binary (n log n + log n) — zyada searches karni ho to worth it hai.

EX 9.1

Binary Search — Iterative + Recursive + Built-in

Overflow-safe mid calculation, negative return value ka matlab, insert position — sab samjho.
import java.util.Arrays;

public class BinarySearch {

    // Iterative — PREFERRED (no stack overhead)
    static int binarySearchIter(int[] arr, int target) {
        int low = 0, high = arr.length - 1;
        while (low <= high) {
            int mid = low + (high - low) / 2;  // (low+high)/2 → overflow risk!
            if      (arr[mid] == target) return mid;     // found!
            else if (arr[mid] <  target) low  = mid + 1;  // right half
            else                         high = mid - 1;  // left half
        }
        return -1;  // not found
    }

    // Recursive version
    static int binarySearchRec(int[] arr, int low, int high, int target) {
        if (low > high) return -1;  // base case: not found
        int mid = low + (high - low) / 2;
        if      (arr[mid] == target) return mid;
        else if (arr[mid] < target)  return binarySearchRec(arr, mid + 1, high, target);
        else                          return binarySearchRec(arr, low, mid - 1, target);
    }

    public static void main(String[] args) {
        int[] arr = {2, 5, 8, 12, 16, 23, 38, 56, 72, 91};
        System.out.println("Array: " + Arrays.toString(arr));

        System.out.println("Search 23 (iterative): index "
            + binarySearchIter(arr, 23));
        System.out.println("Search 91 (recursive): index "
            + binarySearchRec(arr, 0, arr.length-1, 91));
        System.out.println("Search 99 (not found): index "
            + binarySearchIter(arr, 99));

        // Arrays.binarySearch() — negative return = insertion point
        System.out.println("\nArrays.binarySearch(38): " + Arrays.binarySearch(arr, 38));

        int result = Arrays.binarySearch(arr, 20);
        System.out.println("Arrays.binarySearch(20): " + result);
        System.out.println("  → Not found. Insert at index: " + (-result - 1));
        // Negative result = -(insertion_point) - 1
        // -result - 1 = insertion point where 20 should go
    }
}
▶ Output
Array: [2, 5, 8, 12, 16, 23, 38, 56, 72, 91] Search 23 (iterative): index 5 Search 91 (recursive): index 9 Search 99 (not found): index -1 Arrays.binarySearch(38): 6 Arrays.binarySearch(20): -6 → Not found. Insert at index: 5
EX 9.2

Two Pointer — Pair Sum, Three Sum, Reverse

Two pointers O(n) — sorted array pe pairs dhundho. Classic pattern jo bahut saari problems solve karta hai.
import java.util.Arrays;

public class TwoPointer {

    static void twoSum(int[] sorted, int target) {
        int left = 0, right = sorted.length - 1;
        System.out.println("Pairs summing to " + target + "  (Two Pointer O(n)):");
        while (left < right) {
            int sum = sorted[left] + sorted[right];
            if      (sum == target) { System.out.println("  "+sorted[left]+" + "+sorted[right]); left++; right--; }
            else if (sum < target)  left++;
            else                    right--;
        }
    }

    static int[] reverseArray(int[] arr) {
        int[] copy = arr.clone();
        int l = 0, r = copy.length - 1;
        while (l < r) {
            int t = copy[l]; copy[l] = copy[r]; copy[r] = t;
            l++; r--;
        }
        return copy;
    }

    static int maxWater(int[] heights) {
        // Container with most water — LeetCode classic
        int left = 0, right = heights.length - 1, maxWater = 0;
        while (left < right) {
            int water = Math.min(heights[left], heights[right]) * (right - left);
            maxWater = Math.max(maxWater, water);
            if (heights[left] < heights[right]) left++;
            else right--;
        }
        return maxWater;
    }

    public static void main(String[] args) {
        twoSum(new int[]{1, 3, 5, 7, 9, 11, 13}, 14);

        System.out.println("\nReverse: "
            + Arrays.toString(reverseArray(new int[]{1,2,3,4,5})));

        System.out.println("Max Water: "
            + maxWater(new int[]{1,8,6,2,5,4,8,3,7}));
    }
}
▶ Output
Pairs summing to 14 (Two Pointer O(n)): 1 + 13 3 + 11 5 + 9 Reverse: [5, 4, 3, 2, 1] Max Water: 49
EX 9.3

Kadane's Algorithm — Maximum Subarray Sum

O(n) mein maximum subarray sum — dynamic programming ka simplest example. Negative numbers bhi handle hote hain.
public class KadanesAlgorithm {
    public static void main(String[] args) {
        int[] arr = {-2, 1, -3, 4, -1, 2, 1, -5, 4};

        // Kadane's — O(n), O(1) space
        // Idea: har point pe decide karo — naya subarray start karo
        //       ya existing mein extend karo
        int maxSoFar    = arr[0];
        int maxEndingHere = arr[0];
        int start = 0, end = 0, tempStart = 0;

        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > maxEndingHere + arr[i]) {
                maxEndingHere = arr[i];   // naya subarray yahan se
                tempStart = i;
            } else {
                maxEndingHere += arr[i];  // extend karo
            }

            if (maxEndingHere > maxSoFar) {
                maxSoFar = maxEndingHere;
                start = tempStart;
                end = i;
            }
        }

        System.out.println("Max Subarray Sum: " + maxSoFar);
        System.out.print("Subarray:         [");
        for (int i = start; i <= end; i++)
            System.out.print(arr[i] + (i == end ? "]" : ", "));
        System.out.println(" → indices [" + start + ", " + end + "]");

        // All negative test
        int[] allNeg = {-5, -3, -8, -2, -9};
        int maxNeg = allNeg[0];
        for (int n : allNeg) if (n > maxNeg) maxNeg = n;
        System.out.println("\nAll negative array max: " + maxNeg + " (single element)");
    }
}
▶ Output
Max Subarray Sum: 6 Subarray: [4, -1, 2, 1] → indices [3, 6] All negative array max: -2 (single element)
10

Array vs ArrayList

Dynamic Sizing · Generics · Collections Framework · Conversion

📖 Theory — Dono Ka Difference

Array aur ArrayList — Internal Working

Array: Fixed-size, primitive types support, faster (no wrapper/generics overhead), kum memory. Compile time pe size pata ho tab use karo.

ArrayList: Internally bhi ek array use karta hai (Object[])! Jab full ho jaata hai, naya array banata hai 1.5x size ka aur sab elements copy karta hai (amortized O(1) add). Dynamic size, generics support, add/remove convenience methods, null support.

Backend REST APIs, Spring Boot mein zyada tar ArrayList use hota hai — kyunki response ka size pehle se pata nahi hota. Arrays specific size ke liye, ya performance critical loops ke liye.

FeatureArrayArrayList
SizeFixed at creationDynamic (auto-resize 1.5x)
Primitivesint, double directlyInteger, Double (autoboxing)
Accessarr[i]list.get(i)
Length/Sizearr.lengthlist.size()
Add anywhereManual shift neededlist.add(i, elem)
RemoveManual shiftlist.remove(i)
Generics❌ Not supportedArrayList<String>
PerformanceFaster, less memorySlight overhead (boxing)
Multi-dimensionalint[][]ArrayList<ArrayList<Integer>>
EX 10.1

ArrayList — Complete Operations

add, remove, get, set, contains, sort, size, clear — sab ye spring boot APIs mein daily use hote hain.
import java.util.*;

public class ArrayListOps {
    public static void main(String[] args) {

        // ── Create ──
        ArrayList<Integer> list = new ArrayList<>();

        // ── Add ──
        list.add(30); list.add(10); list.add(50);
        list.add(20); list.add(40);
        System.out.println("After add:         " + list);

        list.add(2, 99);  // specific index pe insert
        System.out.println("After add(2,99):   " + list);

        // ── Get, Set ──
        System.out.println("get(0):            " + list.get(0));
        list.set(0, 100);
        System.out.println("After set(0,100):  " + list);

        // ── Remove by index vs Remove by value ──
        list.remove(5);              // index 5 remove karo
        list.remove(Integer.valueOf(99));  // value 99 remove karo (Integer wrap)
        System.out.println("After removes:     " + list);

        // ── Search ──
        System.out.println("contains(50):      " + list.contains(50));
        System.out.println("indexOf(50):       " + list.indexOf(50));
        System.out.println("size():            " + list.size());

        // ── Sort ──
        Collections.sort(list);
        System.out.println("Sorted:            " + list);
        list.sort(Comparator.reverseOrder());
        System.out.println("Sorted desc:       " + list);

        // ── Array → ArrayList ──
        String[] arr = {"Java", "Python", "Go", "Rust"};
        List<String> langs = new ArrayList<>(Arrays.asList(arr));
        langs.add("Kotlin");
        System.out.println("\nLangs list: " + langs);

        // ── ArrayList → Array ──
        String[] backToArr = langs.toArray(new String[0]);
        System.out.println("Back to array: " + Arrays.toString(backToArr));

        // ── Iterate ──
        System.out.print("Iterator: ");
        Iterator<String> it = langs.iterator();
        while (it.hasNext()) System.out.print(it.next() + " ");
    }
}
▶ Output
After add: [30, 10, 50, 20, 40] After add(2,99): [30, 10, 99, 50, 20, 40] get(0): 30 After set(0,100): [100, 10, 99, 50, 20, 40] After removes: [100, 10, 50, 20] contains(50): true indexOf(50): 2 size(): 4 Sorted: [10, 20, 50, 100] Sorted desc: [100, 50, 20, 10] Langs list: [Java, Python, Go, Rust, Kotlin] Back to array: [Java, Python, Go, Rust, Kotlin] Iterator: Java Python Go Rust Kotlin
11

Practice Programs

Topic-wise 4-5 Problems Each · Click to See Solution

📝

Set A — Basic Operations (Traversal + Math)

Array creation, stats, manipulation — fundamentals solid karo

1
Array ka Sum, Average, Product nikalo Ek int array diya hai. Uska sum, average (2 decimal), aur product nikalo. Long use karo overflow ke liye.
MathTraversal
Sum + Average (double cast) + Product (long for overflow)
public class P1_SumAvgProduct {
    public static void main(String[] args) {
        int[] arr = {3, 6, 4, 8, 5, 2, 9, 1};
        long sum = 0, product = 1;

        for (int n : arr) { sum += n; product *= n; }

        System.out.println("Sum:     " + sum);
        System.out.printf( "Average: %.2f%n", (double) sum / arr.length);
        System.out.println("Product: " + product);
    }
}
▶ Output
Sum: 38 Average: 4.75 Product: 155520
2
Array Reverse Karo — In-place, Extra array mat use karo Two-pointer use karke original array ko reverse karo. O(n) time, O(1) space.
Two PointerIn-place
Left-right pointers, temp variable se swap
import java.util.Arrays;
public class P2_InplaceReverse {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8};
        System.out.println("Before: " + Arrays.toString(arr));

        int left = 0, right = arr.length - 1;
        while (left < right) {
            int temp = arr[left];
            arr[left]  = arr[right];
            arr[right] = temp;
            left++;
            right--;
        }
        System.out.println("After:  " + Arrays.toString(arr));
    }
}
▶ Output
Before: [1, 2, 3, 4, 5, 6, 7, 8] After: [8, 7, 6, 5, 4, 3, 2, 1]
3
Duplicates Dhundo — Frequency Array se Array mein jo elements ek se zyada baar aaye, unhe count ke saath print karo. Values 0-99 assume karo.
Frequency ArrayCounting
int[100] frequency array — index = value, value = count
public class P3_FindDuplicates {
    public static void main(String[] args) {
        int[] arr = {1, 3, 4, 2, 2, 3, 7, 8, 4, 1, 5, 5, 5};
        int[] freq = new int[100]; // default = 0

        for (int n : arr) freq[n]++;

        System.out.println("Duplicate elements:");
        for (int i = 0; i < 100; i++)
            if (freq[i] > 1)
                System.out.println("  " + i + " → " + freq[i] + " times");
    }
}
▶ Output
Duplicate elements: 1 → 2 times 2 → 2 times 3 → 2 times 4 → 2 times 5 → 3 times
4
Second Largest aur Second Smallest Nikalo Bina sorting ke O(n) mein second largest aur second smallest dhundo. Duplicate handle karo.
O(n)Tracking
4 variables: first/secondLarge, first/secondSmall — single pass
public class P4_SecondLargeSmall {
    public static void main(String[] args) {
        int[] arr = {12, 35, 1, 10, 34, 1, 99, 34, 35};

        int large1 = Integer.MIN_VALUE, large2 = Integer.MIN_VALUE;
        int small1 = Integer.MAX_VALUE, small2 = Integer.MAX_VALUE;

        for (int n : arr) {
            // Largest track
            if      (n > large1) { large2 = large1; large1 = n; }
            else if (n > large2 && n != large1) large2 = n;

            // Smallest track
            if      (n < small1) { small2 = small1; small1 = n; }
            else if (n < small2 && n != small1) small2 = n;
        }
        System.out.println("Largest: " + large1 + ", Second: " + large2);
        System.out.println("Smallest: " + small1 + ", Second: " + small2);
    }
}
▶ Output
Largest: 99, Second: 35 Smallest: 1, Second: 10
5
Missing Number — 1 to N Mein Se Ek Missing 1 se N tak ke numbers mein se ek missing hai. Sum formula use karo — O(n), O(1). XOR approach bhi sikh lo.
Math TrickO(n) O(1)
Formula: Expected sum = n*(n+1)/2. Actual sum se subtract karo.
public class P5_MissingNumber {
    public static void main(String[] args) {
        int[] arr = {1, 2, 4, 6, 3, 7, 8};  // 1 to 8, 5 missing
        int n = arr.length + 1;  // total count (1 to n)

        // Method 1: Sum formula
        long expected = (long) n * (n + 1) / 2;
        long actual = 0;
        for (int num : arr) actual += num;
        System.out.println("Missing (Sum method): " + (expected - actual));

        // Method 2: XOR — handles overflow better
        int xor = 0;
        for (int i = 1; i <= n; i++) xor ^= i;  // XOR 1 to n
        for (int num : arr)         xor ^= num;  // XOR actual values
        System.out.println("Missing (XOR method): " + xor);
        // Same numbers cancel out (a^a=0), missing number remains
    }
}
▶ Output
Missing (Sum method): 5 Missing (XOR method): 5
🧩

Set B — Sorting & Searching

Algorithms ko code karo, binary search patterns

6
Count Occurrences — Sorted Array Mein Binary Search Sorted array mein koi element kitni baar aaya — first occurrence aur last occurrence binary search se nikalo.
Binary SearchO(log n)
First + Last occurrence binary search → count = last - first + 1
import java.util.Arrays;
public class P6_CountOccurrence {

    static int firstOcc(int[] arr, int target) {
        int lo = 0, hi = arr.length - 1, result = -1;
        while (lo <= hi) {
            int mid = lo + (hi - lo) / 2;
            if      (arr[mid] == target) { result = mid; hi = mid - 1; }  // keep going left
            else if (arr[mid] < target)   lo = mid + 1;
            else                          hi = mid - 1;
        }
        return result;
    }

    static int lastOcc(int[] arr, int target) {
        int lo = 0, hi = arr.length - 1, result = -1;
        while (lo <= hi) {
            int mid = lo + (hi - lo) / 2;
            if      (arr[mid] == target) { result = mid; lo = mid + 1; }  // keep going right
            else if (arr[mid] < target)   lo = mid + 1;
            else                          hi = mid - 1;
        }
        return result;
    }

    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 3, 3, 3, 4, 5, 5, 6};
        System.out.println("Array: " + Arrays.toString(arr));
        int target = 3;
        int first = firstOcc(arr, target), last = lastOcc(arr, target);
        System.out.println("First occ of " + target + ": " + first);
        System.out.println("Last  occ of " + target + ": " + last);
        System.out.println("Count: " + (first == -1 ? 0 : last - first + 1));
    }
}
▶ Output
Array: [1, 2, 3, 3, 3, 3, 4, 5, 5, 6] First occ of 3: 2 Last occ of 3: 5 Count: 4
7
Move All Zeros to End Array mein sab zeros ko end mein le jao, order maintain karo non-zero elements ka. Extra space mat use karo.
Two PointerIn-place
Write pointer se non-zeros pehle shift karo, phir zeros fill karo
import java.util.Arrays;
public class P7_MoveZeros {
    public static void main(String[] args) {
        int[] arr = {0, 1, 0, 3, 12, 0, 5, 8, 0};
        System.out.println("Before: " + Arrays.toString(arr));

        int writeIdx = 0;
        // Non-zeros ko front pe shift karo
        for (int n : arr) if (n != 0) arr[writeIdx++] = n;
        // Remaining positions zeros se fill karo
        while (writeIdx < arr.length) arr[writeIdx++] = 0;

        System.out.println("After:  " + Arrays.toString(arr));
    }
}
▶ Output
Before: [0, 1, 0, 3, 12, 0, 5, 8, 0] After: [1, 3, 12, 5, 8, 0, 0, 0, 0]
8
Leaders in an Array Ek element "leader" hai agar uske right mein sab elements usse chhote hain. Last element hamesha leader hai. O(n) solution.
Right-to-LeftO(n)
Right se traverse karo, max track karo — agar current > max, ye leader hai
import java.util.*;
public class P8_Leaders {
    public static void main(String[] args) {
        int[] arr = {16, 17, 4, 3, 5, 2};
        List<Integer> leaders = new ArrayList<>();

        int maxRight = Integer.MIN_VALUE;
        // Right to left traverse — O(n)
        for (int i = arr.length - 1; i >= 0; i--) {
            if (arr[i] > maxRight) {
                leaders.add(0, arr[i]);  // front pe add (original order)
                maxRight = arr[i];
            }
        }
        System.out.println("Array:   " + Arrays.toString(arr));
        System.out.println("Leaders: " + leaders);
    }
}
▶ Output
Array: [16, 17, 4, 3, 5, 2] Leaders: [17, 5, 2]
9
Sort Array of 0s, 1s, 2s — Dutch National Flag Array sirf 0, 1, 2 se bana hai. Bina library sort ke O(n) mein sort karo. Dutch National Flag Algorithm use karo.
Interview ClassicO(n) O(1)
3 pointers: low (0s end), mid (current), high (2s start)
import java.util.Arrays;
public class P9_DutchFlag {
    static void swap(int[] arr, int i, int j) {
        int t = arr[i]; arr[i] = arr[j]; arr[j] = t;
    }

    public static void main(String[] args) {
        int[] arr = {0, 1, 2, 0, 1, 2, 1, 0, 2, 1};
        System.out.println("Before: " + Arrays.toString(arr));

        int low = 0, mid = 0, high = arr.length - 1;
        while (mid <= high) {
            if      (arr[mid] == 0) { swap(arr, low++, mid++); }
            else if (arr[mid] == 1) { mid++; }
            else                    { swap(arr, mid, high--); }
        }
        System.out.println("After:  " + Arrays.toString(arr));
    }
}
▶ Output
Before: [0, 1, 2, 0, 1, 2, 1, 0, 2, 1] After: [0, 0, 0, 1, 1, 1, 1, 2, 2, 2]
🎯

Set C — 2D Arrays + Real-World

Matrix problems aur practical backend scenarios

10
Matrix ko Spiral Order Mein Print Karo 2D matrix ko clockwise spiral order mein print karo — Amazon, Microsoft interview common question.
Interview2D Array
4 boundaries: top, bottom, left, right — shrink karte jao
public class P10_SpiralMatrix {
    public static void main(String[] args) {
        int[][] mat = {
            {1,  2,  3,  4},
            {5,  6,  7,  8},
            {9,  10, 11, 12},
            {13, 14, 15, 16}
        };
        System.out.print("Spiral: ");
        int top = 0, bottom = mat.length - 1;
        int left = 0, right = mat[0].length - 1;

        while (top <= bottom && left <= right) {
            for (int i = left;  i <= right;  i++) System.out.print(mat[top][i]     + " "); top++;
            for (int i = top;   i <= bottom; i++) System.out.print(mat[i][right]    + " "); right--;
            if (top <= bottom) {
                for (int i = right; i >= left; i--) System.out.print(mat[bottom][i]  + " "); bottom--;
            }
            if (left <= right) {
                for (int i = bottom; i >= top; i--) System.out.print(mat[i][left]    + " "); left++;
            }
        }
    }
}
▶ Output
Spiral: 1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10
11
Two Sum — Target Pairs (Multiple Approaches) Array mein do elements dhundo jinka sum target ke barabar ho. O(n²) brute force aur O(n) HashMap approach dono.
LeetCode #1HashMapO(n)
Brute: nested loops O(n²). Efficient: HashMap complement store karo O(n).
import java.util.*;
public class P11_TwoSum {

    // O(n²) Brute Force
    static void bruteForce(int[] arr, int target) {
        System.out.println("Brute Force O(n²):");
        for (int i = 0; i < arr.length - 1; i++)
            for (int j = i + 1; j < arr.length; j++)
                if (arr[i] + arr[j] == target)
                    System.out.println("  [" + i + "," + j + "] = " + arr[i] + "+" + arr[j]);
    }

    // O(n) HashMap approach — single pass
    static void hashMapApproach(int[] arr, int target) {
        System.out.println("HashMap O(n):");
        Map<Integer, Integer> seen = new HashMap<>();  // value → index
        for (int i = 0; i < arr.length; i++) {
            int complement = target - arr[i];
            if (seen.containsKey(complement))
                System.out.println("  [" + seen.get(complement) + "," + i + "] = "
                    + complement + "+" + arr[i]);
            seen.put(arr[i], i);
        }
    }

    public static void main(String[] args) {
        int[] arr = {2, 7, 11, 15, 3, 8};
        int target = 10;
        System.out.println("Array: " + Arrays.toString(arr) + " Target: " + target);
        bruteForce(arr, target);
        hashMapApproach(arr, target);
    }
}
▶ Output
Array: [2, 7, 11, 15, 3, 8] Target: 10 Brute Force O(n²): [0,5] = 2+8 [4,1] = 3+7 HashMap O(n): [0,5] = 2+8 [1,4] = 7+3
12
Student Grade System — Complete Report Students ke marks se grade calculate karo, pass/fail decide karo, class stats nikalo, report format mein print karo.
Real-WorldBackend Logic
Grade logic + stats + formatted table print
public class P12_GradeSystem {

    static String grade(int m) {
        if      (m >= 90) return "A+";
        else if (m >= 80) return "A";
        else if (m >= 70) return "B";
        else if (m >= 60) return "C";
        else if (m >= 45) return "D";
        else              return "F";
    }

    public static void main(String[] args) {
        String[] names = {"Rahul", "Priya", "Amit", "Sneha", "Rohan"};
        int[]    marks = {  85,      94,      43,     72,       58 };

        System.out.println("╔════════════════════════════════════╗");
        System.out.println("║      STUDENT RESULT REPORT         ║");
        System.out.println("╠════════════════════════════════════╣");
        System.out.printf ("║ %-8s %5s %5s %7s       ║%n","Name","Marks","Grade","Status");
        System.out.println("╠════════════════════════════════════╣");

        int sum = 0, topIdx = 0, passCount = 0;
        for (int i = 0; i < names.length; i++) {
            sum += marks[i];
            if (marks[i] > marks[topIdx]) topIdx = i;
            boolean pass = marks[i] >= 45;
            if (pass) passCount++;
            System.out.printf("║ %-8s %5d %5s %7s       ║%n",
                names[i], marks[i], grade(marks[i]), pass ? "PASS ✓" : "FAIL ✗");
        }
        System.out.println("╠════════════════════════════════════╣");
        System.out.printf ("║ Average: %5.1f  Pass: %d  Fail: %d        ║%n",
            (double) sum / names.length, passCount, names.length - passCount);
        System.out.printf ("║ Topper: %-27s ║%n",
            names[topIdx] + " (" + marks[topIdx] + ")");
        System.out.println("╚════════════════════════════════════╝");
    }
}
▶ Output
╔════════════════════════════════════╗ ║ STUDENT RESULT REPORT ║ ╠════════════════════════════════════╣ ║ Name Marks Grade Status ║ ╠════════════════════════════════════╣ ║ Rahul 85 B PASS ✓ ║ ║ Priya 94 A+ PASS ✓ ║ ║ Amit 43 F FAIL ✗ ║ ║ Sneha 72 B PASS ✓ ║ ║ Rohan 58 C PASS ✓ ║ ╠════════════════════════════════════╣ ║ Average: 70.4 Pass: 4 Fail: 1 ║ ║ Topper: Priya (94) ║ ╚════════════════════════════════════╝

⚠️ Common Mistakes — Inhe Hamesha Avoid Karo

ArrayIndexOutOfBoundsException: arr[arr.length] access karna. Valid range: 0 to arr.length - 1. Loop mein galti: i <= arr.length ki jagah i < arr.length likho.
Shallow Copy Trap: int[] b = a; — ye copy nahi, ye same array hai! b[0] = 99 karne se a[0] bhi 99 ho jaata hai. Deep copy ke liye Arrays.copyOf(a, a.length) use karo.
⚠️
Direct Array Print: System.out.println(arr)[I@1b6d3586 (memory address, values nahi!). Hamesha Arrays.toString(arr) ya Arrays.deepToString(arr) use karo.
⚠️
NullPointerException: String[] arr = new String[5]; ke baad arr[0].length()arr[0] null hai by default! Hamesha if (arr[i] != null) check karo String arrays mein.
💡
Binary Search Overflow: mid = (low + high) / 2 mat use karo — large arrays mein integer overflow ho sakta hai. Safe version: mid = low + (high - low) / 2.
for-each se Modification Nahi Hoti: for (int n : arr) { n = n * 2; }arr unchanged rahega! Primitive arrays ko modify karne ke liye hamesha index-based for loop use karo: for (int i = 0; i < arr.length; i++) arr[i] *= 2;
🎯
Arrays.sort() vs Custom Sort: Production mein hamesha Arrays.sort() use karo — ye dual-pivot quicksort hai, highly optimized. Custom algorithms sirf interview preparation aur special cases ke liye. For objects: Arrays.sort(arr, Comparator.comparingInt(...)).