In this article, we will solve the String Chain Formation problem, where we need to determine whether we can arrange a given array of strings in such a way that the last character of one string matches the first character of the next. This problem is commonly encountered in word puzzles, graph theory, and algorithmic challenges. We will explore an efficient graph-based approach and an alternative sorting-based method to check for a valid chain formation.
Understanding the Problem
Given an array of strings, determine whether it is possible to arrange them in a sequence such that the last character of one string matches the first character of the next string.
Example
Input:
String[] words = {“apple”, “elephant”, “tiger”, “rat”};
Output:
Possible Chain: [“apple”, “elephant”, “tiger”, “rat”]
Explanation:
"apple"
ends with'e'
, and"elephant"
starts with'e'
."elephant"
ends with't'
, and"tiger"
starts with't'
."tiger"
ends with'r'
, and"rat"
starts with'r'
.- Since all words connect, a valid chain is possible.
Approach to Solve the Problem
- Build character mappings:
- Store first and last characters of each word.
- Use a HashMap to count occurrences of each starting and ending letter.
- Check Eulerian Path conditions:
- A valid path exists if at most one character has
+1
difference in start and end counts.
- A valid path exists if at most one character has
- Try forming a sequence using backtracking (DFS or Graph approach).
Java Implementation – Using Graph (Optimal Approach)
package com.javacodepoint.stringarray;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class StringChainFormation {
// Method to check if the given words can form a valid chain
public static boolean canFormStringChain(String[] words) {
Map<Character, Integer> inDegree = new HashMap<>();
Map<Character, Integer> outDegree = new HashMap<>();
Map<Character, List<String>> adjacencyList = new HashMap<>();
Set<Character> uniqueChars = new HashSet<>();
// Build graph representation
for (String word : words) {
char first = word.charAt(0);
char last = word.charAt(word.length() - 1);
outDegree.put(first, outDegree.getOrDefault(first, 0) + 1);
inDegree.put(last, inDegree.getOrDefault(last, 0) + 1);
adjacencyList.computeIfAbsent(first, k -> new ArrayList<>()).add(word);
uniqueChars.add(first);
uniqueChars.add(last);
}
// Check Eulerian Path conditions
int startCount = 0, endCount = 0;
for (char c : uniqueChars) {
int in = inDegree.getOrDefault(c, 0);
int out = outDegree.getOrDefault(c, 0);
if (out - in == 1) {
startCount++;
} else if (in - out == 1) {
endCount++;
} else if (in != out) {
return false;
}
}
return (startCount == 1 && endCount == 1) || (startCount == 0 && endCount == 0);
}
public static void main(String[] args) {
String[] words = {"apple", "elephant", "tiger", "rat"};
if (canFormStringChain(words)) {
System.out.println("Yes, the words can form a valid chain.");
} else {
System.out.println("No, a valid chain cannot be formed.");
}
}
}
OUTPUT:
Yes, the words can form a valid chain.
Explanation of the Code
- Build a character frequency map:
- Track how many times each character appears at the start and end of words.
- Store adjacency lists of words grouped by their first letter.
- Check Eulerian Path conditions:
- At most one character should have
+1
outgoing edge. - At most one character should have
+1
incoming edge. - All other characters should have equal
in-degree
andout-degree
.
- At most one character should have
- Return
true
if conditions match, otherwise returnfalse
.
Alternative Approach: Using Simple Sorting (Less Efficient)
import java.util.Arrays;
public class SimpleStringChain {
public static boolean canArrangeStrings(String[] words) {
Arrays.sort(words); // Sort alphabetically (not always correct but helps)
for (int i = 0; i < words.length - 1; i++) {
if (words[i].charAt(words[i].length() - 1) != words[i + 1].charAt(0)) {
return false; // Break if chain rule is not satisfied
}
}
return true;
}
public static void main(String[] args) {
String[] words = {"apple", "elephant", "tiger", "rat"};
if (canArrangeStrings(words)) {
System.out.println("Yes, a valid chain can be formed.");
} else {
System.out.println("No, a valid chain cannot be formed.");
}
}
}
Conclusion
This problem is closely related to Eulerian Path in Graph Theory, where we check incoming and outgoing edges to determine if a path exists.
You can learn the Top 20 string array programs for interview preparation (Click here).