String Programs

Reverse a String
Easy
Problem

Write a program to reverse a given string without using built-in reverse methods.

Input: "Selenium"

Output: "muineleS"

String Two Pointers Interview
public class ReverseString {
    public static String reverse(String str) {
        // Using StringBuilder
        return new StringBuilder(str).reverse().toString();
    }

    // Without built-in methods
    public static String reverseManual(String str) {
        char[] chars = str.toCharArray();
        int left = 0, right = chars.length - 1;

        while (left < right) {
            // Swap characters
            char temp = chars[left];
            chars[left] = chars[right];
            chars[right] = temp;
            left++;
            right--;
        }
        return new String(chars);
    }

    public static void main(String[] args) {
        System.out.println(reverse("Selenium"));
        // Output: muineleS
    }
}
Explanation
  • Two-pointer approach: Use left and right pointers starting from both ends
  • Swap: Exchange characters at left and right positions
  • Move pointers: Increment left, decrement right until they meet
  • StringBuilder: Built-in reverse() is simpler but interviewers often ask manual approach
Time: O(n) Space: O(n) for char array
Check Palindrome
Easy
Problem

Check if a string is a palindrome (reads same forwards and backwards).

Input: "madam"

Output: true

String Two Pointers
public class Palindrome {
    public static boolean isPalindrome(String str) {
        String clean = str.replaceAll("[^a-zA-Z0-9]", "")
                         .toLowerCase();

        int left = 0;
        int right = clean.length() - 1;

        while (left < right) {
            if (clean.charAt(left) != clean.charAt(right)) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }

    public static void main(String[] args) {
        System.out.println(isPalindrome("madam"));      // true
        System.out.println(isPalindrome("A man a plan a canal Panama")); // true
        System.out.println(isPalindrome("hello"));      // false
    }
}
Explanation
  • Clean string: Remove non-alphanumeric chars and convert to lowercase
  • Two pointers: Compare from both ends moving inward
  • Early exit: Return false immediately on mismatch
  • Common in SDET: Used for validating test data
Time: O(n) Space: O(n)
Count Character Occurrences
Medium
Problem

Count occurrences of each character in a string using HashMap and Streams.

Input: "automation"

Output: {a=2, t=2, o=2, ...}

HashMap Streams Java 8
import java.util.*;
import java.util.stream.Collectors;

public class CharCount {
    // Using HashMap
    public static Map<Character, Integer> countChars(String str) {
        Map<Character, Integer> map = new HashMap<>();
        for (char c : str.toCharArray()) {
            map.put(c, map.getOrDefault(c, 0) + 1);
        }
        return map;
    }

    // Using Java 8 Streams
    public static Map<Character, Long> countWithStreams(String str) {
        return str.chars()
            .mapToObj(c -> (char) c)
            .collect(Collectors.groupingBy(
                c -> c,
                Collectors.counting()
            ));
    }

    public static void main(String[] args) {
        System.out.println(countChars("automation"));
        // {a=2, u=1, t=2, o=2, m=1, i=1, n=1}
    }
}
Explanation
  • HashMap approach: Iterate and use getOrDefault for counting
  • Streams approach: Modern Java 8+ solution using collectors
  • groupingBy: Groups characters and counts occurrences
  • SDET use: Useful for data validation in test frameworks
Time: O(n) Space: O(k) where k = unique chars
Find Duplicate Characters
Medium
Problem

Find all duplicate characters in a string.

Input: "programming"

Output: [r, g, m]

HashSet String
import java.util.*;

public class DuplicateChars {
    public static Set<Character> findDuplicates(String str) {
        Set<Character> seen = new HashSet<>();
        Set<Character> duplicates = new HashSet<>();

        for (char c : str.toLowerCase().toCharArray()) {
            if (!seen.add(c)) {
                // add() returns false if already exists
                duplicates.add(c);
            }
        }
        return duplicates;
    }

    public static void main(String[] args) {
        System.out.println(findDuplicates("programming"));
        // Output: [r, g, m]

        System.out.println(findDuplicates("Selenium WebDriver"));
        // Output: [e, r, i]
    }
}
Explanation
  • Two Sets: One for tracking seen chars, one for duplicates
  • add() trick: Returns false if element already exists
  • Case handling: Convert to lowercase for case-insensitive check
  • HashSet: O(1) lookup makes this efficient
Time: O(n) Space: O(n)

Array Programs

Find Second Largest Element
Easy
Problem

Find the second largest element in an array without sorting.

Input: [12, 35, 1, 10, 34, 1]

Output: 34

Array Single Pass
public class SecondLargest {
    public static int findSecondLargest(int[] arr) {
        int first = Integer.MIN_VALUE;
        int second = Integer.MIN_VALUE;

        for (int num : arr) {
            if (num > first) {
                second = first;
                first = num;
            } else if (num > second && num != first) {
                second = num;
            }
        }
        return second;
    }

    public static void main(String[] args) {
        int[] arr = {12, 35, 1, 10, 34, 1};
        System.out.println(findSecondLargest(arr)); // 34
    }
}
Explanation
  • Track two values: First largest and second largest
  • Update logic: When new max found, shift first to second
  • Handle duplicates: Check num != first to avoid duplicates
  • Single pass: No sorting needed, O(n) solution
Time: O(n) Space: O(1)
Remove Duplicates from Array
Medium
Problem

Remove duplicate elements from array preserving order.

Input: [1, 2, 2, 3, 4, 4, 5]

Output: [1, 2, 3, 4, 5]

Array LinkedHashSet Streams
import java.util.*;
import java.util.stream.*;

public class RemoveDuplicates {
    // Using LinkedHashSet (preserves order)
    public static int[] removeDuplicates(int[] arr) {
        Set<Integer> set = new LinkedHashSet<>();
        for (int num : arr) {
            set.add(num);
        }
        return set.stream().mapToInt(i -> i).toArray();
    }

