Skip to main content
Advanced Array Optimization & SIMD Computing - Enterprise Performance Engineering
  1. Resources/
  2. Study Materials/
  3. Information & Communication Technology Engineering/
  4. ICT Semester 4/
  5. Java Programming (4343203)/
  6. Java Programming Slidev Presentations/

Advanced Array Optimization & SIMD Computing - Enterprise Performance Engineering

·
Milav Dabgar
Author
Milav Dabgar
Experienced lecturer in the electrical and electronic manufacturing industry. Skilled in Embedded Systems, Image Processing, Data Science, MATLAB, Python, STM32. Strong education professional with a Master’s degree in Communication Systems Engineering from L.D. College of Engineering - Ahmedabad.
Table of Contents

Advanced Array Optimization & SIMD Computing
#

Enterprise Performance Engineering & Parallel Processing
#

Lecture 5 - Scientific Computing Standards
#

Java Programming (4343203)
Diploma in ICT - Semester IV
Gujarat Technological University

๐Ÿข Industry Focus: Quantitative Research & Scientific Computing
๐Ÿ’ฐ Career Impact: $250K-600K Performance Engineering Roles
๐ŸŽฏ Specialization: SIMD Vectorization & Parallel Array Processing

Master Enterprise Array Optimization

layout: default
#

Elite Array Optimization Mastery Objectives
#

Transform Into a High-Performance Computing Architect
#

**Mission:** Architect SIMD-optimized array systems processing 1TB+ datasets in real-time
  • ๐Ÿง  MASTER SIMD vectorization achieving 16x performance gains using Intel AVX-512 and ARM NEON instructions for quantitative financial modeling
  • โšก OPTIMIZE cache-conscious array layouts eliminating memory bottlenecks in systems processing 100M+ market data points per second
  • ๐Ÿ”ฌ ENGINEER lock-free parallel array algorithms enabling D.E. Shaw’s machine learning platforms to analyze $60B+ in assets simultaneously
  • ๐Ÿ’Ž IMPLEMENT zero-copy array transformations and streaming processing architectures for Renaissance Technologies’ real-time alpha generation
  • ๐ŸŽฏ ARCHITECT distributed array computing frameworks supporting Google DeepMind’s neural network training on exascale supercomputers
  • ๐Ÿš€ DESIGN GPU-accelerated array operations using CUDA cores for Two Sigma’s quantitative research processing 500TB+ daily datasets
  • ๐Ÿ’ฐ DEPLOY enterprise-grade array optimization generating $10M+ annual performance improvements for algorithmic trading strategies
๐Ÿ† SIMD COMPUTING MASTERY ACHIEVED
Ready to architect exascale array processing systems!

layout: center
#

Type Conversion Overview
#

graph TD
    A[Type Conversion] --> B[Implicit Conversion<br/>Widening]
    A --> C[Explicit Conversion<br/>Narrowing]
    
    B --> D[Automatic<br/>Safe Conversion]
    B --> E[byte โ†’ short โ†’ int โ†’ long<br/>float โ†’ double]
    
    C --> F[Manual Casting<br/>May Lose Data]
    C --> G[long โ†’ int โ†’ short โ†’ byte<br/>double โ†’ float]
    
    style B fill:#e8f5e8
    style C fill:#ffebee
    style D fill:#e3f2fd
    style F fill:#fff3e0

โœ… Implicit (Safe)

Smaller to larger data types

No data loss occurs

โš ๏ธ Explicit (Risky)

Larger to smaller data types

Potential data loss


layout: default
#

Implicit Type Conversion (Widening)
#

๐Ÿ“ˆ Conversion Hierarchy
#

byte โ†’ short โ†’ int โ†’ long โ†’ float โ†’ double
         โ†“
       char โ†’ int

โœ… Safe Conversions
#

// Implicit conversion examples
byte b = 10;
short s = b;        // byte to short
int i = s;          // short to int  
long l = i;         // int to long
float f = l;        // long to float
double d = f;       // float to double

// Character conversion
char c = 'A';       // ASCII value 65
int ascii = c;      // char to int (65)

// Mixed operations
int x = 5;
double y = 2.5;
double result = x + y;  // x promoted to double

๐ŸŽฏ Rules for Implicit Conversion
#

  1. No data loss occurs
  2. Smaller to larger types only
  3. Automatic by compiler
  4. In expressions, smaller types promoted

๐Ÿ“Š Expression Promotion
#

byte a = 10;
byte b = 20;
// byte c = a + b;     // Error! 
int c = a + b;         // Correct

Why? Arithmetic operations promote byte and short to int!


layout: default
#

Explicit Type Conversion (Narrowing)
#

โš ๏ธ Manual Casting Syntax
#

// Basic casting syntax
(target_type) value

// Examples
double d = 9.78;
int i = (int) d;        // 9 (fractional part lost)

long l = 100L;
int x = (int) l;        // 100 (fits in int)

float f = 65.4f;
char c = (char) f;      // 'A' (ASCII 65)

// Complex expressions
double result = 10.5 * 3.2;
int finalValue = (int) (result + 0.5);  // Rounding

๐Ÿ” Data Loss Examples
#

// Potential data loss scenarios
int large = 300;
byte small = (byte) large;    // -44 (overflow!)

double precise = 123.456789;
float less = (float) precise; // 123.45679 (precision loss)

long bigNumber = 3000000000L;
int overflow = (int) bigNumber; // -1294967296 (overflow!)

// Character conversions
int ascii = 65;
char letter = (char) ascii;   // 'A'

char symbol = 'A';
int code = (int) symbol;      // 65
โš ๏ธ Warning: Always check ranges to avoid overflow!

layout: default
#

Type Conversion Best Practices
#

โœ… Good Practices
#

// 1. Check ranges before casting
long bigValue = 1500L;
if (bigValue <= Integer.MAX_VALUE) {
    int safeValue = (int) bigValue;
}

// 2. Use appropriate wrapper methods
String numberStr = "123";
int number = Integer.parseInt(numberStr);

// 3. Handle precision loss consciously
double price = 99.99;
int rupees = (int) Math.round(price);  // Round first

// 4. Use constants for readability
public static final double CONVERSION_RATE = 83.5;
double dollars = 100.0;
int rupees = (int) (dollars * CONVERSION_RATE);

โŒ Common Mistakes
#

// 1. Ignoring overflow
int result = 2000000000 + 2000000000;  // Overflow!

// 2. Unnecessary casting
double d = 5.0;
int i = (int) 5;  // Should be: int i = 5;

// 3. Loss of precision without consideration
double precise = 123.456789;
int rough = (int) precise;  // 123, but no rounding

// 4. Mixing types carelessly
byte a = 10;
byte b = 20;
byte sum = a + b;  // Compilation error!
๐Ÿ’ก Tip: Always be explicit about your intentions with type conversion!

layout: center
#

Introduction to Arrays
#

What is an Array? ๐Ÿ“Š

A collection of elements of the same data type stored in contiguous memory locations

graph LR
    A[Array: ages] --> B[Index 0<br/>20]
    A --> C[Index 1<br/>21]
    A --> D[Index 2<br/>19]
    A --> E[Index 3<br/>22]
    A --> F[Index 4<br/>20]
    
    style A fill:#e3f2fd
    style B fill:#e8f5e8
    style C fill:#e8f5e8
    style D fill:#e8f5e8
    style E fill:#e8f5e8
    style F fill:#e8f5e8

๐ŸŽฏ Fixed Size

Size determined at creation

๐Ÿ“ Indexed Access

Access elements by index (0-based)

๐Ÿ”„ Same Type

All elements same data type


layout: default
#

One-Dimensional Arrays
#

๐Ÿ“ Declaration and Creation
#

// Method 1: Declaration then creation
int[] ages;                    // Declaration
ages = new int[5];            // Creation

// Method 2: Combined declaration and creation
int[] scores = new int[10];

// Method 3: Declaration with initialization
int[] numbers = {10, 20, 30, 40, 50};

// Method 4: Alternative syntax
int marks[] = new int[]{85, 90, 78, 92, 88};

// Different data types
String[] names = {"Alice", "Bob", "Charlie"};
double[] prices = {99.99, 149.50, 75.25};
boolean[] flags = {true, false, true, false};

๐Ÿ” Array Properties
#

int[] numbers = {10, 20, 30, 40, 50};

// Array length
int size = numbers.length;  // 5 (property, not method)

// Accessing elements
int first = numbers[0];     // 10 (first element)
int last = numbers[4];      // 50 (last element)

// Modifying elements
numbers[2] = 35;           // Change 30 to 35

// Array bounds
// int invalid = numbers[5];  // Runtime error!
// numbers[-1] = 10;          // Runtime error!
โš ๏ธ Important: Array index out of bounds throws `ArrayIndexOutOfBoundsException`!

layout: default
#

Array Operations and Examples
#

๐Ÿ”„ Common Array Operations
#

// 1. Initialize array with values
int[] marks = new int[5];
for (int i = 0; i < marks.length; i++) {
    marks[i] = (i + 1) * 10;  // 10, 20, 30, 40, 50
}

// 2. Display array elements
System.out.println("Student Marks:");
for (int i = 0; i < marks.length; i++) {
    System.out.println("Student " + (i+1) + ": " + marks[i]);
}

// 3. Enhanced for loop (for-each)
for (int mark : marks) {
    System.out.println("Mark: " + mark);
}

// 4. Find sum and average
int sum = 0;
for (int mark : marks) {
    sum += mark;
}
double average = (double) sum / marks.length;

๐Ÿ” Searching and Finding
#

// Find maximum element
int[] numbers = {45, 23, 67, 12, 89, 34};
int max = numbers[0];
for (int i = 1; i < numbers.length; i++) {
    if (numbers[i] > max) {
        max = numbers[i];
    }
}

// Linear search
public static int linearSearch(int[] arr, int target) {
    for (int i = 0; i < arr.length; i++) {
        if (arr[i] == target) {
            return i;  // Return index
        }
    }
    return -1;  // Not found
}

// Count occurrences
public static int countOccurrences(int[] arr, int value) {
    int count = 0;
    for (int element : arr) {
        if (element == value) {
            count++;
        }
    }
    return count;
}

layout: default
#

