Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Insert and Delete Simulation

Problem Statement

Write a Java program that simulates text editing using StringBuilder by performing a sequence of insert and delete operations on a string. Each operation is either an insertion (adding a string at a specified index) or a deletion (removing characters from a start index to an end index). The program should process a sequence of operations and return the final string, testing with different sequences, including edge cases like empty strings, invalid indices, or empty operation lists. You can visualize this as editing a document on a word processor, where you insert new text or delete sections, with StringBuilder acting as an efficient editor to keep the changes smooth and fast.

Input: An initial string (possibly empty) and a sequence of operations, where each operation is either:

  • Insert: {type="insert", index, string} (insert string at index).
  • Delete: {type="delete", start, end} (delete characters from start to end-1). Output: The final string after applying all operations. Constraints:
  • Initial string length is between 0 and 10^5.
  • Number of operations is between 0 and 1000.
  • Strings to insert contain printable ASCII characters.
  • Indices are non-negative integers; invalid indices should be handled gracefully.
  • The input may be null or empty. Example:
  • Input: Initial string = "hello", operations = [insert(5, " world"), delete(0, 2)]
  • Output: "llo world"
  • Explanation: Insert " world" at index 5 → "hello world", then delete from index 0 to 1 → "llo world".
  • Input: Initial string = "", operations = [insert(0, "test")]
  • Output: "test"
  • Explanation: Insert "test" into empty string at index 0 → "test".

Pseudocode

FUNCTION simulateTextEditing(initial, operations)
    IF initial is null THEN
        SET initial to empty string
    ENDIF
    CREATE stringBuilder with initial
    FOR each operation in operations
        IF operation.type equals "insert" THEN
            IF operation.index is valid THEN
                CALL stringBuilder.insert(operation.index, operation.string)
            ENDIF
        ELSE IF operation.type equals "delete" THEN
            IF operation.start and operation.end are valid THEN
                CALL stringBuilder.delete(operation.start, operation.end)
            ENDIF
        ENDIF
    ENDFOR
    RETURN stringBuilder as string
ENDFUNCTION

FUNCTION main()
    SET testCases to array of (initial string, operations) pairs
    FOR each (initial, operations) in testCases
        PRINT initial string and operations
        CALL simulateTextEditing(initial, operations)
        PRINT resulting string
    ENDFOR
ENDFUNCTION

Algorithm Steps

  1. Check if the initial string is null; if so, set it to an empty string.
  2. Initialize a StringBuilder with the initial string.
  3. For each operation in the sequence: a. If the operation is "insert":
    • Verify the index is valid (0 ≤ index ≤ current StringBuilder length).
    • Insert the specified string at the index using StringBuilder.insert. b. If the operation is "delete":
    • Verify the start and end indices are valid (0 ≤ start ≤ end ≤ current StringBuilder length).
    • Delete the range from start to end-1 using StringBuilder.delete.
  4. Return the final StringBuilder content as a string.
  5. In the main method, test with different sequences of operations, including empty strings, invalid indices, and large sequences.

Java Implementation

import java.util.*;

public class InsertAndDeleteSimulation {
    // Class to represent an operation
    static class Operation {
        String type; // "insert" or "delete"
        int index;   // For insert: insertion point; for delete: start index
        String str;  // For insert: string to insert
        int end;     // For delete: end index

        // Constructor for insert operation
        Operation(String type, int index, String str) {
            this.type = type;
            this.index = index;
            this.str = str;
        }

        // Constructor for delete operation
        Operation(String type, int start, int end) {
            this.type = type;
            this.index = start;
            this.end = end;
        }
    }

    // Simulates text editing with insert and delete operations
    public String simulateTextEditing(String initial, List<Operation> operations) {
        if (initial == null) {
            initial = "";
        }
        StringBuilder sb = new StringBuilder(initial);
        
        for (Operation op : operations) {
            if (op.type.equals("insert")) {
                if (op.index >= 0 && op.index <= sb.length() && op.str != null) {
                    sb.insert(op.index, op.str);
                }
            } else if (op.type.equals("delete")) {
                if (op.index >= 0 && op.end <= sb.length() && op.index <= op.end) {
                    sb.delete(op.index, op.end);
                }
            }
        }
        return sb.toString();
    }

