767. 重构字符串

767. 重构字符串

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

拆解字符串+重构字符串

先用一个26位vector存储每一个字母出现次数,出现次数大于字符串长度一半时无法重构,其他情况都可以重构。
按出现次数由大到小排序vector,保证先插入出现次数多的元素。
重构时按奇数偶数位置插入元素。

class Solution {
public:
    string reorganizeString(string S) {
        int len = S.size();
        vector<pair<int, int> > arr(26);
        for (const char& c : S)
            ++arr[c - 'a'].second;
        int index = 0;
        for (auto& p : arr)
        {
            p.first = index++;
            if (p.second > ((len + 1) >> 1))
                return "";
        }
        sort(arr.begin(), arr.end(), [](const pair<int, int>& a, const pair<int, int>& b){
            return a.second > b.second;
        });
        string res = S;
        index = 0;
        // 置放奇数位
        for (int i = 0; i < len; i += 2)
        {
            if (arr[index].second == 0)
                ++index;
            res[i] = ('a' + arr[index].first);
            --arr[index].second;
        }
        // 置放偶数位
        for (int i = 1; i < len; i+= 2)
        {
            if (arr[index].second == 0)
                ++index;
            res[i] = ('a' + arr[index].first);
            --arr[index].second;
        }
        return res;
    }
};

查找碰撞元素,查找可插入位置插入

先从index前面找,再从index后面找

class Solution {
public:
    string reorganizeString(string S)
    {
        int len = S.length();
        if (len <= 1) {
            return S;
        }
        for (int i = 1; S[i] != 0;) {
            if (S[i] != S[i - 1]) {
                i++;
                continue;
            }
            // 在前面找位置置换
            if (ReplaceCharOfStringFront(S, i - 1)) {
                continue;
            }
            // 在后面找位置置换
            if (ReplaceCharOfStringBack(S, i)) {
                continue;
            }
            // 找不到位置置换,就返回空
            return "";
        }
        return S;
    }

    // 在前面找,找到,就删除当前位置,插入当前字符
    bool ReplaceCharOfStringFront(string& s, int idx)
    {
        for (int i = 0; i <= (idx - 1); i++) {
            if (s[i] != s[idx] && (i == 0 || s[i - 1] != s[idx])) {
                char ch = s[idx];
                s.erase(idx, 1);
                s.insert(i, 1, ch);
                return true;
            }
        }
        return false;
    }

    // 在后面找,找到,就删除当前位置,插入当前字符
    bool ReplaceCharOfStringBack(string& s, int idx)
    {        
        int len = s.length();
        for (int i = idx + 1; i < len; i++) {
            if (s[i] != s[idx] && (s[i + 1] != s[idx])) {
                char ch = s[idx];
                s.erase(idx, 1);
                s.insert(i, 1, ch);
                return true;
            }
        }

        // 找不到
        return false;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值