Two-Dimensional Arrays
#

๐Ÿ“Š 2D Array Concept
#

Think of a 2D array as a table or matrix:

    Col 0  Col 1  Col 2
Row 0  [85]   [90]   [78]
Row 1  [92]   [88]   [95]
Row 2  [76]   [82]   [89]

๐Ÿ“ Declaration and Creation
#

// Method 1: Declaration then creation
int[][] matrix;
matrix = new int[3][4];  // 3 rows, 4 columns

// Method 2: Combined
int[][] scores = new int[5][3];

// Method 3: With initialization
int[][] marks = {
    {85, 90, 78},
    {92, 88, 95},
    {76, 82, 89}
};

// Method 4: Row by row
int[][] table = new int[2][];
table[0] = new int[]{1, 2, 3};
table[1] = new int[]{4, 5, 6, 7};  // Jagged array

๐Ÿ” Accessing 2D Arrays
#

int[][] marks = {
    {85, 90, 78},
    {92, 88, 95}, 
    {76, 82, 89}
};

// Access specific element
int firstStudentMath = marks[0][0];  // 85
int lastStudentScience = marks[2][2]; // 89

// Modify elements
marks[1][2] = 97;  // Change second student's third subject

// Array dimensions
int rows = marks.length;        // 3
int cols = marks[0].length;     // 3

// Display all elements
for (int i = 0; i < marks.length; i++) {
    for (int j = 0; j < marks[i].length; j++) {
        System.out.print(marks[i][j] + " ");
    }
    System.out.println();  // New line after each row
}

// Enhanced for loop
for (int[] row : marks) {
    for (int mark : row) {
        System.out.print(mark + " ");
    }
    System.out.println();
}

layout: default
#

Practical Array Examples
#

๐ŸŽ“ Student Grade Management System
#

public class StudentGrades {
    public static void main(String[] args) {
        // Student names
        String[] students = {"Alice", "Bob", "Charlie", "Diana", "Eve"};
        
        // Marks in 3 subjects: Math, Science, English
        int[][] marks = {
            {85, 90, 78},  // Alice
            {92, 88, 95},  // Bob
            {76, 82, 89},  // Charlie
            {88, 91, 85},  // Diana
            {79, 85, 92}   // Eve
        };
        
        // Calculate and display results
        System.out.println("Student Grade Report");
        System.out.println("=====================");
        
        for (int i = 0; i < students.length; i++) {
            int total = 0;
            System.out.print(students[i] + ": ");
            
            // Calculate total marks
            for (int j = 0; j < marks[i].length; j++) {
                total += marks[i][j];
                System.out.print(marks[i][j] + " ");
            }
            
            double average = (double) total / marks[i].length;
            char grade = calculateGrade(average);
            
            System.out.printf("| Total: %d | Avg: %.2f | Grade: %c%n", 
                             total, average, grade);
        }
    }
    
    public static char calculateGrade(double average) {
        if (average >= 90) return 'A';
        else if (average >= 80) return 'B';
        else if (average >= 70) return 'C';
        else if (average >= 60) return 'D';
        else return 'F';
    }
}

layout: default
#

Matrix Operations
#

โž• Matrix Addition
#

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

// Example usage
int[][] matrix1 = {{1, 2}, {3, 4}};
int[][] matrix2 = {{5, 6}, {7, 8}};
int[][] sum = addMatrices(matrix1, matrix2);
// Result: {{6, 8}, {10, 12}}

๐Ÿ”„ Matrix Transpose
#

public static int[][] transpose(int[][] matrix) {
    int rows = matrix.length;
    int cols = matrix[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] = matrix[i][j];
        }
    }
    return result;
}

๐Ÿ“Š Practical Example: 3x3 Matrix Addition
#

import java.util.Scanner;

public class MatrixAddition {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int[][] matrix1 = new int[3][3];
        int[][] matrix2 = new int[3][3];
        int[][] result = new int[3][3];
        
        // Input first matrix
        System.out.println("Enter first 3x3 matrix:");
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                matrix1[i][j] = sc.nextInt();
            }
        }
        
        // Input second matrix
        System.out.println("Enter second 3x3 matrix:");
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                matrix2[i][j] = sc.nextInt();
            }
        }
        
        // Add matrices
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                result[i][j] = matrix1[i][j] + matrix2[i][j];
            }
        }
        
        // Display result
        System.out.println("Sum of matrices:");
        displayMatrix(result);
    }
    
    public static void displayMatrix(int[][] matrix) {
        for (int[] row : matrix) {
            for (int element : row) {
                System.out.print(element + " ");
            }
            System.out.println();
        }
    }
}

layout: default
#

Array Common Mistakes and Solutions
#

โŒ Array Index Out of Bounds

```java int[] arr = new int[5]; arr[5] = 10; // Error! Valid indices: 0-4 ``` Solution: Always check: `index < array.length`

โŒ Null Pointer Exception

```java int[] arr = null; int len = arr.length; // NullPointerException! ``` Solution: Initialize array before use: `arr = new int[10];`

โŒ Confusion between length and length()

```java int[] arr = new int[5]; int len = arr.length(); // Error! No parentheses for arrays String str = "Hello"; int sLen = str.length(); // Correct! Strings use method ```

โŒ Modifying array during enhanced for loop

```java for (int element : arr) { element = element * 2; // Won't modify original array! } // Use regular for loop with index for modifications ```

layout: default
#

Practical Exercise
#

๐Ÿ› ๏ธ Hands-On Activities
#

Task 1: Write a program to reverse the digits of a number using arrays
Task 2: Create a program to add two 3x3 matrices and display the result
Task 3: Implement a student grade system that: - Stores marks for 5 students in 3 subjects - Calculates total and average for each student - Finds the highest scorer in each subject
Task 4: Write programs demonstrating type conversion: - Safe implicit conversions - Explicit casting with data loss examples

๐ŸŽฏ Expected Skills
#

  • Array declaration and initialization
  • Type conversion understanding
  • Matrix operations implementation
  • Proper error handling

layout: default
#

Performance Considerations
#

โšก Array Performance Tips
#

  • Access Speed: O(1) for index access
  • Memory: Contiguous allocation is cache-friendly
  • Size: Fixed size for better memory management
  • Initialization: Default values assigned automatically

๐Ÿ“Š Memory Layout
#

int[] arr = {10, 20, 30, 40, 50};
Memory Address: 1000  1004  1008  1012  1016
Values:         [10]  [20]  [30]  [40]  [50]
Index:           0     1     2     3     4

๐ŸŽฏ Best Practices
#

  • Bounds Checking: Always validate indices
  • Initialization: Initialize arrays before use
  • Enhanced For: Use for-each when not modifying
  • Size Planning: Estimate size requirements

๐Ÿ” Debugging Arrays
#

// Print array contents for debugging
int[] arr = {1, 2, 3, 4, 5};

// Method 1: Manual loop
for (int i = 0; i < arr.length; i++) {
    System.out.print(arr[i] + " ");
}

// Method 2: Arrays.toString()
System.out.println(Arrays.toString(arr));
// Output: [1, 2, 3, 4, 5]

layout: center class: text-center
#

Summary
#

๐Ÿ“– What We Learned

  • โ€ข Implicit and explicit type conversion
  • โ€ข Type casting and data loss scenarios
  • โ€ข One-dimensional array operations
  • โ€ข Two-dimensional arrays and matrices
  • โ€ข Common array mistakes and solutions

๐ŸŽฏ Next Steps

  • โ€ข Learn about operators in Java
  • โ€ข Practice with arithmetic operators
  • โ€ข Explore logical and relational operators
  • โ€ข Understand operator precedence
  • โ€ข Build complex expressions
Arrays and type conversion mastered! ๐ŸŽฏ๐Ÿ“Š

layout: default
#

Advanced Type Conversion Scenarios
#

๐Ÿ”„ Complex Type Conversion
#

// Mixed expression evaluation
public class TypePromotionDemo {
    public static void main(String[] args) {
        demonstratePromotionRules();
        demonstrateMethodOverloadingWithTypes();
        demonstratePrecisionLoss();
        demonstrateWrapperConversion();
    }
    
    private static void demonstratePromotionRules() {
        System.out.println("=== Expression Promotion Rules ===");
        
        // Rule 1: byte and short promoted to int in expressions
        byte b1 = 10, b2 = 20;
        // byte result = b1 + b2;  // Compilation error!
        int result = b1 + b2;      // Correct
        System.out.println("byte + byte = " + result + " (int)");
        
        // Rule 2: Mixed type promotion
        int i = 100;
        long l = 200L;
        float f = 3.14f;
        double d = 2.718;
        
        // Result types in mixed expressions
        long longResult = i + l;        // int + long = long
        float floatResult = i + f;      // int + float = float
        double doubleResult = l + d;    // long + double = double
        
        System.out.println("int + long = " + longResult + " (long)");
        System.out.println("int + float = " + floatResult + " (float)");
        System.out.println("long + double = " + doubleResult + " (double)");
        
        // Rule 3: char promotion
        char c1 = 'A', c2 = 'B';
        int charSum = c1 + c2;  // chars promoted to int
        System.out.println("'A' + 'B' = " + charSum + " (ASCII sum)");
    }
    
    private static void demonstrateMethodOverloadingWithTypes() {
        System.out.println("\n=== Method Overloading with Type Conversion ===");
        
        TypeConverter converter = new TypeConverter();
        
        // Automatic type promotion in method calls
        converter.process(10);        // Calls int version
        converter.process(10L);       // Calls long version
        converter.process(10.5f);     // Calls float version
        converter.process(10.5);      // Calls double version
        converter.process('A');       // Calls int version (char promoted)
    }
    
    static class TypeConverter {
        public void process(int value) {
            System.out.println("Processing int: " + value);
        }
        
        public void process(long value) {
            System.out.println("Processing long: " + value);
        }
        
        public void process(float value) {
            System.out.println("Processing float: " + value);
        }
        
        public void process(double value) {
            System.out.println("Processing double: " + value);
        }
    }
    
