赞
踩
因为字符串s由小写字母构成,因此使用一个int[26]的数组保存每个字符的数量,然后从最大的字符开始构造结果字符串sb,基于贪心策略,如果当前剩下的最大字符cur的数量大于repeatLimit,则直接添加repeatLimit个cur到sb中,并且计数-repeatLimit,这时要使最终的sb字典序最大,则需要加入除cur外的字符中最大的字符,只需要加1个就行,作用是为了防止cur连续个数>repeatLimit。最终通过模拟构造除结果字符串sb
时间复杂度:O(|S|*n)。|S|表示26个字符,n表示字符串s的长度
空间复杂度:O(|S|)
public String repeatLimitedString(String s, int repeatLimit) { int[] ch=new int[26]; //计数 for(int i=0;i<s.length();i++){ char c=s.charAt(i); ch[c-'a']++; } StringBuilder sb=new StringBuilder(); //模拟 for(int i=25;i>=0;i--){ int index=i-1;//下一个最大字符 boolean f=false;//是添加下一个最大字符还是当前字符 while(index>=-1&&ch[i]>0){ if(!f){ //当前最大字符的数量大于等于repeatLimit,直接在结果集中加入repeatLimit个当前最大字符 if(ch[i]>repeatLimit){ ch[i]-=repeatLimit; sb.append(createS((char)('a'+i),repeatLimit)); }else{//当前最大字符的数量小于repeatLimit,直接在结果集中加入ch[i]个当前最大字符,当前最大字符清零 sb.append(createS((char)('a'+i),ch[i])); ch[i]=0; } f=!f; }else{ //找到比当前字符小的最大字符 while(index>=0&&ch[index]<=0){ index--; } // 能找到,则加入一个比当前字符小的最大字符 if(index>=0){ sb.append((char)('a'+index)); ch[index]-=1; }else{//找不到,结束循环 break; } f=!f; } } } return sb.toString(); } // 添加count个字符ch public StringBuilder createS(char ch,int count){ StringBuilder sb=new StringBuilder(); for(int i=0;i<count;i++){ sb.append(ch); } return sb; }
更优雅的官方题解
static public int N = 26; public String repeatLimitedString(String s, int repeatLimit) { int[] count = new int[N]; for (int i = 0; i < s.length(); i++) { count[s.charAt(i) - 'a']++; } StringBuilder ret = new StringBuilder(); int m = 0; for (int i = N - 1, j = N - 2; i >= 0 && j >= 0;) { if (count[i] == 0) { // 当前字符已经填完,填入后面的字符,重置 m m = 0; i--; } else if (m < repeatLimit) { // 当前字符未超过限制 count[i]--; ret.append((char)('a' + i)); m++; } else if (j >= i || count[j] == 0) { // 当前字符已经超过限制,查找可填入的其他字符 j--; } else { // 当前字符已经超过限制,填入其他字符,并且重置 m count[j]--; ret.append((char)('a' + j)); m = 0; } } return ret.toString(); }

自己做出来,但是代码没有官方的那么优雅,哈哈哈哈
有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。