767. 重构字符串

地址:

力扣icon-default.png?t=M0H8https://leetcode-cn.com/problems/reorganize-string/

题目:

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

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

示例 1:

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


示例 2:


注意:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reorganize-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:

观察字符串长度为奇数以及偶数情况:

偶数:最多的字母个数 n  > len / 2 就不行

          比如最多字符个数 = 2,那么下图这样放没问题,但是再多一个,放 1 或 3 位置都不行

767. 重构字符串_第1张图片

奇数:最多的字母个数 n > (len + 1) / 2 就不行

        比如最多字符个数 = 3, 那么下图这样放没问题,但是再多一个,放 1 或 3 位置都不行

767. 重构字符串_第2张图片

 考虑到偶数情况下 len /2 == (len + 1) / 2

那么判定是否能够存在这样的字符串就统一了,只要最多字符个数 n > (len + 1) / 2 ,那么返回 “”

解决了判定有效问题后,剩下的就是如何重组

还是以上面奇数图来看,我们只能把最多字符元素依次放在 偶数下标,否则依旧会出现相邻

剩余元素的放置紧跟放置完最多字符后的偶数下标,知道抵达末尾

接着在从 [1] 放置奇数下标,当然如果上一次还没有放完,也是要从这里开始

比如:"aaabbbccc"

1. 将 a 放到偶数下标

2. 将 b 继续放偶数,[6],[8],偶数下标到底后

3. 开始放奇数下标 [1]

4. b 放完后继续奇数下标 [3],[5],[6]

767. 重构字符串_第3张图片

 

题目的限定我们就可以直接定一个 26 大小的计数数组

计数数组可以参考:

排序算法之计数排序

方法一、计数数组

char * reorganizeString(char * s){
    int slen = strlen(s);
    int countArray[26] ={0};
    int maxnum = 0, maxIdx = 0;
    int i,j;

    if(slen < 2)
        return s;

    /* counting charactor nums*/
    i = 0;
    while(s[i])
    {
        int idx = s[i] - 'a';
        countArray[idx]++;
        i++;
    }

    /* record maxnum and idx */
    for(i=0; i<26; i++)
    {
        //printf("countArray[%d]=%d\n", i, countArray[i]);
        if(maxnum < countArray[i])
        {
            maxnum = countArray[i];
            maxIdx = i;
        }
    }

    //printf("maxnum=%d, maxIdx=%d\n", maxnum, maxIdx);
    if(maxnum > (slen + 1) / 2)
        return "";

    /* re-organize string */
    char *newString =(char *)malloc(sizeof(char) * slen + 1);
    newString[slen] = '\0';

    // evenIdx first
    int evenIdx = 0;
    int oddIdx = 1;
    while(maxnum)
    {
        newString[evenIdx] = maxIdx + 'a';
        maxnum--;
        //printf("put maxnum..newString[%d]=%c\n", evenIdx, newString[evenIdx]);
        evenIdx += 2;
    }

    countArray[maxIdx] = 0;

    
    for(i=0; i<26; i++)
    {
        while(countArray[i] && evenIdx < slen)
        {
            newString[evenIdx] = i + 'a';
            //printf("1.newString[%d]=%c\n", evenIdx, newString[evenIdx]);
            countArray[i]--;
            evenIdx += 2;
        }

        while(countArray[i])
        {
            newString[oddIdx] = i + 'a';
            //printf("2.newString[%d]=%c\n", oddIdx, newString[oddIdx]);
            countArray[i]--;
            oddIdx += 2;
        }
    }

    //printf("newString=%s\n", newString);
    return newString;
}

 

查看更多刷题笔记

你可能感兴趣的:(算法训练(C语言版本),leetcode,贪心)