更多2023面试系列在主页文章
1. 华为OD机考题 + 答案
题目描述:
给定一个字符串的摘要算法,请输出给定字符串的摘要值
1、去除字符串中非字母的符号
2、如果出现连续字符 (不区分大小写) ,则输出: 该字符 (小) + 连续出现的次数
3、如果是非连续的字符(不区分大小写) ,则输出: 该字符(小写) 该字母之后字符串中出现的该字符的次数4、对按照以上方式表示后的字符串进行排序: 字母和紧随的数字作为一组进行排序,数字大的在前,数字相同的则按字母进行排序,字母小的在前。
输入描述:
行字符串,长度为[1,200]
输出描述:
摘要字符串
示例1
输入:
aabbcc
输出:
a2b2c2
示例2
输入:
bAaAcBb
输出:
a3b2b2c0
说明:
第一个b非连续字母,该字母之后字符串中还出现了2次 (最后的两个Bb) ,所以输出b2,a连续出现3次,输出a3,
c非连续,该字母之后字符串再没有出现过c,输出c0Bb连续2次,输出b2
对b2a3c0b2进行排序,最终输出a3b2b2c0
1. 使用正则表达式,将字母都获取出来
2. 使用双指针遍历
2.1 使用标志位判断是否连续字母,还是相隔的字母
2.2 连续的字母是累计当前次数+1,非连续字母是统计后面的字母数量
2.3 连续字母中断后,将右指针的值赋值给左指针,跳过这连续字母的下标
2.4 每次遍历后次数,右指针值重新赋值
2.5 储存是小写字母数值,这里的储存使用对象
3. 排序
3.1 先比较次数大小,相等在比较字母的顺序
- public static void main(String[] args) {
- Scanner sc = new Scanner(System.in);
- String value = sc.nextLine();
- StringBuffer sb = new StringBuffer();
- int index = 0;
- for (int i = 1; i <= value.length();i++){
- //1、去除字符串中非字母的符号
- Pattern pattern = Pattern.compile("[a-zA-Z]+");
- Matcher matcher = pattern.matcher((value.substring(index,i)));
- if (matcher.find()){
- sb.append(matcher.group());
- }
- index++;
- }
- List<Info> end = save(sb);
- sort(end);
- }
-
-
- public static List<Info> save(StringBuffer sb){
- //双指针
- int left = 0;
- int right = 1;
- int count = 0;
- Boolean flag = false;
- List<Info> infoList = new ArrayList<>();
- while (left != sb.length() && right != sb.length()) {
- //当前值
- String now = sb.substring(left, left + 1);
- //最后一个字符
- if (left + 1 == sb.length()) {
- Info info = new Info(0, now.toLowerCase(Locale.ROOT));
- infoList.add(info);
- break;
- }
- String after = sb.substring(right, right + 1);
- if (now.equalsIgnoreCase(after)) {
- count++;
- if (right - left <= 1) {
- flag = true;//是否连续标志
- }
- if (right + 1 == sb.length()) {
- if (flag) { //连续值+1
- count++;
- }
- Info info = new Info(count, now.toLowerCase(Locale.ROOT));
- infoList.add(info);
- //移动右指针
- right = left + 1;
- left++; //移动左指针
- count = 0;
- }
- right++;//连续值下标
-
- } else {
- // 2、如果出现连续字符 (不区分大小写) ,则输出: 该字符 (小) + 连续出现的次数
- if (flag) {//连续 中断时保存是数据
- left = right;//跳过连续值
- count++;
- Info info = new Info(count, now.toLowerCase(Locale.ROOT));
- infoList.add(info);
- count = 0;
- if (right + 1 == sb.length()) { //重新赋值右指针
- right = left + 1;
- }
- // 3、如果是非连续的字符(不区分大小写) ,则输出: 该字符(小写) 该字母之后字符串中出现的该字符的次数
- } else if (!flag) { //非连续
- if (right + 1 == sb.length()) {
- Info info = new Info(count, now.toLowerCase(Locale.ROOT));
- infoList.add(info);
- count = 0;
- right = left + 1;
- left++;
- }
- }
- right++;//跳过连续值
- if (right == sb.length()) {
- right = left;
- }
- flag = false;
- }
- }
- return infoList;
- }
-
- /**
- * 4、对按照以上方式表示后的字符串进行排序: 字母和紧随的数字作为一组进行排序,数字大的在前,数字相同的则按字母进行排序,字母小的在前。
- * @param infoList
- */
- public static void sort(List<Info> infoList){
- Collections.sort(infoList,new SoutSummary());
- infoList.forEach(data -> System.out.print(data.getS() + data.getCount()));
- }
-
- static class SoutSummary implements Comparator<Info>{
- @Override
- public int compare(Info o1, Info o2) {
- //先比较次数的大小
- if (o1.getCount() > o2.getCount()){
- return -1;
- }else if (o1.getCount() < o2.getCount()){
- return 1;
- //如果次数相等
- }else {
- return o2.getS().compareTo(o2.getS());
- }
- }
- }
-
-
-
- static class Info{
- int count;
- String s;
-
-
- public Info(int count, String s){
- this.count = count;
- this.s = s;
- }
-
- public Info() {
- }
-
- public int getCount() {
- return count;
- }
-
- public void setCount(int count) {
- this.count = count;
- }
-
- public String getS() {
- return s;
- }
-
- public void setS(String s) {
- this.s = s;
- }
- }