ホームページ記事の 2023 年のインタビュー シリーズの詳細
1. Huawei OD マシンテストの質問と回答
トピックの説明:
文字列のダイジェスト アルゴリズムが指定された場合は、指定された文字列のダイジェスト値を出力してください。
1. 文字列内の文字以外の記号を削除します。
2. 連続文字が出現する場合 (大文字と小文字は区別されません)、出力: 文字 (小) + 連続出現数
3. 非連続文字 (大文字と小文字は区別されない) の場合、出力: 文字 (小文字)、文字列内でその文字が文字の後に出現する回数 4. 上記の方法で表現された文字列を並べ替えます: 文字および 後続の番号は、大きい番号から順にグループとして並べ替えられ、同じ番号を持つ番号は、小さい文字から順にアルファベット順に並べ替えられます。
説明を入力してください:
行文字列、長さ [1,200]
出力の説明:
要約文字列
例1
入力:
aabbcc
出力:
a2b2c2
例 2
入力:
ばあAcBb
出力:
a3b2b2c0
例証します:
最初の b は連続しない文字で、この文字以降は文字列内に 2 回出現するため (最後の 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;
}
}