    private static void demonstratePrecisionLoss() {
        System.out.println("\n=== Precision Loss Analysis ===");
        
        // Float precision limits
        float largeFloat = 16777216f;  // 2^24
        float nextFloat = largeFloat + 1f;
        
        System.out.println("Large float: " + largeFloat);
        System.out.println("Large float + 1: " + nextFloat);
        System.out.println("Are they equal? " + (largeFloat == nextFloat));
        
        // Double to float precision loss
        double preciseValue = 1.23456789012345;
        float lessprecise = (float) preciseValue;
        
        System.out.println("Original double: " + preciseValue);
        System.out.println("Cast to float: " + lessprecise);
        System.out.println("Precision lost: " + (preciseValue - lessprecise));
        
        // Long to int overflow examples
        long[] testValues = {
            Integer.MAX_VALUE - 1,
            Integer.MAX_VALUE,
            Integer.MAX_VALUE + 1L,
            Integer.MIN_VALUE - 1L
        };
        
        System.out.println("\nLong to int conversion:");
        for (long value : testValues) {
            int converted = (int) value;
            System.out.println(value + " -> " + converted + 
                             (value != converted ? " (OVERFLOW!)" : ""));
        }
    }
    
    private static void demonstrateWrapperConversion() {
        System.out.println("\n=== Wrapper Type Conversion ===");
        
        // Autoboxing and unboxing
        Integer wrapper = 42;           // Autoboxing: int -> Integer
        int primitive = wrapper;        // Unboxing: Integer -> int
        
        System.out.println("Autoboxed: " + wrapper);
        System.out.println("Unboxed: " + primitive);
        
        // Wrapper to different primitive types
        Integer intWrapper = 65;
        Character charValue = (char) intWrapper.intValue();
        Double doubleValue = intWrapper.doubleValue();
        
        System.out.println("Integer 65 as char: " + charValue);
        System.out.println("Integer 65 as double: " + doubleValue);
        
        // String to number conversion
        String[] numberStrings = {"123", "45.67", "true", "invalid"};
        
        for (String str : numberStrings) {
            try {
                int intValue = Integer.parseInt(str);
                System.out.println("'" + str + "' -> int: " + intValue);
            } catch (NumberFormatException e) {
                System.out.println("'" + str + "' -> int: INVALID");
            }
            
            try {
                double doubleVal = Double.parseDouble(str);
                System.out.println("'" + str + "' -> double: " + doubleVal);
            } catch (NumberFormatException e) {
                System.out.println("'" + str + "' -> double: INVALID");
            }
        }
    }
}

โšก Performance Considerations
#

Type Conversion Costs:

  • Widening conversions: Nearly free
  • Narrowing conversions: Minimal cost
  • Wrapper conversions: Moderate cost
  • String parsing: Expensive

Optimization Tips:

// Prefer explicit types for clarity
double result = 10.0 / 3.0;  // Clear intention
// Over: double result = 10 / 3;  // Integer division!

// Cache frequently used wrapper objects
Integer cached = Integer.valueOf(100);  // Uses cache
Integer notCached = new Integer(100);   // Creates new object

// Use appropriate numeric types
int counter = 0;           // For loop counters
long timestamp = System.currentTimeMillis();
float coordinates = 10.5f; // For graphics/games
double precision = Math.PI; // For calculations

๐Ÿ” Debugging Type Issues
#

// Common debugging techniques
public class TypeDebugging {
    public static void main(String[] args) {
        // Check actual types at runtime
        Object[] values = {10, 10L, 10.0f, 10.0, '10'};
        
        for (Object value : values) {
            System.out.println(value + " is of type: " + 
                             value.getClass().getSimpleName());
        }
        
        // Range checking
        checkValueRange(Integer.MAX_VALUE + 1L);
        checkValueRange(Short.MIN_VALUE - 1);
        
        // Precision checking
        checkPrecision(1.0 / 3.0, 1f / 3f);
    }
    
    private static void checkValueRange(long value) {
        if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE) {
            System.out.println("WARNING: " + value + 
                             " is outside int range!");
        }
    }
    
    private static void checkPrecision(double d, float f) {
        System.out.println("Double: " + d);
        System.out.println("Float:  " + f);
        System.out.println("Difference: " + Math.abs(d - f));
    }
}

layout: default
#

Advanced Array Algorithms
#

๐Ÿ” Searching Algorithms
#

public class ArraySearching {
    public static void main(String[] args) {
        int[] numbers = {64, 34, 25, 12, 22, 11, 90, 5};
        
        demonstrateLinearSearch(numbers);
        demonstrateBinarySearch(numbers);
        demonstrateAdvancedSearching(numbers);
    }
    
    // Linear Search - O(n) time complexity
    public static int linearSearch(int[] arr, int target) {
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == target) {
                return i;
            }
        }
        return -1; // Not found
    }
    
    // Binary Search - O(log n) - requires sorted array
    public static int binarySearch(int[] arr, int target) {
        int left = 0, right = arr.length - 1;
        
        while (left <= right) {
            int mid = left + (right - left) / 2;
            
            if (arr[mid] == target) {
                return mid;
            } else if (arr[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return -1; // Not found
    }
    
    private static void demonstrateLinearSearch(int[] arr) {
        System.out.println("=== Linear Search ===");
        System.out.println("Array: " + Arrays.toString(arr));
        
        int target = 25;
        long startTime = System.nanoTime();
        int index = linearSearch(arr, target);
        long endTime = System.nanoTime();
        
        System.out.println("Searching for " + target + ": " + 
                          (index != -1 ? "Found at index " + index : "Not found"));
        System.out.println("Time: " + (endTime - startTime) + " ns");
    }
    
    private static void demonstrateBinarySearch(int[] arr) {
        System.out.println("\n=== Binary Search ===");
        
        // First, sort the array for binary search
        int[] sortedArr = arr.clone();
        Arrays.sort(sortedArr);
        System.out.println("Sorted array: " + Arrays.toString(sortedArr));
        
        int target = 25;
        long startTime = System.nanoTime();
        int index = binarySearch(sortedArr, target);
        long endTime = System.nanoTime();
        
        System.out.println("Searching for " + target + ": " + 
                          (index != -1 ? "Found at index " + index : "Not found"));
        System.out.println("Time: " + (endTime - startTime) + " ns");
        
        // Compare with built-in binary search
        int builtInIndex = Arrays.binarySearch(sortedArr, target);
        System.out.println("Built-in binary search result: " + builtInIndex);
    }
    
    private static void demonstrateAdvancedSearching(int[] arr) {
        System.out.println("\n=== Advanced Searching ===");
        
        // Find all occurrences of a value
        int target = 25;
        List<Integer> indices = findAllOccurrences(arr, target);
        System.out.println("All occurrences of " + target + ": " + indices);
        
        // Find second largest element
        int secondLargest = findSecondLargest(arr);
        System.out.println("Second largest element: " + secondLargest);
        
        // Find missing number in sequence (1 to n)
        int[] sequence = {1, 2, 4, 5, 6};
        int missing = findMissingNumber(sequence, 6);
        System.out.println("Missing number in {1,2,4,5,6}: " + missing);
    }
    
    public static List<Integer> findAllOccurrences(int[] arr, int target) {
        List<Integer> indices = new ArrayList<>();
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == target) {
                indices.add(i);
            }
        }
        return indices;
    }
    
    public static int findSecondLargest(int[] arr) {
        if (arr.length < 2) return -1;
        
        int largest = Integer.MIN_VALUE;
        int secondLargest = Integer.MIN_VALUE;
        
        for (int num : arr) {
            if (num > largest) {
                secondLargest = largest;
                largest = num;
            } else if (num > secondLargest && num != largest) {
                secondLargest = num;
            }
        }
        return secondLargest;
    }
    
    public static int findMissingNumber(int[] arr, int n) {
        int expectedSum = n * (n + 1) / 2;
        int actualSum = 0;
        for (int num : arr) {
            actualSum += num;
        }
        return expectedSum - actualSum;
    }
}

๐Ÿ“Š Sorting Algorithms
#

public class ArraySorting {
    public static void main(String[] args) {
        demonstrateBubbleSort();
        demonstrateSelectionSort();
        demonstrateInsertionSort();
        demonstrateAdvancedSorting();
    }
    
    // Bubble Sort - O(nยฒ) time complexity
    public static void bubbleSort(int[] arr) {
        int n = arr.length;
        boolean swapped;
        
        for (int i = 0; i < n - 1; i++) {
            swapped = false;
            for (int j = 0; j < n - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    // Swap elements
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    swapped = true;
                }
            }
            // If no swapping occurred, array is sorted
            if (!swapped) break;
        }
    }
    
    // Selection Sort - O(nยฒ) time complexity
    public static void selectionSort(int[] arr) {
        int n = arr.length;
        
        for (int i = 0; i < n - 1; i++) {
            int minIndex = i;
            
            // Find minimum element in remaining array
            for (int j = i + 1; j < n; j++) {
                if (arr[j] < arr[minIndex]) {
                    minIndex = j;
                }
            }
            
            // Swap minimum with first element
            if (minIndex != i) {
                int temp = arr[i];
                arr[i] = arr[minIndex];
                arr[minIndex] = temp;
            }
        }
    }
    
    // Insertion Sort - O(nยฒ) worst case, O(n) best case
    public static void insertionSort(int[] arr) {
        for (int i = 1; i < arr.length; i++) {
            int key = arr[i];
            int j = i - 1;
            
            // Move elements greater than key one position ahead
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];
                j--;
            }
            arr[j + 1] = key;
        }
    }
    
    private static void demonstrateBubbleSort() {
        int[] arr = {64, 34, 25, 12, 22, 11, 90};
        System.out.println("=== Bubble Sort ===");
        System.out.println("Original: " + Arrays.toString(arr));
        
        long startTime = System.nanoTime();
        bubbleSort(arr);
        long endTime = System.nanoTime();
        
        System.out.println("Sorted: " + Arrays.toString(arr));
        System.out.println("Time: " + (endTime - startTime) + " ns");
    }
    
    private static void demonstrateSelectionSort() {
        int[] arr = {64, 34, 25, 12, 22, 11, 90};
        System.out.println("\n=== Selection Sort ===");
        System.out.println("Original: " + Arrays.toString(arr));
        
        long startTime = System.nanoTime();
        selectionSort(arr);
        long endTime = System.nanoTime();
        
        System.out.println("Sorted: " + Arrays.toString(arr));
        System.out.println("Time: " + (endTime - startTime) + " ns");
    }
    
    private static void demonstrateInsertionSort() {
        int[] arr = {64, 34, 25, 12, 22, 11, 90};
        System.out.println("\n=== Insertion Sort ===");
        System.out.println("Original: " + Arrays.toString(arr));
        
        long startTime = System.nanoTime();
        insertionSort(arr);
        long endTime = System.nanoTime();
        
        System.out.println("Sorted: " + Arrays.toString(arr));
        System.out.println("Time: " + (endTime - startTime) + " ns");
    }
    
    private static void demonstrateAdvancedSorting() {
        System.out.println("\n=== Advanced Sorting Comparisons ===");
        
        // Compare with Arrays.sort() (highly optimized)
        int[] arr = generateRandomArray(10000);
        int[] copy = arr.clone();
        
        long startTime = System.nanoTime();
        Arrays.sort(copy);
        long endTime = System.nanoTime();
        
        System.out.println("Arrays.sort() on 10,000 elements: " + 
                          (endTime - startTime) + " ns");
        
        // Demonstrate sorting with custom objects
        Student[] students = {
            new Student("Alice", 85),
            new Student("Bob", 92),
            new Student("Charlie", 78),
            new Student("Diana", 95)
        };
        
        // Sort by grade (descending)
        Arrays.sort(students, (s1, s2) -> Integer.compare(s2.grade, s1.grade));
        System.out.println("Students sorted by grade (desc):");
        for (Student s : students) {
            System.out.println("  " + s);
        }
    }
    
    private static int[] generateRandomArray(int size) {
        Random random = new Random();
        int[] arr = new int[size];
        for (int i = 0; i < size; i++) {
            arr[i] = random.nextInt(1000);
        }
        return arr;
    }
    
    static class Student {
        String name;
        int grade;
        
        Student(String name, int grade) {
            this.name = name;
            this.grade = grade;
        }
        
        @Override
        public String toString() {
            return name + ": " + grade;
        }
    }
}

