leetcode-026-767. 重构字符串

767. 重构字符串

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

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

示例 1:

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

示例 2:

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

注意:

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

今天不怎么有精神,所以最开始搞的时候方向错了。我选择的是广搜和深搜,一顿错做猛如虎,发现超时。
看了题解是堆排序和插入法,果断选择插入法,不过堆排序还是要搞得,所以就标记了“重要”。
记录一下自己做错的过程。

  1. 深搜是最不合适的方法,我还研究了半天
  2. 广搜也不行,一样的,搜索这道题目根本就是最费劲不讨好的方式
  3. 插入法很好,我的思路是这样的
    a. 创建一个和字符串 S 一样大小的字符串 ans
    b. 使用 map 统计字符串 S 出现的字符和频率
    c. 将频率最高的字符放入到字符串 ans 的偶位置
    d. 频率最高的用完,用次之,依次进行
    e.字符串 ans 中的偶数位置放完,再放置奇数位置

我觉得我的描述很清晰,实际上,我在很刻意的做这件事,可以的训练自己的逻辑。今天在写深搜的时候,那个递归让我写的很痛苦,因为我觉得我根本做不到写代码之前,就在脑海中打理好我该怎么去写,这是一个很糟糕的习惯。这种代码越写越糟糕。
我的插入法中间也有肯多小坑。
4. map 的排序是针对 key,我把这个给忘了,我习惯使用了排好顺序的map,然后错误也是很明显。也就是map提供的排序是针对字符而不是频率
5. map 是不存在对 value 的排序 ,所以我觉得 pair+vector 太麻烦,所以自己定义了一个struct
6. 偶数位置放完之后,放置奇数位置的时候,需要继续从最高频率开始,而不是最低频率,这样是为了避免重复,如果奇数位置从最低频率开始,那么字符串ans的末尾位置很有可能最高频率相邻。
7. 为空的条件是 最高频率 < (字符串 ans 长度 + 1) / 2
8. 需要在运算符号两边留下足够的空格用于运算
这个是这样算的:

	假设字符串长度 len, 最高频率为 a,其他频率为 b,满足不相邻的要求:
    	那么最高频率的最大值为: a <= b + 1
    						 2a <= a + b + 1
    						 a <= (len+1) / 2

一切的逻辑需要用数学表现出来,这也是我想要的能力:


typedef  struct {
	char ch;
	int num;
}Map;

bool cmp(Map a, Map b) {
	return a.num > b.num;
}

class Solution {
public:

	string reorganizeString(string S) {
		int len = S.size();

		map<char, int> maps;
		for (int i = 0; i < len; i++)
			maps[S[i]]++;

		vector<Map> count;
		for (map<char, int>::iterator it = maps.begin(); it != maps.end(); it++) {
			Map tmp;
			tmp.ch = it->first;
			tmp.num = it->second;
			count.push_back(tmp);
		}

		sort(count.begin(), count.end(), cmp);
		
		if ( count.begin()->num > (len+1)/ 2 )
			return "";

		string ans = S;

		vector<Map>::iterator it = count.begin();
		//填充偶数位
		for (int i = 0; i < len; i += 2) {
			if (it->num == 0)
				it++;
			ans[i] = it->ch;
			it->num--;
		}

		//填充奇数位
		for (int i = 1; i < len; i += 2) {
			if (it->num == 0)
				it++;
			ans[i] = it->ch;
			it->num--;
		}

		
		return ans;
	}
};

u1s1, 我觉得我代码写的还是相当精炼的。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值