力扣竞赛5195_最长快乐字符串_字符串处理

竞赛原题:

如果字符串中不含有任何 'aaa''bbb''ccc' 这样的字符串作为子串,那么该字符串就是一个「快乐字符串」。

给你三个整数 abc,请你返回 任意一个 满足下列全部条件的字符串 s

  • s 是一个尽可能长的快乐字符串。
  • s 中 最多 有a 个字母 'a'b 个字母 'b'c 个字母 'c'
  • s 中只含有 'a''b''c' 三种字母。

如果不存在这样的字符串 s ,请返回一个空字符串 ""

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-happy-string

思路:

采用贪心思想,每次找到当前剩余个数最多(以下简称最大字符)的字母max{a, b, c} 进行字符串追加操作,如果连续两轮都是同一个字符,则第二轮选取次大的字符。值得注意的是,应该尽量避免连续两次找到的max{a, b, c}都是同一个字符,所以若最大字符选取完2个之后,若max{a, b, c}仍为当前最大字符,则选取1个次大元素追加至字符串当中。循环的终点为无法找到下一个剩余个数大于0的字符,那么函数退出。

算法伪代码:

longestDiverseString(a, b, c)->string:
	while true:
	do: 
	    max <- max(a, b, c) 			//a, b, c用结构体保存
	    if last != max:				//检查上一轮是否重复
		then size <- max.vol >= 2 ? 2 : 1	//最大字符尽可能步进2
			s <- s + max.char * size		
			max.vol <- max.vol - size
			last <- max			//记录上一轮字符
	    else if secondMax(a, b, c).vol > 0:		//若与上一轮重复,检查次大字符
		then max <- secondMax(a, b, c)
			s <- s + max.char
			max.vol <- max.vol - 1
			last <- max
		else: 					//没有更多合法字符,退出
		    then break
	return s
				

C++代码实现:

/**
 * Game No.5195. 
 * Title: Longest Happy String
 * Author: Moonwalker
 * Date: 2020/04/06
 * Status: Accepted
 * Method: Greedy + Heap
 */

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>
using namespace std;

class Solution {
    struct Info{
        char c;
        int vol;
    };
    struct cmp{
        bool operator()(Info a, Info b){
            return a.vol < b.vol;
        }
    };
public:
    string longestDiverseString(int a, int b, int c) {
        priority_queue<Info, vector<Info>, cmp> pq;
        pq.push({'a', a}), pq.push({'b', b}), pq.push({'c', c});
        Info last = {'#', -1};
        string s;
        while(true){
            Info max = pq.top();
            pq.pop();
            cout << s << ' ' << max.vol << endl;
            if(max.vol <= 0) break;
            if(last.c != max.c){
                s += max.c;
                max.vol--;
                if(max.vol > 0){
                    s += max.c;
                    max.vol--;
                }
                last = max;
                pq.push(max);
            }
            else{
                Info max2 = pq.top();
                pq.pop();
                pq.push(max);
                if(max2.vol > 0){
                    s += max2.c;
                    max2.vol--;
                    last = max2;
                    pq.push(max2);
                }
                else break;
            }
        }
        return s;
    }
};

int main(){
    int a, b, c;
    cin >> a >> b >> c;
    Solution sl;
    cout << sl.longestDiverseString(a, b, c) << endl;
    system("pause");
    return 0;
}

总结:

基于贪心思想,用堆来实现最大字符和次大字符的选取,时间复杂度O(a+b+c).

posted @ 2020-04-06 01:05  月球漫步者  阅读(427)  评论(0)    收藏  举报