{x}
blog image

Rearrange Characters to Make Target String

You are given two 0-indexed strings s and target. You can take some letters from s and rearrange them to form new strings.

Return the maximum number of copies of target that can be formed by taking letters from s and rearranging them.

 

Example 1:

Input: s = "ilovecodingonleetcode", target = "code"
Output: 2
Explanation:
For the first copy of "code", take the letters at indices 4, 5, 6, and 7.
For the second copy of "code", take the letters at indices 17, 18, 19, and 20.
The strings that are formed are "ecod" and "code" which can both be rearranged into "code".
We can make at most two copies of "code", so we return 2.

Example 2:

Input: s = "abcba", target = "abc"
Output: 1
Explanation:
We can make one copy of "abc" by taking the letters at indices 0, 1, and 2.
We can make at most one copy of "abc", so we return 1.
Note that while there is an extra 'a' and 'b' at indices 3 and 4, we cannot reuse the letter 'c' at index 2, so we cannot make a second copy of "abc".

Example 3:

Input: s = "abbaccaddaeea", target = "aaaaa"
Output: 1
Explanation:
We can make one copy of "aaaaa" by taking the letters at indices 0, 3, 6, 9, and 12.
We can make at most one copy of "aaaaa", so we return 1.

 

Constraints:

  • 1 <= s.length <= 100
  • 1 <= target.length <= 10
  • s and target consist of lowercase English letters.

 

Note: This question is the same as 1189: Maximum Number of Balloons.

Solution Explanation

This problem asks to find the maximum number of times we can create the target string using the characters from the s string. The solution involves using character counts to efficiently determine this.

Approach:

  1. Count Character Frequencies: We use a frequency counter (a hash map or array) to store the frequency of each character in both s and target. This allows for quick lookups of character counts.

  2. Calculate Maximum Copies: For each character present in target, we determine how many times it can be used to form copies of target. This is done by integer division of the character's frequency in s by its frequency in target. The minimum of these values across all characters in target represents the maximum number of copies of target that can be formed.

Time and Space Complexity:

  • Time Complexity: O(m + n), where 'm' is the length of s and 'n' is the length of target. The character counting step is linear to the lengths of the strings. The calculation of the maximum number of copies is done in O(k), where k is the number of unique characters in target (which is at most 26). Therefore, the overall time complexity is dominated by the character counting step.

  • Space Complexity: O(1). We use constant extra space for frequency counters (arrays of size 26 for lowercase English alphabets). This space is independent of the input string lengths.

Code Explanation (Python):

The Python solution leverages the Counter object from the collections module, which simplifies the character counting process.

from collections import Counter
 
class Solution:
    def rearrangeCharacters(self, s: str, target: str) -> int:
        cnt1 = Counter(s)  # Count character frequencies in s
        cnt2 = Counter(target) # Count character frequencies in target
 
        return min(cnt1[c] // v for c, v in cnt2.items() if v > 0)  #Calculate max copies
 

The line min(cnt1[c] // v for c, v in cnt2.items() if v >0) efficiently computes the minimum number of copies possible across all characters in target. The if v > 0 condition ensures we only consider characters present in target. The floor division (//) is crucial; we can only use whole characters.

Code Explanation (Other Languages):

The Java, C++, Go, TypeScript, Rust and C solutions follow the same logic but use different syntax for implementing frequency counters (arrays) and finding the minimum value. The core algorithm remains consistent across all languages. For instance, in C++:

class Solution {
public:
    int rearrangeCharacters(string s, string target) {
        int cnt1[26]{}; //Initialize frequency array for s
        int cnt2[26]{}; //Initialize frequency array for target
 
        for (char& c : s) { //Count char frequencies for s
            ++cnt1[c - 'a'];
        }
        for (char& c : target) { //Count char frequencies for target
            ++cnt2[c - 'a'];
        }
        int ans = 100; // Initialize ans to a large value
        for (int i = 0; i < 26; ++i) { //Calculate max copies
            if (cnt2[i]) {
                ans = min(ans, cnt1[i] / cnt2[i]);
            }
        }
        return ans;
    }
};

The key elements remain the same: frequency counting, iterating through the target character frequencies, and calculating the minimum number of possible copies. The choice of language impacts only the syntax and data structure handling, not the fundamental approach to solving the problem.