    // Using Java 8 Streams (one-liner)
    public static int[] removeDuplicatesStream(int[] arr) {
        return Arrays.stream(arr).distinct().toArray();
    }

    public static void main(String[] args) {
        int[] arr = {1, 2, 2, 3, 4, 4, 5};
        System.out.println(Arrays.toString(removeDuplicates(arr)));
        // [1, 2, 3, 4, 5]
    }
}
Explanation
  • LinkedHashSet: Maintains insertion order + removes duplicates
  • Streams distinct(): Clean one-liner solution
  • Order matters: Use LinkedHashSet, not HashSet
  • Interview tip: Know both approaches
Time: O(n) Space: O(n)
Two Sum Problem
Medium
Problem

Find two numbers that add up to target. Return their indices.

Input: [2, 7, 11, 15], target = 9

Output: [0, 1]

HashMap Array LeetCode
import java.util.*;

public class TwoSum {
    public static int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>();

        for (int i = 0; i < nums.length; i++) {
            int complement = target - nums[i];

            if (map.containsKey(complement)) {
                return new int[]{map.get(complement), i};
            }
            map.put(nums[i], i);
        }
        return new int[]{};
    }

    public static void main(String[] args) {
        int[] nums = {2, 7, 11, 15};
        int target = 9;
        System.out.println(Arrays.toString(twoSum(nums, target)));
        // [0, 1] because nums[0] + nums[1] = 2 + 7 = 9
    }
}
Explanation
  • Complement: For each num, check if (target - num) exists
  • HashMap: Store number and its index for O(1) lookup
  • Single pass: Check and add in same loop
  • Classic problem: Very common in coding interviews
Time: O(n) Space: O(n)

Number Programs

Fibonacci Series
Easy
Problem

Print first n numbers of Fibonacci series where each number is sum of previous two.

Input: n = 10

Output: 0 1 1 2 3 5 8 13 21 34

Recursion Dynamic Programming
public class Fibonacci {
    // Iterative (Preferred)
    public static void printFibonacci(int n) {
        int a = 0, b = 1;
        for (int i = 0; i < n; i++) {
            System.out.print(a + " ");
            int sum = a + b;
            a = b;
            b = sum;
        }
    }

    // Recursive (Less efficient)
    public static int fibRecursive(int n) {
        if (n <= 1) return n;
        return fibRecursive(n - 1) + fibRecursive(n - 2);
    }

    public static void main(String[] args) {
        printFibonacci(10);
        // Output: 0 1 1 2 3 5 8 13 21 34
    }
}
Explanation
  • Iterative: O(n) time, O(1) space - preferred in interviews
  • Recursive: O(2^n) time - explain why it's inefficient
  • Pattern: F(n) = F(n-1) + F(n-2)
  • Tip: Mention memoization to optimize recursion
Time: O(n) iterative Space: O(1) iterative
Check Prime Number
Easy
Problem

Check if a number is prime (divisible only by 1 and itself).

Input: 17

Output: true

