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}(insertstringatindex). - Delete:
{type="delete", start, end}(delete characters fromstarttoend-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
- Check if the initial string is null; if so, set it to an empty string.
- Initialize a StringBuilder with the initial string.
- 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.
- Return the final StringBuilder content as a string.
- In the
mainmethod, 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
insertordelete.
- Example Trace (Test case 1):
- Initial:
sb = "hello". - Insert
" world"at 5:sb = "hello world". - Delete 0 to 2:
sb = "llo world".
- Initial:
- 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
| Operation | Time Complexity | Space Complexity |
|---|---|---|
| Insert | O(n + m) | O(m) |
| Delete | O(n) | O(1) |
| Full Algorithm | O(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.