LeetCode -- 767. 重构字符串

 

设字符串s长度为len

s可以重构为相邻字符串不同时 有字符串中出现次数最多的字符 < (len + 1) >> 1

当满足上述条件时候,我们就能对其进行重构

重构法:先放置偶数位置,再放置奇数位置

复制代码
c ++ 
class Solution {
public:
    string reorganizeString(string s) {
        vector<int> cnt(26, 0);
        int n = s.size();
        for(int i = 0; i < n; i ++ ) {
            cnt[s[i] - 'a'] ++ ;
        }

        int mx = 0, alp = 0, lim = (n + 1) >> 1;
        for(int i = 0; i < 26; i ++ ) {
            if(cnt[i] > mx) {
                mx = cnt[i];
                alp = i;
            }
        }

        if(mx > lim) return "";

        string res(n, ' ');
        int idx = 0;
        while(cnt[alp] -- > 0) {
            res[idx] = 'a' + alp;
            idx += 2;
        }

        for(int i = 0; i < 26; i ++ ) {
            while(cnt[i] -- > 0) {
                if(idx >= n) {
                    idx = 1;
                }
                res[idx] = 'a' + i;
                idx += 2;
            }
        }

        return res;
    }
};
复制代码

 

js代码,先把最多的放到答案中,再依次插入。

复制代码
js
/**
 * @param {string} s
 * @return {string}
 */

function getIdx(c) {
    return c.charCodeAt() - 'a'.charCodeAt();
}

function getChar(c) {
    return String.fromCharCode(c + 'a'.charCodeAt());
}

var reorganizeString = function(s) {
    let n = s.length
    let cnt = new Array(26).fill(0);

    for(let i = 0; i < n; i ++ ) {
        let it = cnt[getIdx(s[i])];
        if(it) {
            it.count ++ ;
        } else {
            cnt[getIdx(s[i])] = {name:s[i],count:1};
        }
    }

    cnt = cnt.filter((v) => {
        return v != 0;
    });

    cnt.sort((a, b) => {
        return b.count - a.count;
    });


    if(cnt[0].count > Math.floor((n + 1) / 2)) {
        return "";
    }
    let res = new Array(cnt[0].count).fill(cnt[0].name);

    let idx = 1;
    for(let i = 1; i < cnt.length;) {
        res.splice(idx, 0, cnt[i].name);
        cnt[i].count -- ;
        if(cnt[i].count === 0) {
            i ++ ;
        }
        idx = idx + 2 > res.length ? 1: idx + 2;
    }
    return res.join("")

};
复制代码

 

解法二:利用桶(分组分类)思想

思路 1. 将相同的字符放入不同的桶中以保证其彼此不会相邻,因此桶的数目应等于字符串中最多的元素的数目; 2. 按贪心策略,优先填充数目最多的元素,对于每一种元素,循环在不同桶中进行填充,由于桶的个数等于字符串中最多的元素的数目,因此每个桶中不会出现相同的元素,填充完毕后将桶依次相连即为答案; 3. 若填充完毕后长度为1的桶(只可能出现在最后的位置)的数目多于1,将桶依次相连会使得这些长度为1的桶中的相同元素相邻,说明不存在相应的排列,返回""(这一情况即官解中说明的如果存在一个字母的出现次数大于(n+1)/2,其中n为字符串长度,则无法重新排布字母使得相邻的字母都不相同)。

复制代码
c ++ 
class Solution {
public:
    string reorganizeString(string s) {
        vector<int> cnt(26);
        int n = s.size();
        for(int i = 0; i < n; i ++ ) {
            cnt[s[i] - 'a'] ++ ;
        }

        int mx = -1, pos = -1, lim = n + 1 >> 1;
        for(int i = 0; i < cnt.size(); i ++ ) {
            if(cnt[i] > mx) {
                mx = cnt[i];
                pos = i;
            }
        }
        if(mx > lim) return "";
        //初始化桶,将最多的元素放进去
        vector<string> buf(mx);
        for(int i = 0; i < cnt[pos]; i ++ ) {
            buf[i] += 'a' + pos;
        }
        cnt[pos] = 0;

        int idx = 0;
        for(int i = 0; i < 26; i ++ ) {
            for(int j = 0; j < cnt[i]; j ++ ) {
                buf[idx] += 'a' + i;
                idx = (idx + 1) % mx;
            }
        }

        string res;
        for(int i = 0; i < mx; i ++ ) {
            res += buf[i];
        }

        return res;
    }
};
复制代码
复制代码
python
class Solution:
    def reorganizeString(self, s: str) -> str:
        cnt, idx = Counter(s), 0
        bufnum = cnt.most_common(1)[0][1]
        if bufnum > (len(s) + 1) // 2:
            return ""
        buckets = [[] for _ in range(bufnum)]
        for c, num in cnt.most_common():
            for _ in range(num):
                buckets[idx].append(c)
                idx = (idx + 1) % bufnum
            
        return "".join(["".join(bucket) for bucket in buckets])
复制代码

 

复制代码
java
class Solution {
    public String reorganizeString(String s) {
        int n = s.length();
        int[] cnt = new int[26];
        for(int i = 0; i < n; i ++ ) {
            char c = s.charAt(i);
            cnt[c - 'a'] ++ ;
        }

        int mx = -1, pos = -1, lim = n + 1 >> 1;
        for(int i = 0; i < 26; i ++ ) {
            if(cnt[i] > mx) {
                mx = cnt[i];
                pos = i;
            }
        }

        if(mx > lim) return "";

        int idx = 0;
        StringBuilder[] buf = new StringBuilder[mx];
        for(int i = 0; i < mx; i ++ ) {
            buf[i] = new StringBuilder();
        }

        for(int i = 0; i < mx; i ++ ) {
            buf[i].append((char)(pos + 'a'));
        }
        cnt[pos] = 0;

        for(int i = 0; i < 26; i ++ ) {
            for(int j = 0; j < cnt[i]; j ++ ) {
                buf[idx].append((char)('a' + i));
                idx = (idx + 1) % mx;
            }
        }

        StringBuilder res = new StringBuilder();
        Arrays.stream(buf).forEach((ss) -> {
            res.append(ss);
        });

        return res.toString();
    }
}
复制代码

 

复制代码
golang
func reorganizeString(s string) string {
    cnt := make(map[byte]int)
    mx := 0
    n := len(s)
    for i := 0; i < n; i ++ {
        cnt[s[i]] ++ ;
    }

    chars := []byte{}
    for char, _ := range cnt {
        chars = append(chars, char)
    }
    sort.Slice(chars, func(i int, j int) (bool) {return cnt[chars[i]] > cnt[chars[j]]})

    lim := (n + 1) / 2
    mx = cnt[chars[0]]
    if(mx > lim) {
        return ""
    }

    buf := make([][]byte, mx)

    idx := 0
    for _, ch := range chars {
        for i := 0; i < cnt[ch]; i ++ {
            buf[idx] = append(buf[idx], ch)
            idx = (idx + 1) % mx
        }
    }

    res := ""
    for i := 0; i < mx; i ++ {
        res += string(buf[i])
    }

    return res
}
复制代码

 

posted @   深渊之巅  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)
点击右上角即可分享
微信分享提示