Math Optimization
public class PrimeNumber {
    public static boolean isPrime(int n) {
        if (n <= 1) return false;
        if (n <= 3) return true;
        if (n % 2 == 0 || n % 3 == 0) return false;

        // Check only 6k +/- 1 pattern
        for (int i = 5; i * i <= n; i += 6) {
            if (n % i == 0 || n % (i + 2) == 0) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        System.out.println(isPrime(17)); // true
        System.out.println(isPrime(18)); // false
        System.out.println(isPrime(2));  // true
    }
}
Explanation
  • Early checks: Handle 1, 2, 3, and even numbers
  • sqrt optimization: Only check up to square root
  • 6k pattern: All primes > 3 are of form 6k +/- 1
  • Why: Numbers of form 6k+2, 6k+3, 6k+4 are divisible by 2 or 3
Time: O(sqrt(n)) Space: O(1)

Selenium Programs

WebDriver Setup with WebDriverManager
Easy
Problem

Set up Selenium WebDriver with automatic driver management and basic configurations.

Selenium WebDriverManager Setup
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import io.github.bonigarcia.wdm.WebDriverManager;
import java.time.Duration;

public class SeleniumSetup {
    public static void main(String[] args) {
        // Auto-manage driver binary
        WebDriverManager.chromedriver().setup();

        // Configure Chrome options
        ChromeOptions options = new ChromeOptions();
        options.addArguments("--start-maximized");
        options.addArguments("--disable-notifications");
        // options.addArguments("--headless"); // For headless

        WebDriver driver = new ChromeDriver(options);

        // Set timeouts
        driver.manage().timeouts()
            .implicitlyWait(Duration.ofSeconds(10));
        driver.manage().timeouts()
            .pageLoadTimeout(Duration.ofSeconds(30));

        driver.get("https://www.google.com");
        System.out.println("Title: " + driver.getTitle());

        driver.quit();
    }
}
Explanation
  • WebDriverManager: Auto-downloads matching driver binary
  • ChromeOptions: Configure browser behavior
  • Timeouts: Set implicit wait and page load timeout
  • quit() vs close(): quit() closes all windows and ends session
Maven: io.github.bonigarcia:webdrivermanager:5.x
Explicit Wait with Expected Conditions
Medium
Problem

Use WebDriverWait with ExpectedConditions for synchronization.

Selenium Waits Synchronization
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.*;
import java.time.Duration;

public class ExplicitWaitExample {
    public static void main(String[] args) {
        WebDriver driver = new ChromeDriver();
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

        try {
            driver.get("https://example.com");

            // Wait for element to be clickable
            WebElement btn = wait.until(
                ExpectedConditions.elementToBeClickable(By.id("submit"))
            );
            btn.click();

            // Wait for visibility
            WebElement result = wait.until(
                ExpectedConditions.visibilityOfElementLocated(By.className("result"))
            );

            // Wait for text to be present
            wait.until(
                ExpectedConditions.textToBePresentInElement(result, "Success")
            );

            // Wait for element to disappear
            wait.until(
                ExpectedConditions.invisibilityOfElementLocated(By.id("loader"))
            );

        } finally {
            driver.quit();
        }
    }
}
Explanation
  • WebDriverWait: Waits up to specified time for condition
  • elementToBeClickable: Visible + enabled
  • visibilityOfElementLocated: Present in DOM + visible
  • invisibilityOfElementLocated: Wait for loader/spinner to disappear
Best Practice: Use explicit over implicit waits
Handle Dropdown (Select class)
Easy
Problem

Select values from dropdown using Select class methods.

Selenium Dropdown Select
import org.openqa.selenium.*;
import org.openqa.selenium.support.ui.Select;
import java.util.List;

public class DropdownExample {
    public static void main(String[] args) {
        WebDriver driver = new ChromeDriver();
        driver.get("https://example.com/form");

        WebElement dropdown = driver.findElement(By.id("country"));
        Select select = new Select(dropdown);

        // Check if multiple selection allowed
        System.out.println("Multiple: " + select.isMultiple());

        // Select by visible text
        select.selectByVisibleText("India");

        // Select by value attribute
        select.selectByValue("IN");

        // Select by index (0-based)
        select.selectByIndex(2);

        // Get all options
        List<WebElement> options = select.getOptions();
        options.forEach(opt -> System.out.println(opt.getText()));

        // Get selected option
        WebElement selected = select.getFirstSelectedOption();
        System.out.println("Selected: " + selected.getText());

        driver.quit();
    }
}
Explanation
  • Select class: Only works with <select> tags
  • Three ways: By text, value, or index
  • getOptions(): Returns all available options
  • For custom dropdowns: Use click + findElements
Note: Select class won't work for div-based dropdowns
Handle Multiple Windows/Tabs
Medium
Problem

Switch between multiple browser windows or tabs.

Selenium Windows Handles
import org.openqa.selenium.*;
import java.util.Set;

public class WindowHandling {
    public static void main(String[] args) {
        WebDriver driver = new ChromeDriver();
        driver.get("https://example.com");

        // Store parent window handle
        String parentWindow = driver.getWindowHandle();
        System.out.println("Parent: " + parentWindow);

        // Click link that opens new window
        driver.findElement(By.linkText("Open New Window")).click();

        // Get all window handles
        Set<String> allWindows = driver.getWindowHandles();

        // Switch to new window
        for (String window : allWindows) {
            if (!window.equals(parentWindow)) {
                driver.switchTo().window(window);
                System.out.println("Title: " + driver.getTitle());

                // Perform actions in new window
                // ...

                driver.close(); // Close current window
            }
        }

        // Switch back to parent
        driver.switchTo().window(parentWindow);
        driver.quit();
    }
}
Explanation
  • getWindowHandle(): Returns current window ID
  • getWindowHandles(): Returns Set of all window IDs
  • switchTo().window(): Switch driver focus
  • close() vs quit(): close() closes current, quit() ends session
Tip: Always store parent handle before clicking
Handle JavaScript Alerts
Easy
Problem

Handle JavaScript alerts, confirms, and prompts.

Selenium Alerts JavaScript
import org.openqa.selenium.*;

public class AlertHandling {
    public static void main(String[] args) {
        WebDriver driver = new ChromeDriver();
        driver.get("https://example.com/alerts");

        // Trigger alert
        driver.findElement(By.id("alertBtn")).click();

        // Switch to alert
        Alert alert = driver.switchTo().alert();

        // Get alert text
        String alertText = alert.getText();
        System.out.println("Alert: " + alertText);

        // Accept (OK button)
        alert.accept();

        // For confirm dialog - dismiss (Cancel)
        driver.findElement(By.id("confirmBtn")).click();
        Alert confirm = driver.switchTo().alert();
        confirm.dismiss(); // Click Cancel

        // For prompt - send text
        driver.findElement(By.id("promptBtn")).click();
        Alert prompt = driver.switchTo().alert();
        prompt.sendKeys("Test input");
        prompt.accept();

        driver.quit();
    }
}
Explanation
  • switchTo().alert(): Get Alert object
  • accept(): Click OK/Yes
  • dismiss(): Click Cancel/No
  • sendKeys(): Enter text in prompt
Note: Wait for alert before switching
Page Object Model (POM)
Hard
Problem

Implement Page Object Model design pattern for maintainable test code.

Selenium POM Design Pattern Framework
// LoginPage.java
import org.openqa.selenium.*;
import org.openqa.selenium.support.*;

public class LoginPage {
    private WebDriver driver;

    // Page Factory - Locators
    @FindBy(id = "username")
    private WebElement usernameField;

