LeetCode - 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].
这道题给了我们一个字符串,让我们重构这个字符串,使得相同的字符不会相邻,如果无法做到,那么就返回空串,题目中的例子很好的说明了这一点。那么,如果先不考虑代码实现,让你来手动重构的话,该怎么做呢?我们要做的就是把相同的字符分开。比如例子1中,两个a相邻了,所以我们把第二个a和后面的b交换位置,这样分开了相同的字符,就是最终答案了。我们再来看一个例子,比如"aaabbc",那么其实我们发现第二个字符也是‘a’的时候,就需要往后遍历找到第一个不是‘a’的字符,即‘b’,然后交换‘a’和‘b’即可,然后继续往后面进行同样的处理,当无法找到不同的字符后就返回空串。这种方法对有序的字符串S是可以的,虽然题目给的两个例子中字符串S都是有序的,实际上不一定是有序的。所以博主最先的想法是给数组排序呗,但是博主的这个解法跪在了这个例子上"vvvlo",我们发现排序后就变成"lovvv",这样上面提到的解法就跪了。我们希望次数出现多的字符串再前面,这样才好交换嘛。那么我们还是要统计每个字符串出现的次数啊,这里使用HashMap来建立字母和其出现次数之间的映射。由于我们希望次数多的字符排前面,可以使用一个最大堆,C++中就是优先队列Priority Queue,将次数当做排序的key,那么就把次数和其对应的字母组成一个pair,放进最大堆中自动排序。这里其实有个剪枝的trick,如果某个字母出现的频率大于总长度的一半了,那么必然会有两个相邻的字母出现。这里博主就不证明了,感觉有点像抽屉原理。所以我们在将映射对加入优先队列时,先判断下次数,超过总长度一半了的话直接返回空串就行了。
好,我们的最大堆建立好以后,我们想,此时难道还是应该使用上面所说的交换的方法吗?其实直接构建新的字符串要更加简单一些。接下来,我们每次从优先队列中取队首的两个映射对儿处理,因为我们要拆开相同的字母,这两个映射对儿肯定是不同的字母,我们可以将其放在一起,之后我们需要将两个映射对儿中的次数自减1,如果还有多余的字母,即减1后的次数仍大于0的话,将其再放回最大堆。由于我们是两个两个取的,所以最后while循环退出后,有可能优先队列中还剩下了一个映射对儿,此时将其加入结果res即可。而且这个多余的映射对儿一定只有一个字母了,因为我们提前判断过各个字母的出现次数是否小于等于总长度的一半,按这种机制来取字母,不可能会剩下多余一个的相同的字母.
这道题我之前不明白的是为什么一定要使用priorityQueue最大堆来做,后来写完之后才明白, 如果不用最大堆,可能会出现最后存在的那个映射和前一个是一样,列子“aab”.
注意map, priorityqueue的各种方法
class Solution {
public String reorganizeString(String S) {
if(S == null || S.length() == 0){
return "";
}
Map<Character, Integer> map = new HashMap<>();
for(char c: S.toCharArray()){
map.put(c, map.getOrDefault(c,0)+1);
}
//anonymous class
PriorityQueue<Map.Entry<Character, Integer>> pq = new PriorityQueue<>(new Comparator<Map.Entry<Character, Integer>>() {
public int compare(Map.Entry<Character, Integer> o1, Map.Entry<Character, Integer> o2) {
return o2.getValue() - o1.getValue();
}
});
//pq.addAll(map.entrySet());
for(Map.Entry<Character, Integer> entry : map.entrySet()){
if(entry.getValue() > (S.length()+1)/2){
return "";
}
pq.add(entry);
}
StringBuilder sb = new StringBuilder();
while(pq.size() > 1){
Map.Entry<Character, Integer> entry1 = pq.poll();
Map.Entry<Character, Integer> entry2 = pq.poll();
sb.append(entry1.getKey());
sb.append(entry2.getKey());
if(entry1.getValue() -1 > 0){
entry1.setValue(entry1.getValue() -1);
pq.add(entry1);
}
if(entry2.getValue() -1 > 0){
entry2.setValue(entry2.getValue() -1);
pq.add(entry2);
}
}
if(pq.size() > 0){
sb.append(pq.poll().getKey());
}
return sb.toString();
}
}
LeetCode - Reorganize String的更多相关文章
- [LeetCode] Reorganize String 重构字符串
Given a string S, check if the letters can be rearranged so that two characters that are adjacent to ...
- [leetcode]Weekly Contest 68 (767. Reorganize String&&769. Max Chunks To Make Sorted&&768. Max Chunks To Make Sorted II)
766. Toeplitz Matrix 第一题不说,贼麻瓜,好久没以比赛的状态写题,这个题浪费了快40分钟,我真是...... 767. Reorganize String 就是给你一个字符串,能不 ...
- 767. Reorganize String - LeetCode
Question 767. Reorganize String Solution 题目大意: 给一个字符串,将字符按如下规则排序,相邻两个字符一同,如果相同返回空串否则返回排序后的串. 思路: 首先找 ...
- LeetCode——Reverse String
LeetCode--Reverse String Question Write a function that takes a string as input and returns the stri ...
- Leetcode 8. String to Integer (atoi) atoi函数实现 (字符串)
Leetcode 8. String to Integer (atoi) atoi函数实现 (字符串) 题目描述 实现atoi函数,将一个字符串转化为数字 测试样例 Input: "42&q ...
- 767. Reorganize String
Given a string S, check if the letters can be rearranged so that two characters that are adjacent to ...
- [LeetCode] 767. Reorganize String 重构字符串
Given a string S, check if the letters can be rearranged so that two characters that are adjacent to ...
- 【LeetCode】767. Reorganize String 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.me/ 题目地址:https://leetcode.com/problems/reorganiz ...
- LeetCode - 767. Reorganize String
Given a string S, check if the letters can be rearranged so that two characters that are adjacent to ...
随机推荐
- mySQL 分组查询,根据分组的字段,取最小值
今天看到别人问的问题,给别人写了一条sql! CREATE TEMPORARY TABLE tmp_table ( id INTEGER not NULL, uname VARCHAR(10) NOT ...
- Java基础-流程控制语句与运算符
运算符 算术运算符 ++ -- 在前时先运算后取值:在后时先取值后运算 关系运算符 == !=也可以是引用类型 位运算符 逻辑运算符 赋值运算符 条件运算符 (?:) 布尔表达式 ? 表达式1 : 表 ...
- <Spark><Running on a Cluster>
Introduction 之前学习的时候都是通过使用spark-shell或者是在local模式运行spark 这边我们首先介绍Spark分布式应用的架构,然后讨论在分布式clusters中运行Spa ...
- L262
A London patient has become the second known man worldwide to be cleared of AIDS virus after receivi ...
- MySQL:存储过程和函数
存储过程和函数 一.创建存储过程和函数 1.创建存储过程 语法: CREATE PROCEDURE sp_name ([proc_parameter[,...]]) [characteristic . ...
- 在使用Idea配置jQuery的问题
今天使用idea中引入jQuery代码时,发生的几个错误,时刻提醒 1.jQuery的驱动包要放置在web目录下 2.引入jQuery的驱动包时,语句格式为<script></scr ...
- mysql ON DUPLICATE KEY UPDATE ; 以及 同replace to 的区别.
需求: 1)如果admin表中没有数据, 插入一条 2)如果admin表中有数据, 不插入. 一般做法: if($result = mysql_query("select * from ad ...
- mysql字段添加修改删除
MySQL添加字段和修改字段 MySQL添加字段的方法并不复杂,下面将为您详细介绍MYSQL添加字段和修改字段等操作的实现方法,希望对您学习MySQL添加字段方面会有所帮助. 1添加表字段 alt ...
- python day05--字典
一.字典结构 {key:valu} 注意: key必须是不可变(可哈希)的. value没有要求.可以保存任意类型的数据. dic = {123: 456, True: 999, "id&q ...
- ngxinx 配置
vim 复制操作 1.复制 1)单行复制 在命令模式下,将光标移动到将要复制的行处,按“yy”进行复制: 2)多行复制 在命令模式下,将光标移动到将要复制的首行处,按“nyy”复制n行: 其中n为1. ...