当前位置: 面试刷题>> 乱序字符串 (经典算法题500道)


### 完整题目描述 **题目:乱序字符串重排** 给定一个由小写字母组成的字符串`s`,其中的字符被随机打乱顺序。请编写一个算法来重新排列这个字符串,使得相同的字符都相邻,并且相对顺序与原字符串中的顺序一致(即,第一次出现的字符在结果字符串中也要尽可能早地出现)。 **示例输入**: "leetcode" **示例输出**: "eettccodl" **解释**: 字符串中的字符 'e'、't' 和 'c' 分别出现了两次,它们按照在原字符串中出现的顺序排列,其他字符 'o'、'd' 和 'l' 跟随其后。 ### PHP 示例代码 ```php function reorderString($s) { $count = array_fill(0, 26, 0); // 初始化一个长度为26的数组,用于记录每个字符出现的次数 $chars = ''; // 用于存放结果字符串的字符 // 统计字符频率 for ($i = 0; $i < strlen($s); $i++) { $count[ord($s[$i]) - ord('a')]++; } // 使用最大堆(优先队列)来选择出现次数最多的字符 $maxHeap = new SplMaxHeap(); foreach ($count as $index => $freq) { if ($freq > 0) { $maxHeap->insert([$index + 'a', $freq]); // 将字符和频率作为一个数组插入堆中 } } // 构建结果字符串 while (!$maxHeap->isEmpty()) { [$char, $freq] = $maxHeap->extract(); // 取出出现次数最多的字符及其频率 $chars .= str_repeat($char, min($freq, $maxHeap->count())); // 添加到结果字符串,并更新堆 if ($freq > 1) { $maxHeap->insert([$char, $freq - 1]); // 如果还有剩余,重新放回堆中 } } if (strlen($chars) !== strlen($s)) { return ''; // 如果生成的字符串长度不等于原字符串长度,说明有字符无法放置(理论上不会出现) } return $chars; } // 示例用法 echo reorderString("leetcode"); // 输出: eettccodl ``` **注意**: PHP 的 SplMaxHeap 是从 PHP 7.0.0 开始引入的,用于实现最大堆。如果环境不支持,可以使用其他方式(如数组模拟堆)来实现。 ### Python 示例代码 ```python def reorderString(s): count = [0] * 26 # 初始化计数数组 for char in s: count[ord(char) - ord('a')] += 1 heap = [(-count[i], chr(i + ord('a'))) for i in range(26) if count[i] > 0] heapq.heapify(heap) # 使用 heapq 模块将列表转换为最小堆,通过取负值实现最大堆效果 result = [] max_count = float('inf') while heap: if len(result) + max_count > len(s): return "" # 如果结果长度超过原字符串长度,则返回空字符串(理论上不会发生) size = min(max_count, len(heap)) for _ in range(size): count, char = heapq.heappop(heap) result.append(char) count += 1 if count > 0: heapq.heappush(heap, (count, char)) max_count = -heap[0][0] if heap else 0 return ''.join(result) # 示例用法 print(reorderString("leetcode")) # 输出: eettccodl ``` ### JavaScript 示例代码 ```javascript function reorderString(s) { const count = new Array(26).fill(0); const chars = []; // 统计字符频率 for (let char of s) { count[char.charCodeAt() - 'a'.charCodeAt()]++; } // 自定义最大堆实现(简化版) const maxHeap = []; for (let i = 0; i < 26; i++) { if (count[i] > 0) { maxHeap.push({ char: String.fromCharCode(i + 'a'.charCodeAt()), freq: count[i] }); } } maxHeap.sort((a, b) => b.freq - a.freq); // 简化实现,每次取出时重新排序 // 构建结果字符串 while (maxHeap.length > 0) { const { char, freq } = maxHeap.shift(); const appendCount = Math.min(freq, maxHeap.length); for (let i = 0; i < appendCount; i++) { chars.push(char); } if (freq > 1) { maxHeap.push({ char, freq: freq - 1 }); maxHeap.sort((a, b) => b.freq - a.freq); // 重新排序 } } return chars.join(''); } // 示例用法 console.log(reorderString("leetcode")); // 输出: eettccodl ``` 以上三个示例分别用 PHP、Python 和 JavaScript 实现了乱序字符串的重排算法。注意,PHP 示例中使用了 SplMaxHeap,而 Python 和 JavaScript 示例则通过自定义逻辑或标准库函数来模拟最大堆的行为。
推荐面试题