    @FindBy(id = "password")
    private WebElement passwordField;

    @FindBy(css = "button[type='submit']")
    private WebElement loginButton;

    @FindBy(className = "error-message")
    private WebElement errorMessage;

    // Constructor
    public LoginPage(WebDriver driver) {
        this.driver = driver;
        PageFactory.initElements(driver, this);
    }

    // Page Actions
    public void enterUsername(String username) {
        usernameField.clear();
        usernameField.sendKeys(username);
    }

    public void enterPassword(String password) {
        passwordField.clear();
        passwordField.sendKeys(password);
    }

    public HomePage clickLogin() {
        loginButton.click();
        return new HomePage(driver);
    }

    // Combined action
    public HomePage login(String user, String pass) {
        enterUsername(user);
        enterPassword(pass);
        return clickLogin();
    }

    public String getErrorMessage() {
        return errorMessage.getText();
    }
}
Explanation
  • @FindBy: Declare locators as annotations
  • PageFactory: Initialize elements lazily
  • Return type: Return next page object for chaining
  • Encapsulation: Hide locators, expose actions
Benefits: Reusability, Maintainability, Readability

Playwright Programs

Playwright Java Setup
Easy
Problem

Set up Playwright with Java for browser automation.

Playwright Setup Java
import com.microsoft.playwright.*;

public class PlaywrightSetup {
    public static void main(String[] args) {
        try (Playwright playwright = Playwright.create()) {
            // Launch browser (chromium/firefox/webkit)
            Browser browser = playwright.chromium().launch(
                new BrowserType.LaunchOptions()
                    .setHeadless(false)
                    .setSlowMo(100)
            );

            // Create context and page
            BrowserContext context = browser.newContext();
            Page page = context.newPage();

            // Navigate
            page.navigate("https://www.google.com");
            System.out.println("Title: " + page.title());

            // Take screenshot
            page.screenshot(new Page.ScreenshotOptions()
                .setPath(Paths.get("screenshot.png")));

            browser.close();
        }
    }
}
Explanation
  • try-with-resources: Auto-closes Playwright
  • Browser types: chromium, firefox, webkit
  • Context: Isolated browser session
  • setSlowMo: Slows down actions for debugging
Maven: com.microsoft.playwright:playwright:1.x
Auto-waiting and Locators
Medium
Problem

Use Playwright's auto-waiting and modern locator strategies.

Playwright Locators Auto-wait
import com.microsoft.playwright.*;

public class PlaywrightLocators {
    public static void main(String[] args) {
        try (Playwright playwright = Playwright.create()) {
            Browser browser = playwright.chromium().launch();
            Page page = browser.newPage();
            page.navigate("https://example.com/login");

            // Modern locators (auto-wait built-in)
            page.getByLabel("Username").fill("testuser");
            page.getByLabel("Password").fill("password123");
            page.getByRole(AriaRole.BUTTON,
                new Page.GetByRoleOptions().setName("Sign in"))
                .click();

            // Wait for navigation
            page.waitForURL("**/dashboard");

            // Assertions with auto-retry
            assertThat(page.getByText("Welcome")).isVisible();

            // Get by test ID
            page.getByTestId("submit-button").click();

            // Filter locators
            page.getByRole(AriaRole.LISTITEM)
                .filter(new Locator.FilterOptions().setHasText("Product"))
                .click();

            browser.close();
        }
    }
}
Explanation
  • getByLabel: Find by associated label text
  • getByRole: ARIA role-based locator
  • getByTestId: data-testid attribute
  • Auto-wait: All actions wait automatically
Benefit: No explicit waits needed in most cases
API Testing with Playwright
Medium
Problem

Make API requests using Playwright's APIRequestContext.

Playwright API Testing REST
import com.microsoft.playwright.*;
import com.google.gson.JsonObject;

public class PlaywrightAPITest {
    public static void main(String[] args) {
        try (Playwright playwright = Playwright.create()) {
            APIRequestContext request = playwright.request().newContext(
                new APIRequest.NewContextOptions()
                    .setBaseURL("https://api.example.com")
            );

            // GET request
            APIResponse getResponse = request.get("/users/1");
            System.out.println("Status: " + getResponse.status());
            System.out.println("Body: " + getResponse.text());

            // POST request
            JsonObject body = new JsonObject();
            body.addProperty("name", "Test User");
            body.addProperty("email", "test@example.com");

            APIResponse postResponse = request.post("/users",
                RequestOptions.create()
                    .setData(body.toString())
            );

            // Assertions
            assertThat(postResponse.status()).isEqualTo(201);
            assertThat(postResponse.ok()).isTrue();

            // PUT request
            APIResponse putResponse = request.put("/users/1",
                RequestOptions.create().setData(body.toString())
            );

            // DELETE request
            APIResponse deleteResponse = request.delete("/users/1");
        }
    }
}
Explanation
  • APIRequestContext: Make HTTP requests without browser
  • Supports: GET, POST, PUT, DELETE, PATCH
  • ok(): True if status is 2xx
  • Use case: Setup test data via API before UI tests
Benefit: Unified API + UI testing in same framework

API Testing Programs (Rest Assured)

REST Assured - GET Request
Easy
Problem

Make GET request and validate response with Rest Assured.

Rest Assured GET API Testing
import io.restassured.RestAssured;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;

public class RestAssuredGetTest {
    public static void main(String[] args) {
        RestAssured.baseURI = "https://jsonplaceholder.typicode.com";

        // Simple GET with validation
        given()
            .header("Content-Type", "application/json")
        .when()
            .get("/users/1")
        .then()
            .statusCode(200)
            .body("id", equalTo(1))
            .body("name", notNullValue())
            .body("email", containsString("@"));

        // Extract response
        String name = given()
            .get("/users/1")
        .then()
            .extract()
            .path("name");
        System.out.println("Name: " + name);

        // Get as JSON object
        Response response = get("/users");
        List<String> names = response.jsonPath().getList("name");
        names.forEach(System.out::println);
    }
}
Explanation
  • given-when-then: BDD style syntax
  • Hamcrest matchers: equalTo, notNullValue, containsString
  • extract(): Get specific values from response
  • jsonPath(): Navigate JSON response
Maven: io.rest-assured:rest-assured:5.x
REST Assured - POST Request
Medium
Problem

Make POST request with JSON body and validate response.

Rest Assured POST JSON
import io.restassured.RestAssured;
import static io.restassured.RestAssured.*;
import static org.hamcrest.Matchers.*;
import java.util.*;

public class RestAssuredPostTest {
    public static void main(String[] args) {
        RestAssured.baseURI = "https://jsonplaceholder.typicode.com";

        // Using HashMap for body
        Map<String, Object> body = new HashMap<>();
        body.put("title", "Test Post");
        body.put("body", "This is test content");
        body.put("userId", 1);

        int postId = given()
            .header("Content-Type", "application/json")
            .body(body)
        .when()
            .post("/posts")
        .then()
            .statusCode(201)
            .body("title", equalTo("Test Post"))
            .body("id", notNullValue())
            .extract()
            .path("id");

        System.out.println("Created Post ID: " + postId);

        // Using JSON string
        String jsonBody = """
            {
                "title": "Another Post",
                "body": "Content here",
                "userId": 1
            }
            """;

        given()
            .contentType("application/json")
            .body(jsonBody)
        .when()
            .post("/posts")
        .then()
            .statusCode(201);
    }
}
Explanation
  • body(): Accepts Map, POJO, or JSON string
  • Content-Type: Always set for POST requests
  • 201 Created: Standard status for successful POST
  • Text blocks: Java 15+ feature for multi-line strings
Tip: Use POJOs for complex request bodies
Check Anagram
Easy
Problem

Check if two strings are anagrams (same characters, different order).

Input: "listen", "silent"

Output: true

String Sorting HashMap
import java.util.Arrays;

public class AnagramCheck {

