算法——重构字符串使得相邻字符不同

给定一个字符串S,检查是否能重新排布其中的字母,使得两相邻的字符不同。
若可行,输出任意可行的结果。若不可行,返回空字符串。
leetcode

解题思路:

  • 首先想想什么样的情况下不能构成可行的字符串,就像植树问题,最大的相同的字符个数一定小于字符串长度加一再除以二,如果超了就肯定会相邻。
  • 所以,我们在枚举输出的时候,只要剩下需要输出的字符串一直满足这个条件,就一直能够产生合法的答案。当我们每次输出数量最大的两个字符串的时候,就能够让原来的字符串一直满足条件了。你想嘛,如果每次都输出数量的了,那么数量大的不就肯定会超过半数了。
    这里利用了优先队列,让数量多的字符排在对头。
class Solution {
    public String reorganizeString(String s) {
        int n = s.length();
        if(n < 2) return s;

		// 通过数组对字符串的字符进行计数
        int[] cnt = new int[26];
        int maxCnt = 0;
        for(char c : s.toCharArray()) {
            cnt[c - 'a'] ++;
        }

        for(int i : cnt) {
            maxCnt = Math.max(maxCnt, i);
        }

        if(maxCnt > (n + 1) / 2) return "";
		
		// 构造优先队列
        PriorityQueue<Character> q = new PriorityQueue<>((a, b) -> cnt[b - 'a'] - cnt[a - 'a']);

		// 填入优先队列
        for(int i = 0; i < 26; i++) {
            if(cnt[i] > 0) q.offer((char)(i + 'a'));
        }

        StringBuilder res = new StringBuilder();

        while(q.size() > 1) {
        	// 每次提取两个数量最多的字符
            char a = q.poll();
            char b = q.poll();
            res.append(a);
            res.append(b);

            cnt[a - 'a'] --;
            cnt[b - 'a'] --;
            if(cnt[a - 'a'] > 0) q.offer(a);
            if(cnt[b - 'a'] > 0) q.offer(b);
        }

		// 最后可能还剩下一个
        if(q.size() > 0) res.append(q.poll());

        return res.toString();
    }
}
原文地址:https://www.cnblogs.com/lippon/p/14117607.html