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的更多相关文章

  1. [LeetCode] Reorganize String 重构字符串

    Given a string S, check if the letters can be rearranged so that two characters that are adjacent to ...

  2. [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 就是给你一个字符串,能不 ...

  3. 767. Reorganize String - LeetCode

    Question 767. Reorganize String Solution 题目大意: 给一个字符串,将字符按如下规则排序,相邻两个字符一同,如果相同返回空串否则返回排序后的串. 思路: 首先找 ...

  4. LeetCode——Reverse String

    LeetCode--Reverse String Question Write a function that takes a string as input and returns the stri ...

  5. Leetcode 8. String to Integer (atoi) atoi函数实现 (字符串)

    Leetcode 8. String to Integer (atoi) atoi函数实现 (字符串) 题目描述 实现atoi函数,将一个字符串转化为数字 测试样例 Input: "42&q ...

  6. 767. Reorganize String

    Given a string S, check if the letters can be rearranged so that two characters that are adjacent to ...

  7. [LeetCode] 767. Reorganize String 重构字符串

    Given a string S, check if the letters can be rearranged so that two characters that are adjacent to ...

  8. 【LeetCode】767. Reorganize String 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.me/ 题目地址:https://leetcode.com/problems/reorganiz ...

  9. LeetCode - 767. Reorganize String

    Given a string S, check if the letters can be rearranged so that two characters that are adjacent to ...

随机推荐

  1. 【资料收集】Converting Between cv::Mat and QImage or QPixmap

    参考: 方法一 Convert between cv::Mat and QImage 两种图片类转换 - Grandyang - 博客园 http://www.cnblogs.com/grandyan ...

  2. asp.net MVC之Action过滤器浅析

    在asp.net MVC中,Action过滤器是一大利器,它可以在以下两个步骤执行相关的代码: 1.执行Action方法之前:OnActionExecuting 2.Action方法执行完毕后:OnA ...

  3. 异常处理机制中的return关键字

    Java中,执行try-catch-finally语句需要注意: 第一:return语句并不是函数的最终出口,如果有finally语句,这在return之后还会执行finally(return的值会暂 ...

  4. TypeError: write() argument must be str, not bytes报错原因及Python3写入二进制文件方法

    Python2随机写入二进制文件: with open('/python2/random.bin','w') as f: f.write(os.urandom(10)) 但使用Python3会报错: ...

  5. jstree使用新的

    1.首先准备jstree树的dom元素 <p id="flowList_ul" class="flowList_ul"></p> 2.初 ...

  6. Android: android studio配置生成自定义apk名称

    1.Android Studio 3.0之前: 在build.gradled 的 android {} 内添加如下代码: android.applicationVariants.all { varia ...

  7. Zabbix4.0监控URL

    一:新建群组 1.1:web monitor 二:新建模板 2.1:配置-模板-模板 2.3:创建应用集 配置-模板-web monitor-应用集 2.4:创建web场景 2.5:创建场景步骤: 以 ...

  8. Java 内存监控命令简介(零)

    一.Java性能监控与调优命令.工具简介 1.jps :查看当前运行的Java程序端口号,包括运行jps的程序端口号. 2.jinfo :查看Java进程的运行时信息. 3.jmap + MAT :通 ...

  9. ipv6地址管理

    为了彻底解决IPv4存在的问题,国际互联网工程任务组从1995年开始,着手研究开发下一代IP协议,即IPv6.可彻底解决IPv4地址不足的问题,除此之外,IPv6还采用分级地址模式.高效IP包头.主机 ...

  10. linux 安装crontab执行定时任务

    转载:https://www.cnblogs.com/xiaoluo501395377/archive/2013/04/06/3002602.html http://yangqijun.iteye.c ...