layout: default
#

Multi-dimensional Arrays Deep Dive
#

๐ŸŒ Jagged Arrays
#

public class JaggedArrayDemo {
    public static void main(String[] args) {
        createJaggedArrays();
        workWithTriangularArrays();
        implementPascalTriangle();
        demonstrateMemoryEfficiency();
    }
    
    private static void createJaggedArrays() {
        System.out.println("=== Jagged Arrays ===");
        
        // Create jagged array step by step
        int[][] jagged = new int[4][];  // 4 rows, columns undefined
        
        jagged[0] = new int[2];         // Row 0: 2 columns
        jagged[1] = new int[4];         // Row 1: 4 columns
        jagged[2] = new int[3];         // Row 2: 3 columns
        jagged[3] = new int[1];         // Row 3: 1 column
        
        // Fill with values
        int value = 1;
        for (int i = 0; i < jagged.length; i++) {
            for (int j = 0; j < jagged[i].length; j++) {
                jagged[i][j] = value++;
            }
        }
        
        // Display jagged array
        System.out.println("Jagged array structure:");
        for (int i = 0; i < jagged.length; i++) {
            System.out.print("Row " + i + ": ");
            for (int j = 0; j < jagged[i].length; j++) {
                System.out.print(jagged[i][j] + " ");
            }
            System.out.println("(" + jagged[i].length + " elements)");
        }
    }
    
    private static void workWithTriangularArrays() {
        System.out.println("\n=== Triangular Arrays ===");
        
        int rows = 5;
        int[][] triangle = new int[rows][];
        
        // Create triangular structure (1, 2, 3, 4, 5 elements)
        for (int i = 0; i < rows; i++) {
            triangle[i] = new int[i + 1];
        }
        
        // Fill with multiplication table
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j <= i; j++) {
                triangle[i][j] = (i + 1) * (j + 1);
            }
        }
        
        // Display triangular array
        System.out.println("Triangular multiplication table:");
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j <= i; j++) {
                System.out.printf("%4d", triangle[i][j]);
            }
            System.out.println();
        }
    }
    
    private static void implementPascalTriangle() {
        System.out.println("\n=== Pascal's Triangle ===");
        
        int rows = 7;
        int[][] pascal = new int[rows][];
        
        for (int i = 0; i < rows; i++) {
            pascal[i] = new int[i + 1];
            
            // First and last elements are always 1
            pascal[i][0] = 1;
            pascal[i][i] = 1;
            
            // Fill middle elements
            for (int j = 1; j < i; j++) {
                pascal[i][j] = pascal[i-1][j-1] + pascal[i-1][j];
            }
        }
        
        // Display Pascal's triangle
        System.out.println("Pascal's Triangle:");
        for (int i = 0; i < rows; i++) {
            // Add leading spaces for center alignment
            for (int k = 0; k < rows - i - 1; k++) {
                System.out.print("  ");
            }
            
            for (int j = 0; j <= i; j++) {
                System.out.printf("%4d", pascal[i][j]);
            }
            System.out.println();
        }
    }
    
    private static void demonstrateMemoryEfficiency() {
        System.out.println("\n=== Memory Efficiency ===");
        
        int size = 1000;
        
        // Regular 2D array (square)
        int totalElements = size * size;
        System.out.println("Square array (" + size + "x" + size + "): " + 
                          totalElements + " elements");
        
        // Triangular array (half memory)
        int triangularElements = size * (size + 1) / 2;
        System.out.println("Triangular array: " + triangularElements + 
                          " elements (" + (100.0 * triangularElements / totalElements) + 
                          "% of square array)");
        
        // Example: symmetric matrix storage
        demonstrateSymmetricMatrix();
    }
    
    private static void demonstrateSymmetricMatrix() {
        System.out.println("\nSymmetric matrix example:");
        
        // Store only upper triangle of symmetric matrix
        int n = 4;
        int[][] symmetric = new int[n][];
        
        for (int i = 0; i < n; i++) {
            symmetric[i] = new int[n - i];  // Only store upper triangle
        }
        
        // Fill upper triangle
        int value = 1;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < symmetric[i].length; j++) {
                symmetric[i][j] = value++;
            }
        }
        
        // Display as full symmetric matrix
        System.out.println("Full symmetric matrix (reconstructed):");
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                int value1;
                if (j >= i) {
                    value1 = symmetric[i][j - i];  // Upper triangle
                } else {
                    value1 = symmetric[j][i - j];  // Mirror from upper
                }
                System.out.printf("%4d", value1);
            }
            System.out.println();
        }
    }
}

๐ŸŽฏ 3D Arrays and Beyond
#

public class MultidimensionalArrays {
    public static void main(String[] args) {
        demonstrate3DArrays();
        implementTicTacToe();
        createImageProcessingExample();
        demonstrateArrayManipulation();
    }
    
    private static void demonstrate3DArrays() {
        System.out.println("=== 3D Arrays ===");
        
        // 3D array: [depth][rows][columns]
        int[][][] cube = new int[3][4][5];
        
        // Fill with sequential values
        int value = 1;
        for (int d = 0; d < cube.length; d++) {
            for (int r = 0; r < cube[d].length; r++) {
                for (int c = 0; c < cube[d][r].length; c++) {
                    cube[d][r][c] = value++;
                }
            }
        }
        
        // Display 3D structure
        System.out.println("3D Array (3x4x5):");
        for (int d = 0; d < cube.length; d++) {
            System.out.println("Layer " + d + ":");
            for (int r = 0; r < cube[d].length; r++) {
                for (int c = 0; c < cube[d][r].length; c++) {
                    System.out.printf("%3d ", cube[d][r][c]);
                }
                System.out.println();
            }
            System.out.println();
        }
    }
    
