这道题要求计算使用 s 中的字符可以形成的 target 的最大副本数,因此需要统计 target 中的每个字符的出现次数,以及统计这些字符在 s 中的出现次数。
如果一个字符在 target 中出现 x 次(x > 0),在 s 中出现 y 次,则在只考虑该字符的情况下,可以形成的 target 的最大副本数是 \Big\lfloor \dfrac{y}{x} \Big\rfloor。特别地,如果 y < x,则不能形成 target 的副本。
对于 target 中的每个字符,计算该字符在 target 中的出现次数和在 s 中的出现次数,并计算使用该字符可以形成的 target 的最大副本数。所有字符对应的最大副本数中的最小值即为使用 s 中的字符可以形成的 target 的最大副本数。
实现方面,需要使用两个哈希表分别记录 s 和 target 的每个字符的出现次数。有两处可以优化。
由于只有在 target 中出现的字符才会影响最大副本数,因此统计 s 中的每个字符的出现次数时,只需要考虑在 target 中出现的字符,忽略没有在 target 中出现的字符。
如果遇到一个在 target 中出现的字符对应的最大副本数是 0,则不能使用 s 中的字符形成 target 的副本,此时可提前返回 0。
[sol1-Python3]
1 2 3 4 5 6 7 8 9
classSolution: defrearrangeCharacters(self, s: str, target: str) -> int: ans = inf cnt_s = Counter(s) for c, cnt in Counter(target).items(): ans = min(ans, cnt_s[c] // cnt) if ans == 0: return0 return ans
classSolution { public: intrearrangeCharacters(string s, string target){ unordered_map<char, int> sCounts, targetCounts; int n = s.size(), m = target.size(); for (int i = 0; i < m; i++) { targetCounts[target[i]]++; } for (int i = 0; i < n; i++) { if (targetCounts.count(s[i])) { sCounts[s[i]]++; } } int ans = INT_MAX; for (auto &[c, count] : targetCounts) { int totalCount = sCounts[c]; ans = min(ans, totalCount / count); if (ans == 0) { return0; } } return ans; } };
intrearrangeCharacters(char * s, char * target) { int sCounts[26], targetCounts[26]; memset(sCounts, 0, sizeof(sCounts)); memset(targetCounts, 0, sizeof(targetCounts)); int n = strlen(s), m = strlen(target); for (int i = 0; i < m; i++) { targetCounts[target[i] - 'a']++; } for (int i = 0; i < n; i++) { if (targetCounts[s[i] - 'a']) { sCounts[s[i] - 'a']++; } } int ans = INT_MAX; for (int i = 0; i < 26; i++) { if (targetCounts[i] > 0) { ans = MIN(ans, sCounts[i] / targetCounts[i]); if (ans == 0) { return0; } } } return ans; }
funcrearrangeCharacters(s, target string)int { var cntS, cntT [26]int for _, c := range s { cntS[c-'a']++ } for _, c := range target { cntT[c-'a']++ } ans := len(s) for i, c := range cntT { if c > 0 { ans = min(ans, cntS[i]/c) if ans == 0 { return0 } } } return ans }
funcmin(a, b int)int { if a > b { return b }; return a }
复杂度分析
时间复杂度:O(n + m),其中 n 和 m 分别是字符串 s 的长度和字符串 target 的长度。需要分别遍历两个字符串一次统计每个字符的出现次数并使用哈希表记录,然后遍历哈希表一次计算最大副本数,时间复杂度是 O(n + m)。
空间复杂度:O(m),其中 m 是字符串 target 的长度。空间复杂度主要取决于哈希表,哈希表中只记录在 target 中出现的字符,因此哈希表的大小不超过 m,空间复杂度是 O(m)。