2023. Number of Pairs of Strings With Concatenation Equal to Target
Problem Description
You are given an array of digit strings called nums
and a digit string called target
. Your task is to find how many pairs of indices (i, j)
exist where:
i
andj
are different indices (meaningi != j
)- When you concatenate
nums[i]
andnums[j]
together (in that order), the result equalstarget
For example, if nums = ["7", "23", "77"]
and target = "777"
, then:
nums[0] + nums[2] = "7" + "77" = "777"
equals target (this counts as one pair)nums[2] + nums[0] = "77" + "7" = "777"
equals target (this counts as another pair)
Note that concatenation means joining two strings together. So "12" + "34" = "1234"
.
The solution uses a brute force approach by checking every possible pair of indices. It iterates through all combinations where i
goes from 0 to n-1 and j
goes from 0 to n-1, checking if i != j
and if concatenating nums[i]
with nums[j]
produces the target string. The sum function counts how many such valid pairs exist.
Intuition
The key insight is that we need to find all possible ways to split the target
string into two parts, where each part comes from the nums
array. Since we're looking for concatenations that form the target, we need to check every possible pairing.
Think about it this way: if target = "777"
, it could potentially be formed by:
"7" + "77"
"77" + "7"
"777" + ""
(if empty string existed)- And so on...
Since we don't know in advance which elements in nums
could be the first part or the second part of a valid concatenation, the most straightforward approach is to try all possibilities.
For each element at index i
, we can pair it with any other element at index j
(where i != j
). We concatenate nums[i]
with nums[j]
and check if it matches our target
. This naturally leads to a nested loop structure where we examine all n × n
possible pairings, excluding cases where i == j
since we need different indices.
The beauty of this approach is its simplicity - we don't need to preprocess the data or use complex string matching algorithms. We just systematically check every valid pair and count how many produce our target string. The use of a generator expression with sum()
makes the implementation concise while maintaining clarity about what we're counting.
Solution Approach
The solution implements a brute force enumeration approach to solve this problem. Let's walk through the implementation step by step:
-
Get the array length: First, we determine
n = len(nums)
to know the bounds for our iteration. -
Double loop enumeration: We use two nested loops to enumerate all possible pairs:
- The outer loop variable
i
ranges from0
ton-1
- The inner loop variable
j
also ranges from0
ton-1
- This gives us all
n × n
possible combinations of indices
- The outer loop variable
-
Validation and counting: For each pair
(i, j)
, we check two conditions:i != j
: Ensures we're using different indices as requirednums[i] + nums[j] == target
: Checks if the concatenation matches our target string
-
Sum the results: The solution uses Python's
sum()
function with a generator expression. The expressioni != j and nums[i] + nums[j] == target
evaluates to:True
(counts as 1) when both conditions are metFalse
(counts as 0) otherwise
The entire logic is compressed into a single line:
sum(i != j and nums[i] + nums[j] == target for i in range(n) for j in range(n))
This generator expression iterates through all pairs, evaluates the boolean condition for each, and sums up the True
values (each True
contributes 1 to the sum).
Time Complexity: O(n² × m)
where n
is the length of the array and m
is the average length of strings (for string comparison)
Space Complexity: O(1)
as we only use constant extra space (not counting the input)
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example to understand how the solution works.
Given:
nums = ["2", "4", "24", "42"]
target = "244"
We need to find all pairs (i, j)
where i != j
and nums[i] + nums[j] == "244"
.
Step-by-step execution:
Let's trace through each iteration of our nested loops:
i | j | nums[i] | nums[j] | Concatenation | Equals target? | Count |
---|---|---|---|---|---|---|
0 | 0 | "2" | "2" | - | Skip (i == j) | 0 |
0 | 1 | "2" | "4" | "24" | No | 0 |
0 | 2 | "2" | "24" | "224" | No | 0 |
0 | 3 | "2" | "42" | "242" | No | 0 |
1 | 0 | "4" | "2" | "42" | No | 0 |
1 | 1 | "4" | "4" | - | Skip (i == j) | 0 |
1 | 2 | "4" | "24" | "424" | No | 0 |
1 | 3 | "4" | "42" | "442" | No | 0 |
2 | 0 | "24" | "2" | "242" | No | 0 |
2 | 1 | "24" | "4" | "244" | Yes! | 1 |
2 | 2 | "24" | "24" | - | Skip (i == j) | 1 |
2 | 3 | "24" | "42" | "2442" | No | 1 |
3 | 0 | "42" | "2" | "422" | No | 1 |
3 | 1 | "42" | "4" | "424" | No | 1 |
3 | 2 | "42" | "24" | "4224" | No | 1 |
3 | 3 | "42" | "42" | - | Skip (i == j) | 1 |
Result: We found exactly 1 valid pair: (i=2, j=1)
where nums[2] + nums[1] = "24" + "4" = "244"
.
The solution efficiently checks all 16 possible combinations (4×4), skips the 4 cases where i equals j, and evaluates the remaining 12 concatenations. The sum()
function counts each True
result as 1, giving us our final answer of 1.
Solution Implementation
1class Solution:
2 def numOfPairs(self, nums: List[str], target: str) -> int:
3 """
4 Count the number of pairs (i, j) where i != j and
5 concatenating nums[i] + nums[j] equals the target string.
6
7 Args:
8 nums: List of strings to form pairs from
9 target: Target string to match with concatenated pairs
10
11 Returns:
12 Number of valid pairs that concatenate to form target
13 """
14 n = len(nums)
15
16 # Count all pairs where indices are different and concatenation equals target
17 # Using generator expression with sum to count True values (True = 1, False = 0)
18 count = sum(
19 i != j and nums[i] + nums[j] == target
20 for i in range(n)
21 for j in range(n)
22 )
23
24 return count
25
1class Solution {
2 /**
3 * Counts the number of pairs (i, j) where i != j and
4 * concatenating nums[i] + nums[j] equals the target string.
5 *
6 * @param nums Array of strings to form pairs from
7 * @param target The target string to match with concatenated pairs
8 * @return The count of valid pairs
9 */
10 public int numOfPairs(String[] nums, String target) {
11 // Get the length of the input array
12 int arrayLength = nums.length;
13
14 // Initialize counter for valid pairs
15 int pairCount = 0;
16
17 // Iterate through all possible first elements
18 for (int i = 0; i < arrayLength; i++) {
19 // Iterate through all possible second elements
20 for (int j = 0; j < arrayLength; j++) {
21 // Check if indices are different and concatenation equals target
22 if (i != j && target.equals(nums[i] + nums[j])) {
23 pairCount++;
24 }
25 }
26 }
27
28 return pairCount;
29 }
30}
31
1class Solution {
2public:
3 int numOfPairs(vector<string>& nums, string target) {
4 // Get the size of the input array
5 int arraySize = nums.size();
6
7 // Initialize counter for valid pairs
8 int pairCount = 0;
9
10 // Iterate through each element as the first part of the pair
11 for (int i = 0; i < arraySize; ++i) {
12 // Iterate through each element as the second part of the pair
13 for (int j = 0; j < arraySize; ++j) {
14 // Check if indices are different and concatenation equals target
15 // nums[i] + nums[j] concatenates the two strings
16 if (i != j && nums[i] + nums[j] == target) {
17 pairCount++;
18 }
19 }
20 }
21
22 // Return the total count of valid pairs
23 return pairCount;
24 }
25};
26
1function numOfPairs(nums: string[], target: string): number {
2 // Get the size of the input array
3 const arraySize: number = nums.length;
4
5 // Initialize counter for valid pairs
6 let pairCount: number = 0;
7
8 // Iterate through each element as the first part of the pair
9 for (let i = 0; i < arraySize; i++) {
10 // Iterate through each element as the second part of the pair
11 for (let j = 0; j < arraySize; j++) {
12 // Check if indices are different and concatenation equals target
13 // nums[i] + nums[j] concatenates the two strings
14 if (i !== j && nums[i] + nums[j] === target) {
15 pairCount++;
16 }
17 }
18 }
19
20 // Return the total count of valid pairs
21 return pairCount;
22}
23
Time and Space Complexity
Time Complexity: O(n^2 × m)
The code uses two nested loops, each iterating through all n
elements of the nums
array, resulting in n^2
iterations. For each iteration, the code performs:
- String concatenation:
nums[i] + nums[j]
takesO(len(nums[i]) + len(nums[j]))
time - String comparison: comparing the concatenated string with
target
takesO(m)
time, wherem
is the length of the target string
In the worst case, the length of concatenated strings could be up to m
(when they form the target), so each comparison takes O(m)
time. Therefore, the overall time complexity is O(n^2 × m)
.
Space Complexity: O(m)
While the code doesn't explicitly create any data structures that grow with input size, the string concatenation operation nums[i] + nums[j]
creates a new temporary string for each comparison. This temporary string can have a maximum length of m
(the length of the target string). Although this temporary string is created and discarded in each iteration, at any given moment, the space used for this operation is O(m)
.
Note: The reference answer states O(1)
space complexity, which would be valid if we consider only auxiliary space excluding the temporary strings created during concatenation. However, technically, the string concatenation does use O(m)
space.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Counting Pairs Twice or Missing Order Sensitivity
A common mistake is misunderstanding that (i, j)
and (j, i)
are different pairs when the order matters in concatenation. Some might incorrectly optimize by only checking j > i
to avoid "duplicates", but this would miss valid pairs.
Incorrect approach:
# WRONG: This only counts unordered pairs
count = sum(
nums[i] + nums[j] == target
for i in range(n)
for j in range(i + 1, n) # Only checking j > i misses valid pairs!
)
Why it's wrong: Since concatenation is order-dependent, nums[i] + nums[j]
can be different from nums[j] + nums[i]
. For example, "7" + "77" = "777"
while "77" + "7" = "777"
are both valid but distinct pairs.
Correct approach: Check all pairs where i != j
, allowing both (i, j)
and (j, i)
to be counted separately.
2. Inefficient String Concatenation for Large Datasets
When dealing with large arrays or when the same elements appear multiple times, repeatedly concatenating strings can be inefficient.
Optimized solution using hash maps:
def numOfPairs(self, nums: List[str], target: str) -> int:
count = 0
freq = {}
# Count frequency of each string
for num in nums:
freq[num] = freq.get(num, 0) + 1
# Check each possible prefix
for i in range(1, len(target)):
prefix = target[:i]
suffix = target[i:]
if prefix in freq and suffix in freq:
if prefix == suffix:
# Same string used twice: n * (n-1) pairs
count += freq[prefix] * (freq[prefix] - 1)
else:
# Different strings: n1 * n2 pairs
count += freq[prefix] * freq[suffix]
return count
This optimization reduces time complexity from O(n² × m) to O(n + m²) where m is the length of the target string, which is much better when n is large and m is relatively small.
In a binary min heap, the minimum element can be found in:
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!