    private static void implementTicTacToe() {
        System.out.println("=== Tic-Tac-Toe Game Board ===");
        
        char[][] board = new char[3][3];
        
        // Initialize board with empty spaces
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                board[i][j] = ' ';
            }
        }
        
        // Simulate some moves
        board[0][0] = 'X';  // X moves
        board[1][1] = 'O';  // O moves
        board[0][2] = 'X';
        board[2][0] = 'O';
        board[0][1] = 'X';  // X wins (top row)
        
        // Display board
        displayTicTacToeBoard(board);
        
        // Check winner
        char winner = checkWinner(board);
        if (winner != ' ') {
            System.out.println("Winner: " + winner);
        } else {
            System.out.println("Game continues...");
        }
    }
    
    private static void displayTicTacToeBoard(char[][] board) {
        System.out.println("Current board:");
        for (int i = 0; i < 3; i++) {
            System.out.print(" ");
            for (int j = 0; j < 3; j++) {
                System.out.print(board[i][j]);
                if (j < 2) System.out.print(" | ");
            }
            System.out.println();
            if (i < 2) System.out.println("-----------");
        }
        System.out.println();
    }
    
    private static char checkWinner(char[][] board) {
        // Check rows
        for (int i = 0; i < 3; i++) {
            if (board[i][0] != ' ' && 
                board[i][0] == board[i][1] && 
                board[i][1] == board[i][2]) {
                return board[i][0];
            }
        }
        
        // Check columns
        for (int j = 0; j < 3; j++) {
            if (board[0][j] != ' ' && 
                board[0][j] == board[1][j] && 
                board[1][j] == board[2][j]) {
                return board[0][j];
            }
        }
        
        // Check diagonals
        if (board[0][0] != ' ' && 
            board[0][0] == board[1][1] && 
            board[1][1] == board[2][2]) {
            return board[0][0];
        }
        
        if (board[0][2] != ' ' && 
            board[0][2] == board[1][1] && 
            board[1][1] == board[2][0]) {
            return board[0][2];
        }
        
        return ' '; // No winner
    }
    
    private static void createImageProcessingExample() {
        System.out.println("=== Image Processing Simulation ===");
        
        // Simulate a small grayscale image (5x5 pixels)
        int[][] image = {
            {100, 120, 140, 120, 100},
            {80,  150, 200, 150, 80},
            {60,  180, 255, 180, 60},
            {80,  150, 200, 150, 80},
            {100, 120, 140, 120, 100}
        };
        
        System.out.println("Original image (grayscale values):");
        displayImage(image);
        
        // Apply blur filter
        int[][] blurred = applyBlurFilter(image);
        System.out.println("After blur filter:");
        displayImage(blurred);
        
        // Apply edge detection
        int[][] edges = detectEdges(image);
        System.out.println("Edge detection:");
        displayImage(edges);
    }
    
    private static void displayImage(int[][] image) {
        for (int[] row : image) {
            for (int pixel : row) {
                System.out.printf("%4d", pixel);
            }
            System.out.println();
        }
        System.out.println();
    }
    
    private static int[][] applyBlurFilter(int[][] image) {
        int rows = image.length;
        int cols = image[0].length;
        int[][] result = new int[rows][cols];
        
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                int sum = 0, count = 0;
                
                // Average neighboring pixels
                for (int di = -1; di <= 1; di++) {
                    for (int dj = -1; dj <= 1; dj++) {
                        int ni = i + di, nj = j + dj;
                        if (ni >= 0 && ni < rows && nj >= 0 && nj < cols) {
                            sum += image[ni][nj];
                            count++;
                        }
                    }
                }
                result[i][j] = sum / count;
            }
        }
        return result;
    }
    
    private static int[][] detectEdges(int[][] image) {
        int rows = image.length;
        int cols = image[0].length;
        int[][] result = new int[rows][cols];
        
        // Simple edge detection using gradient
        for (int i = 1; i < rows - 1; i++) {
            for (int j = 1; j < cols - 1; j++) {
                int gx = image[i-1][j+1] + 2*image[i][j+1] + image[i+1][j+1]
                       - image[i-1][j-1] - 2*image[i][j-1] - image[i+1][j-1];
                int gy = image[i+1][j-1] + 2*image[i+1][j] + image[i+1][j+1]
                       - image[i-1][j-1] - 2*image[i-1][j] - image[i-1][j+1];
                
                result[i][j] = Math.min(255, Math.abs(gx) + Math.abs(gy));
            }
        }
        return result;
    }
    
    private static void demonstrateArrayManipulation() {
        System.out.println("=== Array Manipulation Techniques ===");
        
        int[][] matrix = {
            {1, 2, 3, 4},
            {5, 6, 7, 8},
            {9, 10, 11, 12}
        };
        
        System.out.println("Original matrix:");
        displayMatrix(matrix);
        
        // Transpose
        int[][] transposed = transpose(matrix);
        System.out.println("Transposed matrix:");
        displayMatrix(transposed);
        
        // Rotate 90 degrees (for square matrices only)
        int[][] square = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
        System.out.println("Square matrix:");
        displayMatrix(square);
        
        int[][] rotated = rotate90(square);
        System.out.println("Rotated 90 degrees:");
        displayMatrix(rotated);
    }
    
    private static void displayMatrix(int[][] matrix) {
        for (int[] row : matrix) {
            for (int val : row) {
                System.out.printf("%4d", val);
            }
            System.out.println();
        }
        System.out.println();
    }
    
    private static int[][] transpose(int[][] matrix) {
        int rows = matrix.length;
        int cols = matrix[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] = matrix[i][j];
            }
        }
        return result;
    }
    
    private static int[][] rotate90(int[][] matrix) {
        int n = matrix.length;
        int[][] result = new int[n][n];
        
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                result[j][n - 1 - i] = matrix[i][j];
            }
        }
        return result;
    }
}

layout: default
#

Array Utilities and Best Practices
#

๐Ÿ› ๏ธ Array Utilities
#

import java.util.*;

public class ArrayUtilities {
    public static void main(String[] args) {
        demonstrateArraysClass();
        implementCustomUtilities();
        showArrayConversions();
        demonstrateDynamicArrays();
    }
    
    private static void demonstrateArraysClass() {
        System.out.println("=== Arrays Class Utilities ===");
        
        int[] numbers = {5, 2, 8, 1, 9, 3};
        System.out.println("Original: " + Arrays.toString(numbers));
        
        // Sorting
        int[] sorted = numbers.clone();
        Arrays.sort(sorted);
        System.out.println("Sorted: " + Arrays.toString(sorted));
        
        // Binary search (requires sorted array)
        int index = Arrays.binarySearch(sorted, 8);
        System.out.println("Index of 8 in sorted array: " + index);
        
        // Fill array
        int[] filled = new int[5];
        Arrays.fill(filled, 42);
        System.out.println("Filled with 42: " + Arrays.toString(filled));
        
        // Partial fill
        Arrays.fill(filled, 1, 4, 99);
        System.out.println("Partial fill [1,4): " + Arrays.toString(filled));
        
        // Copy arrays
        int[] copy = Arrays.copyOf(numbers, 10);
        System.out.println("Copied (extended): " + Arrays.toString(copy));
        
        int[] range = Arrays.copyOfRange(numbers, 2, 5);
        System.out.println("Range copy [2,5): " + Arrays.toString(range));
        
        // Equality check
        int[] numbers2 = {5, 2, 8, 1, 9, 3};
        System.out.println("Arrays equal: " + Arrays.equals(numbers, numbers2));
        
        // Deep equality for 2D arrays
        int[][] matrix1 = {{1, 2}, {3, 4}};
        int[][] matrix2 = {{1, 2}, {3, 4}};
        System.out.println("2D arrays equal: " + Arrays.deepEquals(matrix1, matrix2));
        
        // HashCode
        System.out.println("Array hashcode: " + Arrays.hashCode(numbers));
        System.out.println("2D array hashcode: " + Arrays.deepHashCode(matrix1));
    }
    
    private static void implementCustomUtilities() {
        System.out.println("\n=== Custom Array Utilities ===");
        
        int[] array = {1, 5, 3, 9, 2, 8, 4};
        
        // Custom utilities
        System.out.println("Array: " + Arrays.toString(array));
        System.out.println("Sum: " + sum(array));
        System.out.println("Average: " + average(array));
        System.out.println("Min: " + min(array));
        System.out.println("Max: " + max(array));
        System.out.println("Median: " + median(array.clone()));
        
        // Array statistics
        Statistics stats = calculateStatistics(array);
        System.out.println("Statistics: " + stats);
        
        // Reverse array
        int[] reversed = reverse(array.clone());
        System.out.println("Reversed: " + Arrays.toString(reversed));
        
        // Remove duplicates
        int[] withDuplicates = {1, 2, 2, 3, 3, 3, 4, 5, 5};
        int[] unique = removeDuplicates(withDuplicates);
        System.out.println("Duplicates: " + Arrays.toString(withDuplicates));
        System.out.println("Unique: " + Arrays.toString(unique));
        
        // Merge sorted arrays
        int[] arr1 = {1, 3, 5, 7};
        int[] arr2 = {2, 4, 6, 8, 9};
        int[] merged = mergeSorted(arr1, arr2);
        System.out.println("Merged: " + Arrays.toString(merged));
    }
    
    // Utility methods
    public static int sum(int[] arr) {
        int sum = 0;
        for (int num : arr) {
            sum += num;
        }
        return sum;
    }
    
    public static double average(int[] arr) {
        return (double) sum(arr) / arr.length;
    }
    
    public static int min(int[] arr) {
        int min = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] < min) {
                min = arr[i];
            }
        }
        return min;
    }
    
    public static int max(int[] arr) {
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        return max;
    }
    
    public static double median(int[] arr) {
        Arrays.sort(arr);
        int n = arr.length;
        if (n % 2 == 0) {
            return (arr[n/2 - 1] + arr[n/2]) / 2.0;
        } else {
            return arr[n/2];
        }
    }
    
    public static Statistics calculateStatistics(int[] arr) {
        return new Statistics(sum(arr), average(arr), min(arr), max(arr));
    }
    
    public static int[] reverse(int[] arr) {
        for (int i = 0; i < arr.length / 2; i++) {
            int temp = arr[i];
            arr[i] = arr[arr.length - 1 - i];
            arr[arr.length - 1 - i] = temp;
        }
        return arr;
    }
    
    public static int[] removeDuplicates(int[] arr) {
        Arrays.sort(arr);
        int[] temp = new int[arr.length];
        int uniqueCount = 0;
        
        for (int i = 0; i < arr.length; i++) {
            if (i == 0 || arr[i] != arr[i - 1]) {
                temp[uniqueCount++] = arr[i];
            }
        }
        
        return Arrays.copyOf(temp, uniqueCount);
    }
    
    public static int[] mergeSorted(int[] arr1, int[] arr2) {
        int[] merged = new int[arr1.length + arr2.length];
        int i = 0, j = 0, k = 0;
        
        while (i < arr1.length && j < arr2.length) {
            if (arr1[i] <= arr2[j]) {
                merged[k++] = arr1[i++];
            } else {
                merged[k++] = arr2[j++];
            }
        }
        
        while (i < arr1.length) {
            merged[k++] = arr1[i++];
        }
        
        while (j < arr2.length) {
            merged[k++] = arr2[j++];
        }
        
        return merged;
    }
    
    static class Statistics {
        int sum;
        double average;
        int min, max;
        
        Statistics(int sum, double average, int min, int max) {
            this.sum = sum;
            this.average = average;
            this.min = min;
            this.max = max;
        }
        
        @Override
        public String toString() {
            return String.format("Sum=%d, Avg=%.2f, Min=%d, Max=%d", 
                               sum, average, min, max);
        }
    }
    
    private static void showArrayConversions() {
        System.out.println("\n=== Array Conversions ===");
        
        // Array to List
        String[] stringArray = {"apple", "banana", "cherry"};
        List<String> list = Arrays.asList(stringArray);
        System.out.println("Array to List: " + list);
        
        // Note: asList() returns fixed-size list
        try {
            list.add("date");  // This will throw exception
        } catch (UnsupportedOperationException e) {
            System.out.println("Cannot modify fixed-size list from asList()");
        }
        
        // Proper array to ArrayList conversion
        List<String> mutableList = new ArrayList<>(Arrays.asList(stringArray));
        mutableList.add("date");
        System.out.println("Mutable list: " + mutableList);
        
        // List to array
        String[] backToArray = mutableList.toArray(new String[0]);
        System.out.println("List to array: " + Arrays.toString(backToArray));
        
        // Primitive array considerations
        int[] intArray = {1, 2, 3, 4, 5};
        // Arrays.asList(intArray);  // This creates List<int[]>, not List<Integer>!
        
        // Correct way for primitives
        List<Integer> intList = Arrays.stream(intArray)
                                     .boxed()
                                     .collect(Collectors.toList());
        System.out.println("Primitive array to List: " + intList);
    }
    
    private static void demonstrateDynamicArrays() {
        System.out.println("\n=== Dynamic Arrays (ArrayList) ===");
        
        // ArrayList as dynamic array
        ArrayList<Integer> dynamic = new ArrayList<>();
        
        System.out.println("Adding elements dynamically:");
        for (int i = 1; i <= 10; i++) {
            dynamic.add(i);
            System.out.println("Added " + i + ", size: " + dynamic.size());
        }
        
        // Insert at specific position
        dynamic.add(5, 99);  // Insert 99 at index 5
        System.out.println("After inserting 99 at index 5: " + dynamic);
        
        // Remove elements
        dynamic.remove(5);   // Remove element at index 5
        dynamic.remove(Integer.valueOf(10));  // Remove first occurrence of 10
        System.out.println("After removals: " + dynamic);
        
        // Dynamic resizing demonstration
        ArrayList<String> words = new ArrayList<>(2);  // Initial capacity 2
        words.add("one");
        words.add("two");
        System.out.println("Capacity 2, added 2 elements");
        
        words.add("three");  // This will trigger resize
        System.out.println("Added third element, ArrayList resized internally");
        System.out.println("Final list: " + words);
    }
}

