Longest Unequal Adjacent Groups Subsequence II
MediumUpdated: Aug 2, 2025
Practice on:
Problem
You are given a string array words, and an array groups, both arrays having length n.
The hamming distance between two strings of equal length is the number of positions at which the corresponding characters are different.
You need to select the longest subsequence from an array of indices [0, 1, ..., n - 1], such that for the subsequence denoted as [i0, i1, ..., ik-1] having length k, the following holds:
- For adjacent indices in the subsequence, their corresponding groups are unequal, i.e.,
groups[ij] != groups[ij+1], for eachjwhere0 < j + 1 < k. words[ij]andwords[ij+1]are equal in length, and the hamming distance between them is1, where0 < j + 1 < k, for all indices in the subsequence.
Return a string array containing the words corresponding to the indices (in order) in the selected subsequence. If there are multiple answers, return any of them.
Note: strings in words may be unequal in length.
Examples
Example 1:
Input: words = ["bab","dab","cab"], groups = [1,2,2]
Output:["bab","cab"]
Explanation: A subsequence that can be selected is `[0,2]`.
* `groups[0] != groups[2]`
* `words[0].length == words[2].length`, and the hamming distance between them is 1.
So, a valid answer is `[words[0],words[2]] = ["bab","cab"]`.
Another subsequence that can be selected is `[0,1]`.
* `groups[0] != groups[1]`
* `words[0].length == words[1].length`, and the hamming distance between them is `1`.
So, another valid answer is `[words[0],words[1]] = ["bab","dab"]`.
It can be shown that the length of the longest subsequence of indices that
satisfies the conditions is `2`.
Example 2:
Input: words = ["a","b","c","d"], groups = [1,2,3,4]
Output:["a","b","c","d"]
Explanation: We can select the subsequence `[0,1,2,3]`.
It satisfies both conditions.
Hence, the answer is `[words[0],words[1],words[2],words[3]] =
["a","b","c","d"]`.
It has the longest length among all subsequences of indices that satisfy the
conditions.
Hence, it is the only answer.
Constraints:
1 <= n == words.length == groups.length <= 10001 <= words[i].length <= 101 <= groups[i] <= nwordsconsists of distinct strings.words[i]consists of lowercase English letters.
Solution
Method 1 - DP
Here is the approach:
- DP Array Initialization:
dp[i]: Stores the length of the longest subsequence ending at indexi.prev[i]: Tracks the prior index in the optimal subsequence to allow backtracking.
- Conditions to Extend Subsequence:
checkmethod ensures that two strings have:- Equal lengths.
- Exactly one character difference (Hamming distance of 1).
- Groups at the indices must be different.
- Backtracking:
- After calculating
dpvalues, backtrack using theprevarray starting from the index with the maximumdpvalue (maxIndex).
- After calculating
Code
Java
class Solution {
public List<String> getWordsInLongestSubsequence(
String[] words, int[] groups
) {
int n = words.length;
int[] dp = new int[n]; // Tracks length of the longest subsequence
int[] prev = new int[n]; // Backtracking from longest subsequence
Arrays.fill(dp, 1); // Base case: every word is a subsequence of length 1
Arrays.fill(prev, -1);
int maxIndex = 0; // Track the index of the longest subsequence
// Build up the DP array by iterating through all pairs of indices
for (int i = 1; i < n; i++) {
for (int j = 0; j < i; j++) {
if (isValid(words[i], words[j], groups[i], groups[j]) && dp[j] + 1 > dp[i]) {
dp[i] = dp[j] + 1;
prev[i] = j; // Connect sequences for backtracking
}
}
// Update the index with the maximum subsequence length
if (dp[i] > dp[maxIndex]) {
maxIndex = i;
}
}
// Backtrack from the index with the longest subsequence
List<String> subsequence = new ArrayList<>();
for (int i = maxIndex; i >= 0; i = prev[i]) {
subsequence.add(words[i]);
}
Collections.reverse(subsequence); // Reverse to maintain order
return subsequence;
}
// Helper function: checks if two words can be part of the subsequence
private boolean isValid(String word1, String word2, int group1, int group2) {
if (word1.length() != word2.length() || group1 == group2) return false;
int diff = 0;
for (int i = 0; i < word1.length(); i++) {
if (word1.charAt(i) != word2.charAt(i)) diff++;
if (diff > 1) return false; // Ensure only one character differs
}
return diff == 1; // Return true if precisely one difference exists
}
}
Python
class Solution:
def getWordsInLongestSubsequence(self, words: List[str], groups: List[int]) -> List[str]:
n = len(words)
dp = [1] * n # Tracks the length of the longest subsequence
prev = [-1] * n # Tracks previous index in the subsequence
max_index = 0 # Index of the longest subsequence
# Helper function: Check if two words satisfy conditions
def is_valid(word1: str, word2: str, group1: int, group2: int) -> bool:
if len(word1) != len(word2) or group1 == group2:
return False
diff = sum(c1 != c2 for c1, c2 in zip(word1, word2)) # Count character differences
return diff == 1
# Build DP array and track previous indices
for i in range(1, n):
for j in range(i):
if is_valid(words[i], words[j], groups[i], groups[j]) and dp[j] + 1 > dp[i]:
dp[i] = dp[j] + 1
prev[i] = j # Update backtracking information
if dp[i] > dp[max_index]:
max_index = i # Update maximum subsequence index
# Backtrack to construct the subsequence
subsequence = []
while max_index != -1:
subsequence.append(words[max_index])
max_index = prev[max_index]
return subsequence[::-1] # Reverse to maintain order
Complexity
- ⏰ Time complexity:
O(n^2*m), wherenis the number of words andmis the average length of the words.- Outer loop runs
ntimes. - Inner loop runs at most
ntimes for eachi. checkmethod runs for the length of the strings.
- Outer loop runs
- 🧺 Space complexity:
O(n)for usingdpandprevarray.