    // Method 1: Sort and Compare
    public static boolean isAnagram(String s1, String s2) {
        if (s1.length() != s2.length()) return false;
        char[] a = s1.toLowerCase().toCharArray();
        char[] b = s2.toLowerCase().toCharArray();
        Arrays.sort(a);
        Arrays.sort(b);
        return Arrays.equals(a, b);
    }

    // Method 2: Frequency Count (More efficient)
    public static boolean isAnagramFreq(String s1, String s2) {
        if (s1.length() != s2.length()) return false;
        int[] freq = new int[26];
        for (int i = 0; i < s1.length(); i++) {
            freq[s1.charAt(i) - 'a']++;
            freq[s2.charAt(i) - 'a']--;
        }
        for (int f : freq) if (f != 0) return false;
        return true;
    }

    public static void main(String[] args) {
        System.out.println(isAnagram("listen", "silent")); // true
        System.out.println(isAnagram("hello",  "world"));  // false
    }
}
Explanation
  • Sort approach: Sort both strings β€” if equal they're anagrams
  • Frequency approach: Count chars in s1, subtract for s2 β€” all must be 0
  • Length check first: Quick rejection saves computation
  • SDET use: Validate shuffled test data or response fields
Time: O(n log n) sort | O(n) frequency Space: O(1) frequency
First Non-Repeating Character
Medium
Problem

Find the first character that does not repeat in a string.

Input: "aabbcde"

Output: 'c'

String LinkedHashMap Java 8
import java.util.*;

public class FirstNonRepeating {

    public static char firstUnique(String str) {
        // LinkedHashMap preserves insertion order
        Map<Character, Integer> map = new LinkedHashMap<>();
        for (char c : str.toCharArray()) {
            map.put(c, map.getOrDefault(c, 0) + 1);
        }
        for (Map.Entry<Character, Integer> entry : map.entrySet()) {
            if (entry.getValue() == 1) return entry.getKey();
        }
        return '\0'; // No unique char found
    }

    // Java 8 Streams approach
    public static Optional<Character> firstUniqueStream(String str) {
        Map<Character, Long> freq = str.chars()
            .mapToObj(c -> (char) c)
            .collect(java.util.stream.Collectors.groupingBy(
                c -> c, LinkedHashMap::new,
                java.util.stream.Collectors.counting()));
        return freq.entrySet().stream()
            .filter(e -> e.getValue() == 1)
            .map(Map.Entry::getKey)
            .findFirst();
    }

    public static void main(String[] args) {
        System.out.println(firstUnique("aabbcde"));   // c
        System.out.println(firstUnique("selenium"));  // e (s appears once too)
    }
}
Explanation
  • LinkedHashMap: Keeps insertion order so first unique is found correctly
  • Two passes: First build frequency map, then scan for count == 1
  • Streams: Compact one-stream solution using groupingBy
  • Interview tip: Always mention why LinkedHashMap over HashMap here
Time: O(n) Space: O(k) unique chars
Rotate Array by K Positions
Medium
Problem

Rotate an array to the right by k positions.

Input: [1,2,3,4,5], k=2

Output: [4,5,1,2,3]

Array Reverse In-place
import java.util.Arrays;

public class RotateArray {

