Largest Merge Of Two Strings
Problem
You are given two strings word1 and word2. You want to construct a string
merge in the following way: while either word1 or word2 are non-empty, choose one of the following options:
- If
word1is non-empty, append the first character inword1tomergeand delete it fromword1.- For example, if
word1 = "abc"andmerge = "dv", then after choosing this operation,word1 = "bc"andmerge = "dva".
- For example, if
- If
word2is non-empty, append the first character inword2tomergeand delete it fromword2.- For example, if
word2 = "abc"andmerge = "", then after choosing this operation,word2 = "bc"andmerge = "a".
- For example, if
Return _the lexicographicallylargest _merge you can construct.
A string a is lexicographically larger than a string b (of the same length) if in the first position where a and b differ, a has a character strictly larger than the corresponding character in b. For example, "abcd"
is lexicographically larger than "abcc" because the first position they differ is at the fourth character, and d is greater than c.
Examples
Example 1
Input: word1 = "cabaa", word2 = "bcaaa"
Output: "cbcabaaaaa"
Explanation: One way to get the lexicographically largest merge is:
- Take from word1: merge = "c", word1 = "abaa", word2 = "bcaaa"
- Take from word2: merge = "cb", word1 = "abaa", word2 = "caaa"
- Take from word2: merge = "cbc", word1 = "abaa", word2 = "aaa"
- Take from word1: merge = "cbca", word1 = "baa", word2 = "aaa"
- Take from word1: merge = "cbcab", word1 = "aa", word2 = "aaa"
- Append the remaining 5 a's from word1 and word2 at the end of merge.
Example 2
Input: word1 = "abcabc", word2 = "abdcaba"
Output: "abdcabcabcaba"
Constraints
1 <= word1.length, word2.length <= 3000word1andword2consist only of lowercase English letters.
Solution
Method 1 – Greedy Lexicographical Merge
Intuition
To get the lexicographically largest merge, always pick the first character from the string whose remaining suffix is lexicographically larger. This ensures the merge is as large as possible at every step.
Approach
- Use two pointers for word1 and word2.
- At each step, compare the remaining substrings word1[i:] and word2[j:].
- If word1[i:] > word2[j:], append word1[i] to the result and increment i.
- Otherwise, append word2[j] to the result and increment j.
- Continue until both strings are exhausted.
- Return the merged string.
Code
C++
class Solution {
public:
string largestMerge(string word1, string word2) {
int i = 0, j = 0, n = word1.size(), m = word2.size();
string ans;
while (i < n || j < m) {
if (word1.substr(i) > word2.substr(j)) ans += word1[i++];
else ans += word2[j++];
}
return ans;
}
};
Go
func largestMerge(word1, word2 string) string {
i, j := 0, 0
n, m := len(word1), len(word2)
ans := make([]byte, 0, n+m)
for i < n || j < m {
if word1[i:] > word2[j:] {
ans = append(ans, word1[i])
i++
} else {
ans = append(ans, word2[j])
j++
}
}
return string(ans)
}
Java
class Solution {
public String largestMerge(String word1, String word2) {
int i = 0, j = 0, n = word1.length(), m = word2.length();
StringBuilder ans = new StringBuilder();
while (i < n || j < m) {
if (word1.substring(i).compareTo(word2.substring(j)) > 0) ans.append(word1.charAt(i++));
else ans.append(word2.charAt(j++));
}
return ans.toString();
}
}
Kotlin
class Solution {
fun largestMerge(word1: String, word2: String): String {
var i = 0; var j = 0
val n = word1.length; val m = word2.length
val ans = StringBuilder()
while (i < n || j < m) {
if (word1.substring(i) > word2.substring(j)) ans.append(word1[i++])
else ans.append(word2[j++])
}
return ans.toString()
}
}
Python
class Solution:
def largestMerge(self, word1: str, word2: str) -> str:
i, j = 0, 0
n, m = len(word1), len(word2)
ans = []
while i < n or j < m:
if word1[i:] > word2[j:]:
ans.append(word1[i])
i += 1
else:
ans.append(word2[j])
j += 1
return ''.join(ans)
Rust
impl Solution {
pub fn largest_merge(word1: String, word2: String) -> String {
let (mut i, mut j) = (0, 0);
let n = word1.len();
let m = word2.len();
let w1 = word1.as_bytes();
let w2 = word2.as_bytes();
let mut ans = Vec::with_capacity(n + m);
while i < n || j < m {
if &w1[i..] > &w2[j..] {
ans.push(w1[i]);
i += 1;
} else {
ans.push(w2[j]);
j += 1;
}
}
String::from_utf8(ans).unwrap()
}
}
TypeScript
class Solution {
largestMerge(word1: string, word2: string): string {
let i = 0, j = 0, n = word1.length, m = word2.length;
let ans = '';
while (i < n || j < m) {
if (word1.slice(i) > word2.slice(j)) ans += word1[i++];
else ans += word2[j++];
}
return ans;
}
}
Complexity
- ⏰ Time complexity:
O((n+m)^2), where n and m are the lengths of word1 and word2. Each comparison of suffixes can take O(n+m) time. - 🧺 Space complexity:
O(n+m), for the result string.