Leetcode:767. 重构字符串

本文探讨了一种算法,用于检查并重组给定字符串S中的字母,确保任意两个相邻字符都不相同。通过统计字符频率并排序,算法判断是否能实现目标重组,并提供重组后的字符串或空字符串作为结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

示例 1:

输入: S = "aab"
输出: "aba"

示例 2:

输入: S = "aaab"
输出: ""

注意:

  • S 只包含小写字母并且长度在[1, 500]区间内。

解题思路:

任务调度问题,排序。本题有点像之前的一个任务调度问题,由于题量太大,忘了哪一个。。。

  1. 统计当前字符串各个字符的个数,然后按照数量多少排序,如果数量一样,则按照字符大小排序,最终得到vector<pair<char,int>>mp,pair<char,int>中char代表字符,int代表数量。
  2. 假设字符总数是num,当前排序后的最大数量mp[0].second。如果2*mp[0].second>num+1,那么直接返回“”,必然有多余的字符。如果2*mp[0].second==num+1。第一个字符必然是mp[0].first,之后的成对即可,注意每一对都应该是mp[0].first在后,这样可以防止当前末尾与下一层的开始一样。如果,2*mp[0].second<num+1,直接组成mp[0].second对字符即可。
  3. 如果遇到2*mp[0].second<num+1情况,将mp[0].second对字符加入结果之后,mp中必然还有剩余的字符,对剩余的字符再次排序重复2过程即可。不过不一样的是,此刻结果字符串已经不为空了,当遇到2*mp[0].second>num+1的情况,应该先考虑是否能将多余的插入之前已经确定的结果,能则插入,不能则返回""。
C++代码
class Solution {
public:
    static bool cmp(pair<char, int> a, pair<char, int> b) {
        if (a.second == b.second) return a.first < b.first;
        return a.second > b.second;
    }
    string reorganizeString(string S) {
        vector<pair<char, int>> mp;
        int i, size = S.size();
        for (i = 1; i <= 26; i++) mp.push_back({ 'a' + i - 1,0 });
        for (i = 1; i <= size; i++) mp[S[i - 1] - 'a'].second++;
        sort(mp.begin(), mp.end(), Solution::cmp);
        int num = size;
        string res;
        while (num > 0) {
            if (mp[0].second * 2 > num + 1) {
                //在已有的字符串中查找mp[0].second*2 - num - 1个可以插入mp[0].first的位置,不包括末尾
                int sum = mp[0].second * 2 - num - 1;
                for (i = 0; i < res.size(); i++) {
                    if (sum>0&&i == 0 && res[0] != mp[0].first) {
                        res.insert(res.begin(), mp[0].first);
                        sum--;
                        num--;
                        mp[0].second--;
                    }
                    else {
                        if (sum > 0 && res[i] != mp[0].first&&res[i - 1] != mp[0].first) {
                            res.insert(res.begin()+i, mp[0].first);
                            sum--;
                            num--;
                            mp[0].second--;
                        }
                    }
                }
                if (sum > 0) return "";
            }
            if (mp[0].second * 2 == num + 1) {
                res.push_back(mp[0].first);
                num--;
                mp[0].second--;
            }
            int pos = 1;
            while (mp[0].second > 0) {
                res.push_back(mp[pos].first);
                mp[pos].second--;
                res.push_back(mp[0].first);
                mp[0].second--;
                num -= 2;
                if (mp[pos].second == 0&&pos!=25) pos++;
            }
            sort(mp.begin(), mp.end(), Solution::cmp);
        }
        return res;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值