返回介绍

solution / 0300-0399 / 0358.Rearrange String k Distance Apart / README

发布于 2024-06-17 01:04:01 字数 4989 浏览 0 评论 0 收藏 0

358. K 距离间隔重排字符串

English Version

题目描述

给你一个非空的字符串 s 和一个整数 k ,你要将这个字符串 s 中的字母进行重新排列,使得重排后的字符串中相同字母的位置间隔距离 至少 为 k 。如果无法做到,请返回一个空字符串 ""

 

示例 1:

输入: s = "aabbcc", k = 3
输出: "abcabc" 
解释: 相同的字母在新的字符串中间隔至少 3 个单位距离。

示例 2:

输入: s = "aaabc", k = 3
输出: "" 
解释: 没有办法找到可能的重排结果。

示例 3:

输入: s = "aaadbbcc", k = 2
输出: "abacabcd"
解释: 相同的字母在新的字符串中间隔至少 2 个单位距离。

 

提示:

  • 1 <= s.length <= 3 * 105
  • s 仅由小写英文字母组成
  • 0 <= k <= s.length

解法

方法一:贪心 + 哈希表 + 优先队列(大根堆)

先用哈希表 cnt 统计每个字母出现的次数,然后构建一个大根堆 pq,其中每个元素是一个 (v, c) 的元组,其中 c 是字母,v 是字母出现的次数。

重排字符串时,我们每次从堆顶弹出一个元素 (v, c),将 c 添加到结果字符串中,并将 (v-1, c) 放入队列 q 中。当队列 q 的长度达到 $k$ 及以上时,弹出队首元素,若此时 v 大于 0,则将队首元素放入堆中。循环,直至堆为空。

最后判断结果字符串的长度,若与 s 长度相等,则返回结果字符串,否则返回空串。

时间复杂度 $O(n\log n)$,其中 $n$ 是字符串 s 的长度。

相似题目:

class Solution:
  def rearrangeString(self, s: str, k: int) -> str:
    h = [(-v, c) for c, v in Counter(s).items()]
    heapify(h)
    q = deque()
    ans = []
    while h:
      v, c = heappop(h)
      v *= -1
      ans.append(c)
      q.append((v - 1, c))
      if len(q) >= k:
        w, c = q.popleft()
        if w:
          heappush(h, (-w, c))
    return "" if len(ans) != len(s) else "".join(ans)
class Solution {
  public String rearrangeString(String s, int k) {
    int n = s.length();
    int[] cnt = new int[26];
    for (char c : s.toCharArray()) {
      ++cnt[c - 'a'];
    }
    PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> b[0] - a[0]);
    for (int i = 0; i < 26; ++i) {
      if (cnt[i] > 0) {
        pq.offer(new int[] {cnt[i], i});
      }
    }
    Deque<int[]> q = new ArrayDeque<>();
    StringBuilder ans = new StringBuilder();
    while (!pq.isEmpty()) {
      var p = pq.poll();
      int v = p[0], c = p[1];
      ans.append((char) ('a' + c));
      q.offer(new int[] {v - 1, c});
      if (q.size() >= k) {
        p = q.pollFirst();
        if (p[0] > 0) {
          pq.offer(p);
        }
      }
    }
    return ans.length() == n ? ans.toString() : "";
  }
}
class Solution {
public:
  string rearrangeString(string s, int k) {
    unordered_map<char, int> cnt;
    for (char c : s) ++cnt[c];
    priority_queue<pair<int, char>> pq;
    for (auto& [c, v] : cnt) pq.push({v, c});
    queue<pair<int, char>> q;
    string ans;
    while (!pq.empty()) {
      auto [v, c] = pq.top();
      pq.pop();
      ans += c;
      q.push({v - 1, c});
      if (q.size() >= k) {
        auto p = q.front();
        q.pop();
        if (p.first) {
          pq.push(p);
        }
      }
    }
    return ans.size() == s.size() ? ans : "";
  }
};
func rearrangeString(s string, k int) string {
  cnt := map[byte]int{}
  for i := range s {
    cnt[s[i]]++
  }
  pq := hp{}
  for c, v := range cnt {
    heap.Push(&pq, pair{v, c})
  }
  ans := []byte{}
  q := []pair{}
  for len(pq) > 0 {
    p := heap.Pop(&pq).(pair)
    v, c := p.v, p.c
    ans = append(ans, c)
    q = append(q, pair{v - 1, c})
    if len(q) >= k {
      p = q[0]
      q = q[1:]
      if p.v > 0 {
        heap.Push(&pq, p)
      }
    }
  }
  if len(ans) == len(s) {
    return string(ans)
  }
  return ""
}

type pair struct {
  v int
  c byte
}

type hp []pair

func (h hp) Len() int { return len(h) }
func (h hp) Less(i, j int) bool {
  a, b := h[i], h[j]
  return a.v > b.v
}
func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *hp) Push(v any)   { *h = append(*h, v.(pair)) }
func (h *hp) Pop() any   { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文