【LeetCode】767. Reorganize String 重构字符串(Medium)(JAVA)

【LeetCode】767. Reorganize String 重构字符串(Medium)(JAVA)

题目地址: https://leetcode.com/problems/reorganize-string/

题目描述:

Given a string S, check if the letters can be rearranged so that two characters that are adjacent to each other are not the same.

If possible, output any possible result.  If not possible, return the empty string.

Example 1:

Input: S = "aab"
Output: "aba"

Example 2:

Input: S = "aaab"
Output: ""

Note:

  • S will consist of lowercase letters and have length in range [1, 500].

题目大意

给定一个字符串S,检查是否能重新排布其中的字母,使得两相邻的字符不同。

若可行,输出任意可行的结果。若不可行,返回空字符串。

解题方法

  1. 首先把所有所有字母次数计算出来,然后根据次数进行排序
  2. 如果最多的次数大于字符串 S 长度的一般,就说明不存在这种重排,直接返回空字符串
  3. 接下来就是重组字符串了,这个比较难
  4. 先把次数最多的用了,也就是先取次数最多的字符,然后取第二个次数多的字符,然后不断循环即可(如果当前字符没有次数就直接在列表里删掉了,免得下次还要无效判断)
  5. note: 上面这样取会遇到一个问题:取次数最多的字符可能是上一次取第二个次数多的字符,所以要判断这次的第一次,是不是上一次的最后一个字符,如果是的话,直接插到最前面去(开始直接跳过处理,发现不行,插到最前面可行的原因是:不管这么插到最前面,肯定不会超过次数最多的个数,所以插入是可行的)
class Solution {
    public String reorganizeString(String S) {
        if (S.length() <= 1) return S;
        List<int[]> list = new ArrayList<>();
        for (int i = 0; i < 26; i++) {
            list.add(new int[]{0, i});
        }
        for (int i = 0; i < S.length(); i++) {
            list.get(S.charAt(i) - 'a')[0]++;
        }
        Collections.sort(list, (a, b) -> (a[0] - b[0] == 0 ? a[1] - b[1] : -a[0] + b[0]));
        if (list.get(0)[0] > (S.length() % 2 == 0 ? S.length() / 2 : (S.length() / 2 + 1))) return "";
        StringBuilder res = new StringBuilder();
        int insertIndex = 0;
        while (list.size() > 0) {
            if (list.get(0)[0] == 0) {
                list.remove(0);
                continue;
            }
            list.get(0)[0]--;
            if (res.length() == 0 || res.charAt(res.length() - 1) != (list.get(0)[1] + 'a')) {
                res.append((char) (list.get(0)[1] + 'a'));
            } else {
                res.insert(insertIndex, (char) (list.get(0)[1] + 'a'));
                insertIndex += 2;
            }
            int next = 1;
            while (next < list.size() && list.get(next)[0] == 0) {
                list.remove(next);
            }
            if (next < list.size()) {
                list.get(next)[0]--;
                res.append((char) (list.get(next)[1] + 'a'));
            }
        }
        return res.toString();
    }
}

执行耗时:5 ms,击败了29.46% 的Java用户
内存消耗:36.8 MB,击败了57.16% 的Java用户

欢迎关注我的公众号,LeetCode 每日一题更新
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值