[LeetCode 767] 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,我们怎么判断其是否是valid的呢。

答案是不能有任何一个char c的统计个数超过(s,size() + 1)/2。

例如:5个a,至少需要4个其他的字符才能保证有解。

因此首先统计各个字符的计数,一旦发现有的计数大于(s,size() + 1)/2,就返回失败。

计数完毕之后,字符串也是valid,能够找到解,那我们怎么组织字符串使得相邻的两个char不同呢?

假设字符串是这样的: 5 a , 4 b, 4 c,我们需要先对字符串的字数进行排序,将最多的字符先放到最前面。

比较容易想到的先拼接1个ab到结果,剩余 4a, 3b, 4c,那么需要对剩余字符再次排序, 4a, 4c, 3b。

再去ac拼接到结果,继续排序,3a, 3c, 3b

依次类推,可以得到剩余的字符对分别是  ac, ba, bc, bc, a

 

Code

class Solution {
public:
    string reorganizeString(string S) {
        map<char, int> count;
        string res;
        for (int i = 0; i < S.size(); i ++)
        {
            if (count.find(S[i]) == count.end())
                count[S[i]] = 0;
            count[S[i]] ++;
            if (count[S[i]] > (S.size() + 1)/2)
                return res;
        }
        
        vector<char> order;
        map<char, int>::iterator iter = count.begin();
        for (; iter != count.end(); iter ++)
        {
            int cnt = iter->second;
            int i = 0;
            for (i = 0; i < order.size(); i ++)
            {
                if (cnt >= count[order[i]])
                    break;
            }
            order.insert(order.begin() + i, iter->first);
        }
        
        while (!order.empty())
        {
            if (order.size() == 1)
            {
                res.push_back(order[0]);
                return res;
            }
            char c1 = order[0];
            char c2 = order[1];
            res.push_back(c1);
            res.push_back(c2);
            
            count[c1] --;
            count[c2] --;
            if (count[c2] == 0)
            {
                count.erase(c2);
                order.erase(order.begin() + 1);
            }
            if (count[c1] == 0)
            {
                count.erase(c1);
                order.erase(order.begin());
            }
            
            for (int i = 2; i < order.size(); i ++)
            {
                char c = order[i];
                if (count[c] <= count[c2])
                    break;
                else
                {
                    swap(order[i], order[i-1]);
                }
            }
            for (int i = 1; i < order.size(); i ++)
            {
                char c = order[i];
                if (count[c] <= count[c1])
                    break;
                else
                {
                    swap(order[i], order[i-1]);
                }
            }
        }
        
        return res;
    }
};

运行效率

Runtime: 8 ms, faster than 41.72% of C++ online submissions for Reorganize String.

Memory Usage: 8.6 MB, less than 100.00% of C++ online submissions forReorganize String.

值得注意的是LeetCode的这道题的测试结果有问题,之前我使用了一种错误的解法发现也能够通过。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值