    // Reverse technique - O(n) time, O(1) space
    public static void rotate(int[] arr, int k) {
        int n = arr.length;
        k = k % n; // Handle k > n
        reverse(arr, 0, n - 1);      // Reverse whole array
        reverse(arr, 0, k - 1);      // Reverse first k elements
        reverse(arr, k, n - 1);      // Reverse remaining
    }

    private static void reverse(int[] arr, int l, int r) {
        while (l < r) {
            int tmp = arr[l];
            arr[l++] = arr[r];
            arr[r--] = tmp;
        }
    }

    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        rotate(arr, 2);
        System.out.println(Arrays.toString(arr));
        // Output: [4, 5, 1, 2, 3]
    }
}
Explanation
  • Reverse trick: Reverse all β†’ reverse first k β†’ reverse rest
  • k % n: Handles cases where k is larger than array length
  • In-place: No extra array needed, O(1) space
  • Visualize: [1,2,3,4,5] β†’ [5,4,3,2,1] β†’ [4,5,3,2,1] β†’ [4,5,1,2,3]
Time: O(n) Space: O(1)
Sort Array of 0s, 1s, 2s (Dutch National Flag)
Medium
Problem

Sort an array containing only 0, 1, 2 in a single pass without extra space.

Input: [2,0,1,2,0,1]

Output: [0,0,1,1,2,2]

Array Three Pointers Dutch Flag
import java.util.Arrays;

public class DutchNationalFlag {

    public static void sort012(int[] arr) {
        int low = 0, mid = 0, high = arr.length - 1;

        while (mid <= high) {
            if (arr[mid] == 0) {
                // Swap with low region
                int tmp = arr[low]; arr[low] = arr[mid]; arr[mid] = tmp;
                low++; mid++;
            } else if (arr[mid] == 1) {
                mid++;           // 1 is already in place
            } else {
                // Swap with high region
                int tmp = arr[mid]; arr[mid] = arr[high]; arr[high] = tmp;
                high--;          // Don't increment mid (new value unchecked)
            }
        }
    }

