更多2023面试系列在主页文章
1. 华为OD机考题 + 答案
2023华为OD统一考试(A+B卷)题库清单-带答案(持续更新)
题目描述:
给定一个字符串的摘要算法,请输出给定字符串的摘要值
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;
}
}