๐ŸŽฏ Memory Management & Performance
#

public class ArrayMemoryPerformance {
    public static void main(String[] args) {
        analyzeMemoryUsage();
        comparePerformance();
        demonstrateCaching();
        showBestPractices();
    }
    
    private static void analyzeMemoryUsage() {
        System.out.println("=== Memory Usage Analysis ===");
        
        Runtime runtime = Runtime.getRuntime();
        
        // Measure memory before array creation
        runtime.gc();  // Suggest garbage collection
        long memoryBefore = runtime.totalMemory() - runtime.freeMemory();
        
        // Create large array
        int[] largeArray = new int[1_000_000];
        
        // Measure memory after
        long memoryAfter = runtime.totalMemory() - runtime.freeMemory();
        long arrayMemory = memoryAfter - memoryBefore;
        
        System.out.println("Memory used by int[1,000,000]: " + arrayMemory + " bytes");
        System.out.println("Expected: " + (1_000_000 * 4) + " bytes (4 bytes per int)");
        System.out.println("Overhead: " + (arrayMemory - 1_000_000 * 4) + " bytes");
        
        // Compare different array types
        compareArrayMemory();
    }
    
    private static void compareArrayMemory() {
        System.out.println("\nMemory usage by data type (1000 elements):");
        
        int size = 1000;
        
        // Create arrays of different types
        byte[] byteArray = new byte[size];        // 1 byte each
        short[] shortArray = new short[size];     // 2 bytes each
        int[] intArray = new int[size];           // 4 bytes each
        long[] longArray = new long[size];        // 8 bytes each
        float[] floatArray = new float[size];     // 4 bytes each
        double[] doubleArray = new double[size];  // 8 bytes each
        
        System.out.println("byte[1000]:   ~" + (size * 1) + " bytes");
        System.out.println("short[1000]:  ~" + (size * 2) + " bytes");
        System.out.println("int[1000]:    ~" + (size * 4) + " bytes");
        System.out.println("long[1000]:   ~" + (size * 8) + " bytes");
        System.out.println("float[1000]:  ~" + (size * 4) + " bytes");
        System.out.println("double[1000]: ~" + (size * 8) + " bytes");
        
        // Object arrays have additional overhead
        String[] stringArray = new String[size];
        System.out.println("String[1000]:  ~" + (size * 8) + 
                          " bytes + string content (reference array only)");
    }
    
    private static void comparePerformance() {
        System.out.println("\n=== Performance Comparison ===");
        
        int size = 10_000_000;
        int[] array = new int[size];
        ArrayList<Integer> list = new ArrayList<>(size);
        
        // Fill both with same data
        for (int i = 0; i < size; i++) {
            array[i] = i;
            list.add(i);
        }
        
        // Test random access performance
        Random random = new Random(42);
        int iterations = 1_000_000;
        
        // Array access
        long startTime = System.nanoTime();
        long sum = 0;
        for (int i = 0; i < iterations; i++) {
            int index = random.nextInt(size);
            sum += array[index];
        }
        long arrayTime = System.nanoTime() - startTime;
        
        // ArrayList access
        random = new Random(42);  // Reset for fair comparison
        startTime = System.nanoTime();
        sum = 0;
        for (int i = 0; i < iterations; i++) {
            int index = random.nextInt(size);
            sum += list.get(index);
        }
        long listTime = System.nanoTime() - startTime;
        
        System.out.println("Random access performance (1M operations):");
        System.out.println("Array:     " + arrayTime / 1_000_000 + " ms");
        System.out.println("ArrayList: " + listTime / 1_000_000 + " ms");
        System.out.println("Array is " + (double) listTime / arrayTime + "x faster");
        
        // Test sequential access
        testSequentialAccess(array, list);
    }
    
    private static void testSequentialAccess(int[] array, ArrayList<Integer> list) {
        System.out.println("\nSequential access performance:");
        
        // Array sequential access
        long startTime = System.nanoTime();
        long sum = 0;
        for (int i = 0; i < array.length; i++) {
            sum += array[i];
        }
        long arraySeqTime = System.nanoTime() - startTime;
        
        // Enhanced for loop with array
        startTime = System.nanoTime();
        sum = 0;
        for (int value : array) {
            sum += value;
        }
        long arrayForTime = System.nanoTime() - startTime;
        
        // ArrayList sequential access
        startTime = System.nanoTime();
        sum = 0;
        for (int i = 0; i < list.size(); i++) {
            sum += list.get(i);
        }
        long listSeqTime = System.nanoTime() - startTime;
        
        // Enhanced for loop with ArrayList
        startTime = System.nanoTime();
        sum = 0;
        for (Integer value : list) {
            sum += value;
        }
        long listForTime = System.nanoTime() - startTime;
        
        System.out.println("Array indexed loop:    " + arraySeqTime / 1_000_000 + " ms");
        System.out.println("Array enhanced for:    " + arrayForTime / 1_000_000 + " ms");
        System.out.println("ArrayList indexed:     " + listSeqTime / 1_000_000 + " ms");
        System.out.println("ArrayList enhanced:    " + listForTime / 1_000_000 + " ms");
    }
    
    private static void demonstrateCaching() {
        System.out.println("\n=== CPU Cache Effects ===");
        
        int size = 1000;
        int[][] matrix = new int[size][size];
        
        // Fill matrix with values
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                matrix[i][j] = i * size + j;
            }
        }
        
        // Row-major access (cache-friendly)
        long startTime = System.nanoTime();
        long sum = 0;
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                sum += matrix[i][j];
            }
        }
        long rowMajorTime = System.nanoTime() - startTime;
        
        // Column-major access (cache-unfriendly)
        startTime = System.nanoTime();
        sum = 0;
        for (int j = 0; j < size; j++) {
            for (int i = 0; i < size; i++) {
                sum += matrix[i][j];
            }
        }
        long colMajorTime = System.nanoTime() - startTime;
        
        System.out.println("Matrix traversal (1000x1000):");
        System.out.println("Row-major (cache-friendly):    " + rowMajorTime / 1_000_000 + " ms");
        System.out.println("Column-major (cache-unfriendly): " + colMajorTime / 1_000_000 + " ms");
        System.out.println("Row-major is " + (double) colMajorTime / rowMajorTime + "x faster");
    }
    
    private static void showBestPractices() {
        System.out.println("\n=== Array Best Practices ===");
        
        // 1. Pre-size arrays when possible
        System.out.println("1. Pre-size collections:");
        ArrayList<Integer> presized = new ArrayList<>(1000);
        ArrayList<Integer> defaultsize = new ArrayList<>();
        
        long start = System.nanoTime();
        for (int i = 0; i < 1000; i++) {
            presized.add(i);
        }
        long presizedTime = System.nanoTime() - start;
        
        start = System.nanoTime();
        for (int i = 0; i < 1000; i++) {
            defaultsize.add(i);
        }
        long defaultTime = System.nanoTime() - start;
        
        System.out.println("   Pre-sized: " + presizedTime + " ns");
        System.out.println("   Default:   " + defaultTime + " ns");
        System.out.println("   Improvement: " + (double) defaultTime / presizedTime + "x");
        
        // 2. Use enhanced for loops for iteration
        System.out.println("\n2. Use enhanced for loops for simple iteration:");
        int[] array = {1, 2, 3, 4, 5};
        
        System.out.println("   Good: for (int value : array) { ... }");
        System.out.println("   Avoid: for (int i = 0; i < array.length; i++) when index not needed");
        
        // 3. Consider primitive collections for performance
        System.out.println("\n3. Consider primitive arrays over object collections:");
        System.out.println("   int[] vs ArrayList<Integer>");
        System.out.println("   Primitive arrays: less memory, better cache locality");
        
        // 4. Array bounds checking
        System.out.println("\n4. Always validate array bounds:");
        System.out.println("   if (index >= 0 && index < array.length) { ... }");
        
        // 5. Use Arrays utility class
        System.out.println("\n5. Leverage Arrays utility class:");
        System.out.println("   Arrays.sort(), Arrays.binarySearch(), Arrays.equals()");
        System.out.println("   Arrays.toString(), Arrays.copyOf()");
    }
}

layout: default
#

Common Pitfalls and Troubleshooting
#

โš ๏ธ Common Array Mistakes
#

public class ArrayPitfalls {
    public static void main(String[] args) {
        demonstrateIndexOutOfBounds();
        demonstrateNullPointerExceptions();
        demonstrateReferenceIssues();
        demonstrateTypeCastingProblems();
    }
    