    public static void main(String[] args) {
        int[] arr = {2, 0, 1, 2, 0, 1};
        sort012(arr);
        System.out.println(Arrays.toString(arr));
        // Output: [0, 0, 1, 1, 2, 2]
    }
}
Explanation
  • Three pointers: low (0s), mid (current), high (2s)
  • 0 found: Swap to low region, advance both low & mid
  • 1 found: Already in place, just move mid
  • 2 found: Swap to high region, only decrease high (don't move mid)
Time: O(n) β€” single pass Space: O(1)
Factorial (Iterative & Recursive)
Easy
Problem

Calculate factorial of a number n! = n Γ— (n-1) Γ— … Γ— 1.

Input: 5

Output: 120

Recursion Math
public class Factorial {

    // Iterative
    public static long factIter(int n) {
        long result = 1;
        for (int i = 2; i <= n; i++) result *= i;
        return result;
    }

    // Recursive
    public static long factRec(int n) {
        if (n <= 1) return 1;
        return n * factRec(n - 1);
    }

    // Using Java 8 Streams
    public static long factStream(int n) {
        return java.util.stream.LongStream
            .rangeClosed(1, n)
            .reduce(1, (long) Math::multiplyExact);
    }

    public static void main(String[] args) {
        System.out.println(factIter(5));   // 120
        System.out.println(factRec(10));  // 3628800
    }
}
Explanation
  • Iterative: Simple loop, O(n) time O(1) space β€” preferred
  • Recursive: Clean but has O(n) stack frames β€” risk of StackOverflow for large n
  • long type: int overflows beyond 12!, long handles up to 20!
  • Base case: 0! = 1 and 1! = 1
Time: O(n) Space: O(1) iterative | O(n) recursive
Armstrong Number
Easy
Problem

An Armstrong number equals the sum of its own digits each raised to the power of the number of digits.

Input: 153

Output: true (1Β³ + 5Β³ + 3Β³ = 153)

Math Number
public class Armstrong {

    public static boolean isArmstrong(int n) {
        String s = String.valueOf(n);
        int digits = s.length();
        int sum = 0, temp = n;

        while (temp > 0) {
            int digit = temp % 10;
            sum += (int) Math.pow(digit, digits);
            temp /= 10;
        }
        return sum == n;
    }

    public static void main(String[] args) {
        System.out.println(isArmstrong(153));  // true
        System.out.println(isArmstrong(370));  // true  (3Β³+7Β³+0Β³=370)
        System.out.println(isArmstrong(9474)); // true  (4-digit)
        System.out.println(isArmstrong(100));  // false

        // Print all 3-digit Armstrong numbers
        System.out.print("Armstrong 3-digit: ");
        for (int i = 100; i <= 999; i++)
            if (isArmstrong(i)) System.out.print(i + " ");
        // 153 370 371 407
    }
}
Explanation
  • Get digits: Count digits with String.valueOf(n).length()
  • Extract digit: n % 10 gives last digit, n / 10 removes it
  • Math.pow: Raises digit to power of digit count
  • Classic 3-digit Armstrong: 153, 370, 371, 407
Time: O(d) where d = number of digits Space: O(1)

Pattern Programs

Right-Angled Triangle (Stars)
Easy
Problem

Print a right-angled triangle of stars for n rows.

Input: n = 5

*
**
***
****
*****
Pattern Loops Beginner
public class RightTriangle {

    public static void print(int n) {
        for (int i = 1; i <= n; i++) {         // rows
            for (int j = 1; j <= i; j++) {     // cols = row number
                System.out.print("* ");
            }
            System.out.println();
        }
    }

    // Inverted triangle
    public static void printInverted(int n) {
        for (int i = n; i >= 1; i--) {
            for (int j = 1; j <= i; j++) {
                System.out.print("* ");
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        System.out.println("--- Triangle ---");
        print(5);
        System.out.println("--- Inverted ---");
        printInverted(5);
    }
}
Explanation
  • Outer loop: Controls number of rows (1 to n)
  • Inner loop: Prints stars β€” count equals current row number
  • println(): Moves to next line after each row
  • Inverted: Start outer loop from n, count down to 1
Time: O(nΒ²) Space: O(1)
Pyramid (Centred Triangle)
Medium
Problem

Print a centred star pyramid for n rows.

Input: n = 4

   *
  ***
 *****
*******
Pattern Spaces Pyramid
public class Pyramid {

    public static void print(int n) {
        for (int i = 1; i <= n; i++) {
            // Print leading spaces
            for (int s = 1; s <= n - i; s++)
                System.out.print(" ");

            // Print stars: 2*i - 1 stars per row
            for (int j = 1; j <= (2 * i - 1); j++)
                System.out.print("*");

            System.out.println();
        }
    }

    // Diamond = Pyramid + Inverted pyramid
    public static void diamond(int n) {
        // Upper half
        for (int i = 1; i <= n; i++) {
            for (int s = n - i; s > 0; s--) System.out.print(" ");
            for (int j = 1; j <= 2 * i - 1; j++) System.out.print("*");
            System.out.println();
        }
        // Lower half
        for (int i = n - 1; i >= 1; i--) {
            for (int s = n - i; s > 0; s--) System.out.print(" ");
            for (int j = 1; j <= 2 * i - 1; j++) System.out.print("*");
            System.out.println();
        }
    }

    public static void main(String[] args) {
        System.out.println("--- Pyramid ---");
        print(4);
        System.out.println("--- Diamond ---");
        diamond(4);
    }
}
Explanation
  • Spaces: Row i needs (n - i) leading spaces to centre it
  • Stars per row: Row i has (2*i - 1) stars
  • Diamond: Combine pyramid (up) + inverted pyramid (down)
  • Pattern rule: Row 1β†’1 star, row 2β†’3 stars, row 3β†’5 stars…
Time: O(nΒ²) Space: O(1)
Number Triangle Patterns
Easy
Problem

Print common number triangle patterns asked in interviews.

Pattern A (1-12-123):

1
1 2
1 2 3
1 2 3 4

Pattern B (Floyd's):

1
2 3
4 5 6
7 8 9 10
Pattern Numbers Floyd's Triangle
public class NumberTriangles {

    // Pattern A: 1 / 1 2 / 1 2 3 ...
    public static void patternA(int n) {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= i; j++)
                System.out.print(j + " ");
            System.out.println();
        }
    }

    // Pattern B: Floyd's Triangle (sequential numbers)
    public static void floyds(int n) {
        int num = 1;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= i; j++)
                System.out.print(num++ + " ");
            System.out.println();
        }
    }

    // Pattern C: Multiplication table triangle
    public static void multiTable(int n) {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= i; j++)
                System.out.print((i * j) + "\t");
            System.out.println();
        }
    }

    public static void main(String[] args) {
        System.out.println("--- Pattern A ---");  patternA(4);
        System.out.println("--- Floyd's   ---");  floyds(4);
        System.out.println("--- Multi Table--");  multiTable(4);
    }
}
Explanation
  • Pattern A: Inner loop prints 1…i (resets each row)
  • Floyd's: Single counter num increments continuously across all rows
  • Multi table: Each cell = row Γ— col
  • Key insight: Understand whether inner loop variable resets or not
Time: O(nΒ²) Space: O(1)
Pascal's Triangle
Hard
Problem

Print Pascal's Triangle for n rows where each element = sum of two above.

Input: n = 5

    1
   1 1
  1 2 1
 1 3 3 1
1 4 6 4 1
Pattern Dynamic Programming Binomial
import java.util.*;

public class PascalsTriangle {

    public static List<List<Integer>> generate(int n) {
        List<List<Integer>> result = new ArrayList<>();

        for (int i = 0; i < n; i++) {
            List<Integer> row = new ArrayList<>();
            row.add(1); // First element always 1

            for (int j = 1; j < i; j++) {
                // Each element = sum of two above
                List<Integer> prev = result.get(i - 1);
                row.add(prev.get(j - 1) + prev.get(j));
            }

            if (i > 0) row.add(1); // Last element always 1
            result.add(row);
        }
        return result;
    }

    public static void print(int n) {
        List<List<Integer>> triangle = generate(n);
        for (int i = 0; i < n; i++) {
            // Print leading spaces for pyramid shape
            System.out.print(" ".repeat(n - i - 1));
            for (int val : triangle.get(i))
                System.out.print(val + " ");
            System.out.println();
        }
    }

    public static void main(String[] args) {
        print(6);
    }
}
Explanation
  • Edge elements: Always 1 (first and last of each row)
  • Middle elements: prev[j-1] + prev[j] from previous row
  • Build row by row: Each row depends only on the previous
  • Applications: Binomial coefficients, probability, combinations