    // Main method to test text editing simulation
    public static void main(String[] args) {
        InsertAndDeleteSimulation simulator = new InsertAndDeleteSimulation();

        // Test cases
        List<Object[]> testCases = new ArrayList<>();
        
        // Test case 1: Normal insert and delete
        List<Operation> ops1 = new ArrayList<>();
        ops1.add(new Operation("insert", 5, " world"));
        ops1.add(new Operation("delete", 0, 2));
        testCases.add(new Object[]{"hello", ops1});
        
        // Test case 2: Empty string with insert
        List<Operation> ops2 = new ArrayList<>();
        ops2.add(new Operation("insert", 0, "test"));
        testCases.add(new Object[]{"", ops2});
        
        // Test case 3: Empty operations
        List<Operation> ops3 = new ArrayList<>();
        testCases.add(new Object[]{"abc", ops3});
        
        // Test case 4: Large sequence of operations
        List<Operation> ops4 = new ArrayList<>();
        ops4.add(new Operation("insert", 0, "start"));
        for (int i = 1; i <= 10; i++) {
            ops4.add(new Operation("insert", i * 5, "x"));
            ops4.add(new Operation("delete", i * 2, i * 2 + 1));
        }
        testCases.add(new Object[]{"base", ops4});
        
        // Test case 5: Null initial string and invalid indices
        List<Operation> ops5 = new ArrayList<>();
        ops5.add(new Operation("insert", 10, "invalid"));
        ops5.add(new Operation("delete", -1, 5));
        testCases.add(new Object[]{null, ops5});

        // Run test cases
        for (int i = 0; i < testCases.size(); i++) {
            String initial = (String) testCases.get(i)[0];
            List<Operation> ops = (List<Operation>) testCases.get(i)[1];
            System.out.println("Test case " + (i + 1) + ":");
            System.out.println("Initial string: \"" + (initial != null ? initial : "null") + "\"");
            System.out.println("Operations:");
            for (Operation op : ops) {
                if (op.type.equals("insert")) {
                    System.out.println("  Insert \"" + op.str + "\" at index " + op.index);
                } else {
                    System.out.println("  Delete from index " + op.index + " to " + op.end);
                }
            }
            String result = simulator.simulateTextEditing(initial, ops);
            System.out.println("Result: \"" + (result != null && result.length() > 50 ? result.substring(0, 50) + "..." : result) + "\"\n");
        }
    }
}

Output

Running the main method produces:

Test case 1:
Initial string: "hello"
Operations:
  Insert " world" at index 5
  Delete from index 0 to 2
Result: "llo world"

Test case 2:
Initial string: ""
Operations:
  Insert "test" at index 0
Result: "test"

Test case 3:
Initial string: "abc"
Operations:
Result: "abc"

Test case 4:
Initial string: "base"
Operations:
  Insert "start" at index 0
  Insert "x" at index 5
  Delete from index 2 to 3
  Insert "x" at index 10
  Delete from index 4 to 5
  Insert "x" at index 15
  Delete from index 6 to 7
  Insert "x" at index 20
  Delete from index 8 to 9
  Insert "x" at index 25
  Delete from index 10 to 11
  Insert "x" at index 30
  Delete from index 12 to 13
  Insert "x" at index 35
  Delete from index 14 to 15
  Insert "x" at index 40
  Delete from index 16 to 17
  Insert "x" at index 45
  Delete from index 18 to 19
  Insert "x" at index 50
  Delete from index 20 to 21
Result: "staxrtxxx"

Test case 5:
Initial string: "null"
Operations:
  Insert "invalid" at index 10
  Delete from index -1 to 5
Result: ""

Explanation:

  • Test case 1: "hello" → insert " world" at 5 → "hello world" → delete 0 to 2 → "llo world".
  • Test case 2: "" → insert "test" at 0 → "test".
  • Test case 3: "abc" with no operations → "abc".
  • Test case 4: "base" → complex sequence of inserts and deletes → "staxrtxxx".
  • Test case 5: Null initial string becomes "", invalid indices are skipped → "".

How It Works

  • StringBuilder: Efficient for insert and delete operations due to mutable character array.
  • Operation Class: Represents insert (index, string) or delete (start, end) operations.
  • simulateTextEditing:
    • Initializes StringBuilder with initial string (empty if null).
    • Processes each operation, checking index validity before applying insert or delete.
  • Example Trace (Test case 1):
    • Initial: sb = "hello".
    • Insert " world" at 5: sb = "hello world".
    • Delete 0 to 2: sb = "llo world".
  • Main Method: Tests with normal operations, empty string, no operations, large sequence, and invalid cases.
  • Validation: Skips invalid operations (e.g., out-of-bounds indices) to ensure robustness.

Complexity Analysis Table

OperationTime ComplexitySpace Complexity
InsertO(n + m)O(m)
DeleteO(n)O(1)
Full AlgorithmO(k * (n + m))O(n + k * m)

Note:

  • n is the current length of the StringBuilder, m is the length of the inserted string, k is the number of operations.
  • Insert: O(n + m) due to shifting characters and copying the new string.
  • Delete: O(n) due to shifting characters after deletion.
  • Full algorithm: O(k * (n + m)) for k operations, worst case when each operation involves the maximum string length.
  • Space: O(n + k * m) for the StringBuilder, including inserted strings.

✅ Tip: Use StringBuilder for efficient text editing operations like insert and delete. Test with invalid indices and edge cases to ensure the program handles them gracefully.

⚠ Warning: Validate indices before performing operations to avoid IndexOutOfBoundsException. Handle null inputs to prevent unexpected behavior.