    private static void demonstrateIndexOutOfBounds() {
        System.out.println("=== Array Index Out Of Bounds ===");
        
        int[] numbers = {10, 20, 30, 40, 50};
        
        System.out.println("Array: " + Arrays.toString(numbers));
        System.out.println("Valid indices: 0 to " + (numbers.length - 1));
        
        // Common mistakes
        try {
            // Mistake 1: Using length as index
            int value = numbers[numbers.length];  // Wrong! Should be length-1
            System.out.println("This won't print");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Error: Tried to access index " + numbers.length);
            System.out.println("Fix: Use index " + (numbers.length - 1) + " for last element");
        }
        
        try {
            // Mistake 2: Off-by-one error in loops
            for (int i = 1; i <= numbers.length; i++) {  // Wrong condition!
                System.out.println(numbers[i]);
            }
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Error: Loop condition should be i < numbers.length");
        }
        
        try {
            // Mistake 3: Negative indices
            int value = numbers[-1];  // Not valid in Java (unlike Python)
            System.out.println("This won't print");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("Error: Negative indices not supported in Java");
        }
        
        // Correct ways to access array elements
        System.out.println("\nCorrect access patterns:");
        System.out.println("First element: numbers[0] = " + numbers[0]);
        System.out.println("Last element: numbers[length-1] = " + numbers[numbers.length - 1]);
        
        // Safe access with bounds checking
        int index = 10;
        if (index >= 0 && index < numbers.length) {
            System.out.println("Safe access: " + numbers[index]);
        } else {
            System.out.println("Index " + index + " is out of bounds");
        }
    }
    
    private static void demonstrateNullPointerExceptions() {
        System.out.println("\n=== Null Pointer Exceptions ===");
        
        // Mistake 1: Uninitialized array
        int[] uninitializedArray = null;
        try {
            int length = uninitializedArray.length;
        } catch (NullPointerException e) {
            System.out.println("Error: Array is null, cannot access length");
            System.out.println("Fix: Initialize array first");
        }
        
        // Mistake 2: Array of objects with null elements
        String[] names = new String[3];  // Creates array, but elements are null
        System.out.println("String array after creation: " + Arrays.toString(names));
        
        try {
            int length = names[0].length();  // names[0] is null!
        } catch (NullPointerException e) {
            System.out.println("Error: Array element is null");
            System.out.println("Fix: Initialize elements before use");
        }
        
        // Correct initialization
        names[0] = "Alice";
        names[1] = "Bob";
        names[2] = "Charlie";
        
        // Safe access with null check
        String name = names[0];
        if (name != null) {
            System.out.println("Length of first name: " + name.length());
        }
        
        // Initialize array with values at creation
        String[] properlyInitialized = {"Alice", "Bob", "Charlie"};
        System.out.println("Properly initialized: " + Arrays.toString(properlyInitialized));
    }
    
    private static void demonstrateReferenceIssues() {
        System.out.println("\n=== Array Reference Issues ===");
        
        // Arrays are reference types
        int[] original = {1, 2, 3, 4, 5};
        int[] reference = original;  // This copies the reference, not the array!
        
        System.out.println("Original: " + Arrays.toString(original));
        System.out.println("Reference: " + Arrays.toString(reference));
        
        // Modifying through reference affects original
        reference[2] = 999;
        System.out.println("\nAfter modifying reference[2]:");
        System.out.println("Original: " + Arrays.toString(original));
        System.out.println("Reference: " + Arrays.toString(reference));
        System.out.println("Both changed! They point to the same array.");
        
        // Correct way to copy arrays
        int[] properCopy = original.clone();
        properCopy[1] = 888;
        
        System.out.println("\nAfter modifying proper copy:");
        System.out.println("Original: " + Arrays.toString(original));
        System.out.println("Proper copy: " + Arrays.toString(properCopy));
        System.out.println("Only the copy changed.");
        
        // Array comparison pitfall
        int[] array1 = {1, 2, 3};
        int[] array2 = {1, 2, 3};
        
        System.out.println("\nArray comparison:");
        System.out.println("array1 == array2: " + (array1 == array2));  // false!
        System.out.println("Arrays.equals(array1, array2): " + Arrays.equals(array1, array2));
        
        // 2D array comparison
        int[][] matrix1 = {{1, 2}, {3, 4}};
        int[][] matrix2 = {{1, 2}, {3, 4}};
        
        System.out.println("\n2D Array comparison:");
        System.out.println("Arrays.equals(matrix1, matrix2): " + Arrays.equals(matrix1, matrix2));  // false!
        System.out.println("Arrays.deepEquals(matrix1, matrix2): " + Arrays.deepEquals(matrix1, matrix2));
    }
    
    private static void demonstrateTypeCastingProblems() {
        System.out.println("\n=== Type Casting Problems ===");
        
        // Problem 1: Narrowing conversion data loss
        long[] longArray = {Integer.MAX_VALUE + 1L, 42L, Integer.MIN_VALUE - 1L};
        int[] intArray = new int[longArray.length];
        
        System.out.println("Converting long to int:");
        for (int i = 0; i < longArray.length; i++) {
            intArray[i] = (int) longArray[i];
            System.out.println(longArray[i] + " -> " + intArray[i] + 
                             (longArray[i] != intArray[i] ? " (DATA LOSS!)" : ""));
        }
        
        // Problem 2: Precision loss with floating point
        double[] preciseValues = {1.23456789, 99.99999999, 0.123456789123456789};
        float[] lessPrecise = new float[preciseValues.length];
        
        System.out.println("\nConverting double to float:");
        for (int i = 0; i < preciseValues.length; i++) {
            lessPrecise[i] = (float) preciseValues[i];
            System.out.println(preciseValues[i] + " -> " + lessPrecise[i]);
            System.out.println("Difference: " + (preciseValues[i] - lessPrecise[i]));
        }
        
        // Problem 3: Character to number conversion
        char[] chars = {'A', '0', '9', 'Z', ' '};
        int[] asciiValues = new int[chars.length];
        
        System.out.println("\nCharacter to ASCII conversion:");
        for (int i = 0; i < chars.length; i++) {
            asciiValues[i] = (int) chars[i];
            System.out.println("'" + chars[i] + "' -> " + asciiValues[i]);
        }
        
        // Safe conversion with validation
        System.out.println("\nSafe string to number conversion:");
        String[] numberStrings = {"123", "invalid", "45.67", "", null};
        
        for (String str : numberStrings) {
            try {
                if (str != null && !str.isEmpty()) {
                    int number = Integer.parseInt(str);
                    System.out.println("'" + str + "' -> " + number + " (success)");
                } else {
                    System.out.println("'" + str + "' -> skipped (null or empty)");
                }
            } catch (NumberFormatException e) {
                System.out.println("'" + str + "' -> conversion failed: " + e.getMessage());
            }
        }
    }
}

๐Ÿ”ง Debugging and Testing Arrays
#

public class ArrayDebugging {
    public static void main(String[] args) {
        demonstrateDebuggingTechniques();
        demonstrateTestingStrategies();
        demonstrateValidationMethods();
        demonstrateLoggingTechniques();
    }
    
    private static void demonstrateDebuggingTechniques() {
        System.out.println("=== Array Debugging Techniques ===");
        
        int[] problematicArray = {1, 5, 3, 8, 2, 9, 4};
        
        // Technique 1: Print array state at key points
        System.out.println("1. State Inspection:");
        System.out.println("   Initial state: " + Arrays.toString(problematicArray));
        
        // Simulate sorting with debugging
        bubbleSortWithDebug(problematicArray.clone());
        
        // Technique 2: Validate assumptions
        System.out.println("\n2. Assumption Validation:");
        int[] testArray = {10, 20, 30, 40, 50};
        validateArrayAssumptions(testArray);
        
        // Technique 3: Check boundary conditions
        System.out.println("\n3. Boundary Condition Testing:");
        testBoundaryConditions();
        
        // Technique 4: Use assertions for debugging
        System.out.println("\n4. Assertion-based Debugging:");
        demonstrateAssertions();
    }
    
    private static void bubbleSortWithDebug(int[] arr) {
        System.out.println("   Bubble sort with debugging:");
        
        for (int i = 0; i < arr.length - 1; i++) {
            boolean swapped = false;
            System.out.println("   Pass " + (i + 1) + ":");
            
            for (int j = 0; j < arr.length - i - 1; j++) {
                System.out.println("     Comparing " + arr[j] + " and " + arr[j + 1]);
                
                if (arr[j] > arr[j + 1]) {
                    // Swap
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    swapped = true;
                    
                    System.out.println("     Swapped! Array now: " + 
                                     Arrays.toString(arr));
                }
            }
            
            if (!swapped) {
                System.out.println("   No swaps in this pass - array is sorted!");
                break;
            }
        }
    }
    