Time: O(nΒ²) Space: O(nΒ²) to store all rows

OOP & Core Java

Page Object Model (POM) with Selenium
Medium
Problem

Implement the Page Object Model design pattern for a login page to keep test code and page logic separate.

POM Selenium Design Pattern OOP
import org.openqa.selenium.*;
import org.openqa.selenium.support.*;

// --- LoginPage.java (Page Object) ---
public class LoginPage {

    private WebDriver driver;

    // @FindBy replaces driver.findElement() calls
    @FindBy(id = "username")
    private WebElement usernameInput;

    @FindBy(id = "password")
    private WebElement passwordInput;

    @FindBy(css = "button[type='submit']")
    private WebElement loginBtn;

    @FindBy(css = ".error-msg")
    private WebElement errorMessage;

    public LoginPage(WebDriver driver) {
        this.driver = driver;
        // Initialise @FindBy elements
        PageFactory.initElements(driver, this);
    }

    public void login(String user, String pass) {
        usernameInput.clear();
        usernameInput.sendKeys(user);
        passwordInput.sendKeys(pass);
        loginBtn.click();
    }

    public String getErrorText() {
        return errorMessage.getText();
    }
}

// --- LoginTest.java (Test Class) ---
public class LoginTest {

    public static void main(String[] args) {
        WebDriver driver = new ChromeDriver();
        driver.get("https://example.com/login");

        LoginPage loginPage = new LoginPage(driver);
        loginPage.login("admin", "wrongpass");

        System.out.println(loginPage.getErrorText());
        // "Invalid credentials"

        driver.quit();
    }
}
Explanation
  • Separation: Page class holds locators & actions; test class holds assertions
  • @FindBy: Declares element using annotation instead of findElement()
  • PageFactory.initElements: Injects all @FindBy elements at runtime
  • Reusability: Any test can import LoginPage without repeating locators
  • Maintainability: If a locator changes, update only in one place
Pattern: Most common Selenium architecture in real projects
Data-Driven Testing with TestNG @DataProvider
Medium
Problem

Run the same test with multiple sets of input data using TestNG DataProvider β€” no code duplication.

TestNG DataProvider Data-Driven Automation
import org.testng.Assert;
import org.testng.annotations.*;

public class LoginDataDrivenTest {

    WebDriver driver;

    @BeforeMethod
    public void setUp() {
        driver = new ChromeDriver();
        driver.get("https://example.com/login");
    }

    // Supply multiple rows of test data
    @DataProvider(name = "loginData")
    public Object[][] getData() {
        return new Object[][] {
            { "admin",    "admin123",  "Dashboard"  },
            { "user1",    "pass123",   "Dashboard"  },
            { "invalid",  "wrong",     "Login"      },
            { "",         "",           "Login"      }
        };
    }

    // Test runs once per row in @DataProvider
    @Test(dataProvider = "loginData")
    public void testLogin(String user, String pass, String expectedTitle) {
        LoginPage page = new LoginPage(driver);
        page.login(user, pass);
        Assert.assertEquals(driver.getTitle(), expectedTitle,
            "Title mismatch for user: " + user);
    }

    @AfterMethod
    public void tearDown() {
        driver.quit();
    }
}
Explanation
  • @DataProvider: Returns Object[][] β€” each inner array is one test run
  • @Test(dataProvider): Links test method to its data source by name
  • Runs 4 times: Once per row β€” valid users, invalid, empty
  • @BeforeMethod / @AfterMethod: Fresh browser for each test run
  • Real project use: Data can also be loaded from Excel/CSV via Apache POI
Tip: Combine with Excel reading (Apache POI) for large datasets
Interface vs Abstract Class
Medium
Problem

Demonstrate when to use Interface vs Abstract Class β€” one of the most common Java interview questions for SDETs.

OOP Interface Abstract Interview
// Interface β€” defines a contract (WHAT to do)
interface Browser {
    void open(String url);
    void close();

    // Java 8+: default method allowed in interface
    default void screenshot(String path) {
        System.out.println("Screenshot saved to: " + path);
    }
}

// Abstract Class β€” partial implementation (HOW partially)
abstract class BasePage {
    protected WebDriver driver;

    public BasePage(WebDriver driver) {
        this.driver = driver;
        PageFactory.initElements(driver, this);
    }

    // Concrete method β€” reused by all subclasses
    public void waitForElement(WebElement el) {
        new WebDriverWait(driver, Duration.ofSeconds(10))
            .until(ExpectedConditions.visibilityOf(el));
    }

    // Subclasses MUST implement this
    public abstract String getPageTitle();
}

// Concrete Page inherits BasePage + implements Browser
public class LoginPage extends BasePage implements Browser {

    @FindBy(id = "username") WebElement usernameInput;

    public LoginPage(WebDriver driver) { super(driver); }

    @Override public void open(String url) { driver.get(url); }
    @Override public void close()         { driver.quit(); }
    @Override public String getPageTitle() { return driver.getTitle(); }
}
Explanation
  • Interface: Use when unrelated classes share a capability (e.g., multiple page types that can all take screenshots)
  • Abstract class: Use when classes share code & state (e.g., all pages need a WebDriver)
  • Multiple interface: Java supports implementing many interfaces but only one class extension
  • In SDET: BasePage (abstract) + Browser/Clickable (interface) is real-world POM architecture
Rule: "Is-a" β†’ Abstract class | "Can-do" β†’ Interface
Found this helpful? Sponsor on GitHub