Similar Problems
Similar Problems not available
Largest Merge Of Two Strings - Leetcode Solution
Companies:
LeetCode: Largest Merge Of Two Strings Leetcode Solution
Difficulty: Medium
Topics: greedy string two-pointers
Problem Statement:
Given two strings word1 and word2, return the largest string such that every substring in the string can be rearranged to form one of the words in the input.
If there is more than one answer, return any of them. If there is no answer, return an empty string.
Example 1: Input: word1 = "abcabc", word2 = "abdcaba" Output: "abcabcabdcaba"
Example 2: Input: word1 = "ab", word2 = "cd" Output: "abcd"
Example 3: Input: word1 = "a", word2 = "a" Output: "a"
Example 4: Input: word1 = "a"*1000, word2 = "b"*1000 Output: ""
Approach:
The key concept used in this problem is to break the strings into smaller substrings and then combine them to obtain the largest possible string. In order to do this efficiently, we can use a graph representation where the nodes represent the substrings and the edges represent the possible ordering of these substrings.
We can find all the valid substrings of the given input strings word1
and word2
using a recursive function. For each substring, we can calculate its frequency count and store it along with the string in a dictionary.
Next, we can create a directed graph where each node represents a substring and there is an edge from node A to node B if and only if we can form the string B by merging the substrings represented by the nodes in the path from A to B. This can be done by comparing the frequency count of each character in the two substrings represented by the nodes.
Finally, we can traverse this graph to find the longest path from a starting node to an ending node. The longest path will represent the largest string that can be formed by merging the given input strings.
Solution:
def largestMerge(word1: str, word2: str) -> str:
def generate_substrings(s: str, substrings: set):
if s:
substrings.add(s)
generate_substrings(s[1:], substrings)
generate_substrings(s[:-1], substrings)
w1_substrings, w2_substrings = set(), set()
generate_substrings(word1, w1_substrings)
generate_substrings(word2, w2_substrings)
substring_counts = {}
for s in w1_substrings | w2_substrings:
counts = [0] * 26
for c in s:
counts[ord(c) - ord('a')] += 1
substring_counts[s] = tuple(counts)
graph = {s: set() for s in substring_counts}
for s1 in substring_counts:
for s2 in substring_counts:
if s1 != s2 and substring_counts[s1] == substring_counts[s2]:
graph[s1].add(s2)
longest_path = ''
for node in graph:
stack, visited = [(node, node)], set()
while stack:
curr, path = stack.pop()
if curr in visited:
continue
visited.add(curr)
if len(path) > len(longest_path) or (
len(path) == len(longest_path) and path > longest_path):
longest_path = path
for neighbor in graph[curr]:
stack.append((neighbor, path + neighbor))
return longest_path
Explanation:
-
First, we define a wrapper function
largestMerge
that takes in two strings as input and returns the largest possible merged string. -
We define a recursive helper function
generate_substrings
that takes in a string and a set of substrings. This function generates all possible substrings of the input string and adds them to the set of substrings. -
We generate the set of substrings for both
word1
andword2
using thegenerate_substrings
function and store them inw1_substrings
andw2_substrings
, respectively. -
Next, we generate a dictionary
substring_counts
that stores the frequency count of each character in each substring. For this, we loop through all the substrings in the union ofw1_substrings
andw2_substrings
and calculate their frequency counts using a list of size 26 (one for each lowercase character), initialized with zeros. We then store the resulting tuple of frequency counts in thesubstring_counts
dictionary. -
We create a directed graph
graph
where each node represents a substring and there is an edge from node A to node B if and only if we can form the string B by merging the substrings represented by the nodes in the path from A to B. For this, we loop through all pairs of substrings and check if they have the same frequency counts, indicating that they can be combined to form a larger string. If so, we add an edge from the node representing the first substring to the node representing the second substring. -
We initialize the variable
longest_path
to the empty string. -
We loop through each node in the
graph
and use a depth-first traversal with a stack to find the longest path from that node to another node in the graph. For this, we start at the current node, push it onto the stack along with its string representation, and pop nodes and their paths from the stack until it is empty. We skip any nodes that have been already visited. -
If the length of the current path is longer than that of
longest_path
, or if the lengths are the same but the current path is lexicographically larger, we updatelongest_path
. -
Finally, we return the
longest_path
.
Time Complexity:
The time complexity of the solution is O(N^2 log N) where N is the total number of substrings obtained from both the input strings. This is because we need to generate all possible substrings and then compare them with each other to create the graph. The DFS traversal takes O(N log N) time, as there can be at most N nodes and each node can have up to N neighbors in the worst case.
Space Complexity:
The space complexity of the solution is O(N^2) where N is the total number of substrings obtained from both the input strings. This is because we need to store all possible substrings and their frequency counts, as well as the graph of all possible paths. However, this can be optimized by using a hashmap instead of a set to store the substrings in the graph.
Largest Merge Of Two Strings Solution Code
1