Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Selected Reading
Check whether we can form string2 by deleting some characters from string1 without reordering the characters of any string - JavaScript
In this problem, we need to determine whether we can form string2 by removing some characters from string1 without changing the order of characters in either string. This is essentially checking if string2 is a subsequence of string1.
Understanding the Problem
We want to check if the second string can be formed from the first string while preserving character order. Let's look at some examples:
// Example 1: Can form "ale" from "apple"
let s1 = "apple";
let s2 = "ale";
console.log("Can form '" + s2 + "' from '" + s1 + "'?");
// Expected: true (a-p-p-l-e contains a-l-e in order)
Can form 'ale' from 'apple'?
// Example 2: Cannot form "pan" from "banana"
let s3 = "banana";
let s4 = "pan";
console.log("Can form '" + s4 + "' from '" + s3 + "'?");
// Expected: false ('p' doesn't exist in "banana")
Can form 'pan' from 'banana'?
Algorithm Approach
We'll use a two-pointer technique:
- Initialize two pointers: one for string1 (i) and one for string2 (j)
- Iterate through both strings simultaneously
- When characters match, advance both pointers
- When they don't match, only advance the string1 pointer
- If we've matched all characters in string2, return true
Implementation
function canFormString(string1, string2) {
let i = 0; // Pointer for string1
let j = 0; // Pointer for string2
// Continue until we've checked all of string2 or reached end of string1
while (j < string2.length && i < string1.length) {
if (string1[i] === string2[j]) {
// Characters match - advance both pointers
i++;
j++;
} else {
// Characters don't match - only advance string1 pointer
i++;
}
}
// Return true if we found all characters of string2
return j === string2.length;
}
// Test cases
console.log("Test 1:", canFormString("apple", "ale"));
console.log("Test 2:", canFormString("banana", "pan"));
console.log("Test 3:", canFormString("hello world", "helo"));
console.log("Test 4:", canFormString("programming", "gramin"));
Test 1: true Test 2: false Test 3: true Test 4: true
Step-by-Step Example
Let's trace through "apple" and "ale":
function canFormStringWithTrace(string1, string2) {
let i = 0, j = 0;
console.log("Checking if '" + string2 + "' can be formed from '" + string1 + "'");
while (j < string2.length && i < string1.length) {
console.log("Comparing '" + string1[i] + "' with '" + string2[j] + "'");
if (string1[i] === string2[j]) {
console.log("Match found! Advancing both pointers");
i++;
j++;
} else {
console.log("No match. Advancing string1 pointer only");
i++;
}
}
let result = j === string2.length;
console.log("Result:", result);
return result;
}
canFormStringWithTrace("apple", "ale");
Checking if 'ale' can be formed from 'apple' Comparing 'a' with 'a' Match found! Advancing both pointers Comparing 'p' with 'l' No match. Advancing string1 pointer only Comparing 'p' with 'l' No match. Advancing string1 pointer only Comparing 'l' with 'l' Match found! Advancing both pointers Comparing 'e' with 'e' Match found! Advancing both pointers Result: true
Complexity Analysis
| Complexity Type | Value | Explanation |
|---|---|---|
| Time Complexity | O(m + n) | We traverse each string at most once |
| Space Complexity | O(1) | Only using constant extra space for pointers |
Conclusion
The two-pointer approach efficiently determines if one string is a subsequence of another in linear time. This solution maintains character order and works well for checking if string2 can be formed by deleting characters from string1.
Advertisements
