Before and After Puzzle

Concatenate phrases sharing a boundary word — group by first word and last word.

Medium
Time O(N^2 * L) Space O(N)
LeetCode
5 min read
hash-map strings sorting

Problem#

Given a list of phrases, return all distinct “puzzle” phrases formed by joining two phrases such that the last word of the first equals the first word of the second. The shared word should appear once in the result. Return the answer sorted, deduplicated.

Examples#

  • phrases = ["mission statement","a quick bite to eat","a chip off the old block","chocolate bar","mission impossible","a man on a mission","block party","eat my words","bar of soap"] → contains things like "a chip off the old block party", "chocolate bar of soap".

Constraints#

  • 1 <= phrases.length <= 100, 1 <= phrases[i].length <= 100.

Hints#

Hint
For each pair (i, j) with i != j, check if phrases[i]’s last word equals phrases[j]’s first word. Pre-extract first/last to avoid repeated parsing.

Approach#

Extract firstWord and lastWord for each phrase. For every ordered pair (i, j) with i != j, if lastWord[i] == firstWord[j], concat with the boundary word appearing once. Use a set for dedupe and final sort.

Solution#

Before and After Puzzle
class Solution {
pair<string,string> firstLast(const string& p) {
int sp1 = p.find(' ');
int sp2 = p.rfind(' ');
string first = sp1 == (int)string::npos ? p : p.substr(0, sp1);
string last = sp2 == (int)string::npos ? p : p.substr(sp2 + 1);
return {first, last};
}
public:
vector<string> beforeAndAfterPuzzles(vector<string>& phrases) {
int n = phrases.size();
vector<pair<string,string>> fl(n);
for (int i = 0; i < n; ++i) fl[i] = firstLast(phrases[i]);
set<string> uniq;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (i == j) continue;
if (fl[i].second == fl[j].first) {
// concat dropping the duplicate boundary word
int sp = phrases[j].find(' ');
string tail = sp == (int)string::npos ? "" : phrases[j].substr(sp);
uniq.insert(phrases[i] + tail);
}
}
}
return {uniq.begin(), uniq.end()};
}
};

Editorial#

Pre-extracting first/last avoids re-parsing inside the O(N^2) loop. The dedupe set simultaneously sorts the output — important because two different pairs can produce the same merged string. The boundary word appears once because we keep phrases[i] whole and strip the first word from phrases[j].

Complexity#

  • Time: O(N^2 * L).
  • Space: O(N * L) for the result.

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.