    private static void validateArrayAssumptions(int[] arr) {
        // Assumption: Array is not null
        assert arr != null : "Array should not be null";
        System.out.println("   โœ“ Array is not null");
        
        // Assumption: Array has elements
        assert arr.length > 0 : "Array should not be empty";
        System.out.println("   โœ“ Array is not empty (length: " + arr.length + ")");
        
        // Assumption: Array is sorted (ascending)
        boolean isSorted = true;
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] < arr[i - 1]) {
                isSorted = false;
                break;
            }
        }
        System.out.println("   " + (isSorted ? "โœ“" : "โœ—") + " Array is sorted: " + isSorted);
        
        // Assumption: All elements are positive
        boolean allPositive = true;
        for (int value : arr) {
            if (value <= 0) {
                allPositive = false;
                break;
            }
        }
        System.out.println("   " + (allPositive ? "โœ“" : "โœ—") + " All elements positive: " + allPositive);
    }
    
    private static void testBoundaryConditions() {
        // Test with empty array
        int[] empty = {};
        System.out.println("   Empty array length: " + empty.length);
        
        // Test with single element
        int[] single = {42};
        System.out.println("   Single element array: " + Arrays.toString(single));
        
        // Test with two elements
        int[] pair = {1, 2};
        System.out.println("   Two element array: " + Arrays.toString(pair));
        
        // Test with maximum values
        int[] maxValues = {Integer.MAX_VALUE, Integer.MIN_VALUE};
        System.out.println("   Extreme values: " + Arrays.toString(maxValues));
        
        // Test operations on boundary arrays
        try {
            int max = findMax(empty);
            System.out.println("   Max of empty array: " + max);
        } catch (IllegalArgumentException e) {
            System.out.println("   โœ“ Correctly handled empty array: " + e.getMessage());
        }
        
        System.out.println("   Max of single element: " + findMax(single));
        System.out.println("   Max of two elements: " + findMax(pair));
    }
    
    private static int findMax(int[] arr) {
        if (arr.length == 0) {
            throw new IllegalArgumentException("Cannot find max of empty array");
        }
        
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max) {
                max = arr[i];
            }
        }
        return max;
    }
    
    private static void demonstrateAssertions() {
        // Note: Assertions must be enabled with -ea flag
        int[] testArray = {1, 2, 3, 4, 5};
        
        // Pre-condition assertion
        assert testArray != null && testArray.length > 0 : "Array must be valid";
        
        // Post-condition assertion (after operation)
        int sum = calculateSum(testArray);
        assert sum > 0 : "Sum should be positive for positive array";
        
        System.out.println("   All assertions passed for sum calculation");
        System.out.println("   (Note: Run with -ea flag to enable assertions)");
    }
    
    private static int calculateSum(int[] arr) {
        int sum = 0;
        for (int value : arr) {
            sum += value;
            // Invariant assertion (checked during loop)
            assert sum >= 0 : "Sum should never decrease with positive values";
        }
        return sum;
    }
    
    private static void demonstrateTestingStrategies() {
        System.out.println("\n=== Array Testing Strategies ===");
        
        // Strategy 1: Test normal cases
        System.out.println("1. Normal Case Testing:");
        testSortingFunction(new int[]{5, 2, 8, 1, 9});
        
        // Strategy 2: Test edge cases
        System.out.println("\n2. Edge Case Testing:");
        testSortingFunction(new int[]{});  // Empty
        testSortingFunction(new int[]{42});  // Single element
        testSortingFunction(new int[]{1, 2, 3, 4, 5});  // Already sorted
        testSortingFunction(new int[]{5, 4, 3, 2, 1});  // Reverse sorted
        testSortingFunction(new int[]{3, 3, 3, 3});  // All equal
        
        // Strategy 3: Test with large datasets
        System.out.println("\n3. Performance Testing:");
        testSortingPerformance();
        
        // Strategy 4: Test error conditions
        System.out.println("\n4. Error Condition Testing:");
        testErrorConditions();
    }
    
    private static void testSortingFunction(int[] arr) {
        int[] original = arr.clone();
        int[] sorted = arr.clone();
        Arrays.sort(sorted);
        
        // Apply our sorting function
        bubbleSort(arr);
        
        boolean passed = Arrays.equals(arr, sorted);
        System.out.println("   Test " + Arrays.toString(original) + 
                          " -> " + (passed ? "PASSED" : "FAILED"));
        
        if (!passed) {
            System.out.println("   Expected: " + Arrays.toString(sorted));
            System.out.println("   Actual:   " + Arrays.toString(arr));
        }
    }
    
    private static void bubbleSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
    
    private static void testSortingPerformance() {
        int[] largeArray = new int[10000];
        Random random = new Random(42);  // Fixed seed for reproducibility
        
        for (int i = 0; i < largeArray.length; i++) {
            largeArray[i] = random.nextInt(1000);
        }
        
        long startTime = System.nanoTime();
        Arrays.sort(largeArray.clone());
        long javaSort = System.nanoTime() - startTime;
        
        startTime = System.nanoTime();
        bubbleSort(largeArray.clone());
        long bubbleTime = System.nanoTime() - startTime;
        
        System.out.println("   Arrays.sort(): " + javaSort / 1_000_000 + " ms");
        System.out.println("   Bubble sort:   " + bubbleTime / 1_000_000 + " ms");
        System.out.println("   Performance ratio: " + (double) bubbleTime / javaSort + "x");
    }
    
    private static void testErrorConditions() {
        // Test null array
        try {
            bubbleSort(null);
            System.out.println("   โœ— Should have thrown exception for null array");
        } catch (NullPointerException e) {
            System.out.println("   โœ“ Correctly handled null array");
        }
        
        // Test array access bounds
        int[] arr = {1, 2, 3};
        try {
            int value = arr[10];  // Out of bounds
            System.out.println("   โœ— Should have thrown exception for out of bounds");
        } catch (ArrayIndexOutOfBoundsException e) {
            System.out.println("   โœ“ Correctly detected out of bounds access");
        }
    }
    
    private static void demonstrateValidationMethods() {
        System.out.println("\n=== Array Validation Methods ===");
        
        int[] validArray = {1, 2, 3, 4, 5};
        int[] invalidArray = null;
        int[] emptyArray = {};
        
        System.out.println("Validation results:");
        System.out.println("   Valid array: " + validateArray(validArray));
        System.out.println("   Null array: " + validateArray(invalidArray));
        System.out.println("   Empty array: " + validateArray(emptyArray));
        
        // Range validation
        System.out.println("\nRange validation:");
        System.out.println("   Index 2 in valid array: " + validateIndex(validArray, 2));
        System.out.println("   Index 10 in valid array: " + validateIndex(validArray, 10));
        System.out.println("   Index -1 in valid array: " + validateIndex(validArray, -1));
    }
    
    private static boolean validateArray(int[] arr) {
        if (arr == null) {
            System.out.println("     Error: Array is null");
            return false;
        }
        
        if (arr.length == 0) {
            System.out.println("     Warning: Array is empty");
            return false;  // Or true, depending on requirements
        }
        
        return true;
    }
    
    private static boolean validateIndex(int[] arr, int index) {
        if (!validateArray(arr)) {
            return false;
        }
        
        if (index < 0 || index >= arr.length) {
            System.out.println("     Error: Index " + index + " is out of bounds [0, " + 
                             (arr.length - 1) + "]");
            return false;
        }
        
        return true;
    }
    
    private static void demonstrateLoggingTechniques() {
        System.out.println("\n=== Array Logging Techniques ===");
        
        int[] data = {45, 23, 67, 12, 89};
        
        // Basic logging
        logArrayState("Initial", data);
        
        // Process array with detailed logging
        for (int i = 0; i < data.length; i++) {
            int oldValue = data[i];
            data[i] = data[i] * 2;  // Double each value
            logOperation("Doubled", i, oldValue, data[i]);
        }
        
        logArrayState("Final", data);
        
        // Summary logging
        logArraySummary(data);
    }
    
    private static void logArrayState(String label, int[] arr) {
        System.out.println("   [" + label + "] Array: " + Arrays.toString(arr) + 
                          " (length: " + arr.length + ")");
    }
    
    private static void logOperation(String operation, int index, int oldValue, int newValue) {
        System.out.println("   [" + operation + "] Index " + index + ": " + 
                          oldValue + " -> " + newValue);
    }
    
    private static void logArraySummary(int[] arr) {
        int sum = Arrays.stream(arr).sum();
        double average = (double) sum / arr.length;
        int min = Arrays.stream(arr).min().orElse(0);
        int max = Arrays.stream(arr).max().orElse(0);
        
        System.out.println("   [Summary] Sum: " + sum + ", Avg: " + String.format("%.2f", average) + 
                          ", Min: " + min + ", Max: " + max);
    }
}

layout: center class: text-center
#

Elite Array Optimization Challenge Lab
#

Transform Into a SIMD Computing Specialist
#

๐Ÿ† Level 1: SIMD Vectorization Mastery

โšก Implement AVX-512 vectorized array operations achieving 16x performance gains
๐Ÿ’Ž Design cache-conscious array layouts for 100M+ data points processing
๐ŸŽฏ Create lock-free parallel algorithms for concurrent array manipulation

๐Ÿš€ Level 2: Exascale Array Computing

๐Ÿง  Build distributed array frameworks processing 1TB+ datasets in real-time
๐Ÿ”ฌ Engineer GPU-accelerated operations using thousands of CUDA cores
๐Ÿ“Š Deploy zero-copy streaming architectures for continuous data processing

๐ŸŽ–๏ธ Level 3: Quantum-Ready Array Systems

๐Ÿ›๏ธ Architect quantum-classical hybrid computing arrays for D.E. Shaw Research
๐Ÿ’ฐ Implement machine learning array optimizations generating $100M+ alpha
๐Ÿ”ฅ Design fault-tolerant array systems with 99.9999% reliability requirements

๐Ÿ’ฐ Career Transformation Assessment

Software Engineer โ†’ Performance Architect
$90K โ†’ $350K+ annually
Google DeepMind, NVIDIA, Intel Advanced Computing
SIMD Computing Specialist
Exascale Systems Engineering
$400K-600K at D.E. Shaw, Two Sigma, Citadel
Chief Technology Officer
Quantum Computing Leadership
$1M+ at quantum computing startups

๐ŸŒŸ Elite Certifications Unlocked

โœ… **Intel SIMD Optimization Expert**
โœ… **NVIDIA CUDA Professional**
โœ… **AMD ROCm Specialist**
โœ… **Google TensorFlow Performance Engineer**
โœ… **Microsoft Azure HPC Architect**
โœ… **Quantum Computing Developer**
Portfolio Value: $100K+ salary premium
๐ŸŽฏ SIMD ARRAY MASTERY ACHIEVED
Exascale Computing: COMPLETE
Ready for quantum-hybrid computing engineering roles
Next lecture: Advanced Operator Optimization & Bit Manipulation

layout: center class: text-center
#

Elite Developer Transformation Complete
#

From Basic Arrays to Exascale Computing Systems
#

๐Ÿ† Mastery Achieved

  • โ€ข SIMD vectorization with 16x performance gains
  • โ€ข Cache-conscious array layouts for 100M+ data points
  • โ€ข Lock-free parallel algorithms for quantum computing
  • โ€ข GPU-accelerated operations using thousands of cores
  • โ€ข Zero-copy streaming for real-time processing

๐Ÿš€ Career Trajectory

  • โ€ข **Performance Architect** at Google DeepMind
  • โ€ข **SIMD Specialist** at Intel Advanced Computing
  • โ€ข **Exascale Engineer** at D.E. Shaw Research
  • โ€ข **Quantum Developer** at IBM Quantum Network
  • โ€ข **CTO Track** at Quantum Computing Startups
Master SIMD arrays, master exascale computing! ๐Ÿš€
**Next lecture:** Advanced Operator Optimization & Bit Manipulation for Quantum Computing