重构字符串,使得两相邻的字符不同
题目链接:767. 重构字符串 - 力扣(LeetCode) (leetcode-cn.com)
参考文章:(17条消息) JAVA程序设计:重构字符串(LeetCode:767)_信仰.的博客-CSDN博客
思路一:排序
我们按照字符出现的频率进行排序,这样相同的字符此时是连续出现的,我们可以每隔一个字符空位插入一个字符,但是有一种特殊情况是出现次数最多的字符可能出现了(n+1)/2次,此时有可能前两个字符会出现相同的情况,为了避免这种情况,我们要使出现次数最多的字母排在最后,因此我们选择从小到大排序,问题解决了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| public String reorganizeString(String S) { int len=S.length(); int[] nums=new int[26]; for(char c : S.toCharArray()) { nums[c-'a']+=100; } for(int i=0;i<26;i++) { nums[i]+=i; } Arrays.parallelSort(nums); int t=1; char[] ans=new char[len]; for(int num : nums) { int ct=num/100; char ch=(char)('a'+(num%100)); if(ct>(len+1)/2) { return ""; } for(int i=0;i<ct;i++) { if(t>=len) { t=0; } ans[t]=ch; t+=2; } } return new String(ans); }
|
思路二:优先队列
我们考虑每次插入的字符是出现次数最多的字符,可以这么做的原因在于,只有当一个字符出现的次数超过 (N+1) / 2 的情况下,这个问题才无解。只要初试情况下这个条件满足,每次都输出剩余出现次数最多的字符就可以将这个条件一直保持下去
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| class node{ int count; char letter; public node(int count,char letter) { this.count=count; this.letter=letter; } }
public String reorganizeString(String S) { int len=S.length(); int[] nums=new int[26]; for(char c : S.toCharArray()) { nums[c-'a']++; } PriorityQueue<node> q=new PriorityQueue<node>( (a,b)->a.count==b.count?a.letter-b.letter:b.count-a.count); for(int i=0;i<26;i++) { if(nums[i]==0) { continue; } if(nums[i]>(len+1)/2) { return ""; } q.add(new node(nums[i],(char)('a'+i))); } StringBuilder ans=new StringBuilder(); while(q.size()>=2) { node a1=q.poll(); node a2=q.poll(); ans.append(a1.letter); ans.append(a2.letter); if(--a1.count>0) { q.add(a1); } if(--a2.count>0) { q.add(a2); } } if(q.size()>0) { ans.append(q.poll().letter); } return new String(ans); }
|