【刷题日记】leetcode-767 重构字符串

一、题目

给定一个字符串S,检查是否能重新排布其中的字母,使得两相邻的字符不同。
若可行,输出任意可行的结果。若不可行,返回空字符串。
示例 1:
输入: S = “aab”
输出: “aba”
示例 2:
输入: S = “aaab”
输出: “”
注意:
S 只包含小写字母并且长度在[1, 500]区间内。

二、解题

思路:

  1. “两相邻的字符不同” 推出重复次数最多的字符不能超过n/2 + 1 个,否则不能构成符合条件的字符串
  2. 生成哈希表,记录每个字符出现的个数,将最大字符(X)从哈希表剔除
  3. 如果满足条件,遍历哈希表,将X放在遍历开头加入,直到除X外的所有字符都追加完成
  4. 此时若还有X没有追加到重构的字符串里,从重构的字符串尾部判断是否能追加插入X

另外,题目说了是纯字母的,可以通过转成int数组来解决。性能上应该能提升不少。习惯用通用解法,这里编码的时候就么有写。

按这个思路,其实自己觉得应该能挺快的。结果虽然不会超时,但是还是算不上一个好的解法:
在这里插入图片描述
代码如下:

class Solution {
    public String reorganizeString(String S) {
        // 将输入拆分为字符数组
        String[] cArr = S.split("");

        // 确定阈值
        int origLength = S.length();
        int max = origLength / 2 ;
        if(origLength % 2 == 1) {
            max = max + 1;
        }

        // 遍历确定各元素个数
        Map<String, Integer> hash = new HashMap<>();
        int maxLength = 0;
        // 用于记录最大的key
        String maxKey = cArr[0];
        for(int i = 0; i < cArr.length; ++i) {
            int currentSize = hash.getOrDefault(cArr[i], 0) + 1;
            if(maxLength < currentSize) {
                maxLength = currentSize;
                maxKey = cArr[i];
            }
            hash.put(cArr[i], currentSize);
        }

        // 校验是否满足要求
        if(maxLength > max) {
            return "";
        }

        // 如果没有溢出, 则生成符合要求的字符串
        // 将最大的key作为开始,遍历所有元素生成满足要求的字符串
        String maxKeyStr = maxKey;
        char maxKeyChar = maxKey.charAt(0);
        hash.remove(maxKeyStr);
        String ret = "";
        while(origLength-- > 0 && maxLength-- > 0) {
            ret = ret+maxKey;
            for(Map.Entry<String, Integer> entry : hash.entrySet()) {
                if(entry.getValue() > 0) {
                    ret = ret + entry.getKey();
                    entry.setValue(entry.getValue() - 1);
                    origLength--;
                }
            }
            // 如果hash里的字母都写完了,退出
            if(origLength == maxLength) {
                break;
            }
        }

        // 遍历完尚未清空最大数组,将剩余的maxKey插入结果中
        StringBuilder sbRet=new StringBuilder(ret);
        if(maxLength > 0) {
            int i = 0;
            while(maxLength-- > 0) {
                // 如果插入位置左右都没有maxKey,则后续都可以直接插入
                while((i == 0 && sbRet.charAt(ret.length() - 1 - i) == maxKeyChar)
                        || (i > 0 && (sbRet.charAt(ret.length() - 1 - i) == maxKeyChar || sbRet.charAt(ret.length() - 1 - i + 1) == maxKeyChar))) {
                    i++;
                }
                sbRet.insert(ret.length() - i++, maxKey);
            }
        }
        return sbRet.toString();
    }
}

三、题解

有些题解说先把X放在下标偶数位置,再随意安插其他字符就可以得出解了,但是如果是aaaabbbbc这种,a_a_a_a_这样安插完后,再随意安插的话就有abacababb,会出现重复的情况,这个还没有get到题解的意思。

另外官方题解:重构字符串看着可以说是比较权威了,值得研读,先休息,明天学习下题解。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页