字符串处理

2026 华为OD机试真题 6月17日华为OD上机新系统考试真题 100 分题型

点击查看华为 OD 机试真题完整目录:2026最新华为OD机试新系统卷 + 双机位C卷 真题题库目录|全覆盖题库 + 逐点算法考点详解

题目描述

给定一个字符串 s,以及字符串子串的长度 n,要求:

  1. 把 s 按照 n 的长度进行字符串子串拆分;
  2. 每个子串不允许出现重复的字符,如果出现,则保留最后一个,例如 “aba” 处理后会变成 “ba”,因为第一个 ‘a’ 出现重复,因此第一个 ‘a’ 被删除,保留了最后一个 ‘a’;
  3. 字符串 s 的长度不一定恰好是 n 的倍数,最后一个数据包可能少于 n 个字符,但处理规则不变;

最后把所有子串再次拼接,输出一个新的字符串。

输入描述

  • 第一行输入一个字符串 s,字符串不为空且仅包含小写字母,长度不超过 1000。
  • 第二行输入一个整数 n (1≤n≤1000),表示子串的长度。

输出描述

  • 输出一个字符串,表示处理后的新的字符串。

示例1

输入

abaabacbda,3

输出

babacbda

说明

原始字符串分成 4 个子串: “aba”、“aba”、“cbd”、“a”。

  • “aba” 处理为 “ba”
  • “aba” 处理为 “ba”
  • “cbd” 处理为 “cbd”
  • “a” 处理为 “a” 拼接得到 “ba” + “ba” + “cbd” + “a” = “babacbda”。

示例2

输入

aaabbb,2

输出

aabb

说明

原始字符串分成 3 个子串: “aa”、“ab”、“bb”。

  • “aa” 处理为 “a”
  • “ab” 处理为 “ab”
  • “bb” 处理为 “b"拼接得到"a”+“ab”+“b”=“aabb$”。

示例3

输入

a,1

输出

a

说明

只有 1 个字符,结果为 “a”

示例4

输入

a,1000

输出

a

说明

只有 1 个字符,结果为 “a”

解题思路

本题的关键是 如何高效地保留每个字符的最后一次出现位置

算法步骤:

  1. 将字符串 s 按长度 n 分割成多个子串
  2. 对于每个子串:
    • 记录每个字符最后一次出现的位置(索引)
    • 遍历子串,只保留那些索引等于最后一次出现位置的字符
  3. 将处理后的所有子串拼接起来

去重逻辑:

  • 遍历子串时,用字典记录每个字符最后出现的索引
  • 再次遍历时,只保留 当前位置 == 该字符最后出现位置 的字符

为什么这样有效?

  • “aba” -> last = {‘a’:2, ‘b’:1} -> 遍历[0,1,2],保留索引为1,2的字符 -> “ba”

复杂度分析

  • 时间复杂度:O(s),s 为字符串长度,每个字符最多遍历两次
  • 空间复杂度:O(n),存储字符最后出现位置的字典

Java

import java.util.*;

/**
 * 华为OD机试真题 - 字符串处理
 */
public class Main {
    
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // 读取字符串 s(可能包含逗号分隔的输入格式)
        String firstLine = scanner.nextLine().trim();
        String s;
        int n;
        
        // 处理可能出现的逗号分隔格式
        if (firstLine.contains(",")) {
            String[] parts = firstLine.split(",");
            s = parts[0].trim();
            n = Integer.parseInt(parts[1].trim());
        } else {
            s = firstLine;
            n = Integer.parseInt(scanner.nextLine().trim());
        }
        
        String result = processChunks(s, n);
        System.out.println(result);
    }
    
    /**
     * 核心算法:处理字符串块
     */
    public static String processChunks(String s, int n) {
        StringBuilder result = new StringBuilder();
        
        // 按长度 n 分割字符串
        for (int i = 0; i < s.length(); i += n) {
            int end = Math.min(i + n, s.length());
            String chunk = s.substring(i, end);
            result.append(dedup(chunk));
        }
        
        return result.toString();
    }
    
    /**
     * 去重函数:只保留字符最后一次出现的位置
     */
    private static String dedup(String chunk) {
        // 记录每个字符最后出现的位置
        Map<Character, Integer> lastPos = new HashMap<>();
        for (int i = 0; i < chunk.length(); i++) {
            lastPos.put(chunk.charAt(i), i);
        }
        
        // 只保留每个字符最后一次出现的位置
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < chunk.length(); i++) {
            if (lastPos.get(chunk.charAt(i)) == i) {
                sb.append(chunk.charAt(i));
            }
        }
        
        return sb.toString();
    }
}

Python

"""
华为OD机试真题 - 字符串处理

本题的关键是高效保留每个字符的最后一次出现位置。
"""
from typing import List


class Solution:
    def processChunks(self, s: str, n: int) -> str:
        """
        核心算法:处理字符串块
        
        Args:
            s: 输入字符串
            n: 子串长度
            
        Returns:
            处理后的字符串
        """
        result_parts = []
        
        # 按长度 n 分割字符串
        for i in range(0, len(s), n):
            chunk = s[i : i + n]
            result_parts.append(self._dedup(chunk))
        
        return "".join(result_parts)
    
    def _dedup(self, chunk: str) -> str:
        """
        去重函数:只保留字符最后一次出现的位置
        
        算法:
        1. 遍历字符串,记录每个字符最后出现的位置
        2. 再次遍历,只保留当前位置等于该字符最后出现位置的字符
        """
        # 记录每个字符最后出现的位置
        last_pos = {}
        for idx, char in enumerate(chunk):
            last_pos[char] = idx
        
        # 只保留每个字符最后一次出现的位置
        return "".join(char for idx, char in enumerate(chunk) if last_pos[char] == idx)


if __name__ == "__main__":
    # 读取输入
    first_line = input().strip()
    
    # 处理可能出现的逗号分隔格式
    if ',' in first_line:
        parts = first_line.split(',')
        s = parts[0].strip()
        n = int(parts[1].strip())
    else:
        s = first_line
        n = int(input().strip())
    
    # 调用核心算法
    result = Solution().processChunks(s, n)
    
    # 输出结果
    print(result)

JavaScript

/**
 * 华为OD机试真题 - 字符串处理
 */

/**
 * 去重函数:只保留字符最后一次出现的位置
 */
function dedup(chunk) {
    // 记录每个字符最后出现的位置
    const lastPos = new Map();
    for (let i = 0; i < chunk.length; i++) {
        lastPos.set(chunk[i], i);
    }
    
    // 只保留每个字符最后一次出现的位置
    let result = '';
    for (let i = 0; i < chunk.length; i++) {
        if (lastPos.get(chunk[i]) === i) {
            result += chunk[i];
        }
    }
    
    return result;
}

/**
 * 核心算法:处理字符串块
 */
function processChunks(s, n) {
    let result = '';
    
    // 按长度 n 分割字符串
    for (let i = 0; i < s.length; i += n) {
        const chunk = s.substring(i, Math.min(i + n, s.length));
        result += dedup(chunk);
    }
    
    return result;
}

// 读取输入
const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin
});

const lines = [];
rl.on('line', (line) => {
    lines.push(line.trim());
});

rl.on('close', () => {
    // 处理可能出现的逗号分隔格式
    let s, n;
    if (lines[0].includes(',')) {
        const parts = lines[0].split(',');
        s = parts[0].trim();
        n = parseInt(parts[1].trim());
    } else {
        s = lines[0];
        n = parseInt(lines[1]);
    }
    
    const result = processChunks(s, n);
    console.log(result);
});

C++

#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>

using namespace std;

/**
 * 华为OD机试真题 - 字符串处理
 */

/**
 * 去重函数:只保留字符最后一次出现的位置
 */
string dedup(const string& chunk) {
    // 记录每个字符最后出现的位置
    unordered_map<char, int> lastPos;
    for (int i = 0; i < chunk.length(); i++) {
        lastPos[chunk[i]] = i;
    }
    
    // 只保留每个字符最后一次出现的位置
    string result;
    for (int i = 0; i < chunk.length(); i++) {
        if (lastPos[chunk[i]] == i) {
            result += chunk[i];
        }
    }
    
    return result;
}

/**
 * 核心算法:处理字符串块
 */
string processChunks(const string& s, int n) {
    string result;
    
    // 按长度 n 分割字符串
    for (int i = 0; i < s.length(); i += n) {
        string chunk = s.substr(i, min(n, (int)s.length() - i));
        result += dedup(chunk);
    }
    
    return result;
}

int main() {
    string firstLine;
    getline(cin, firstLine);
    
    string s;
    int n;
    
    // 处理可能出现的逗号分隔格式
    size_t commaPos = firstLine.find(',');
    if (commaPos != string::npos) {
        s = firstLine.substr(0, commaPos);
        n = stoi(firstLine.substr(commaPos + 1));
    } else {
        s = firstLine;
        cin >> n;
    }
    
    string result = processChunks(s, n);
    cout << result << endl;
    
    return 0;
}

Go

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

/**
 * 华为OD机试真题 - 字符串处理
 */

/**
 * 去重函数:只保留字符最后一次出现的位置
 */
func dedup(chunk string) string {
	// 记录每个字符最后出现的位置
	lastPos := make(map[rune]int)
	for i, c := range chunk {
		lastPos[c] = i
	}
	
	// 只保留每个字符最后一次出现的位置
	result := strings.Builder{}
	for i, c := range chunk {
		if lastPos[c] == i {
			result.WriteRune(c)
		}
	}
	
	return result.String()
}

/**
 * 核心算法:处理字符串块
 */
func processChunks(s string, n int) string {
	result := strings.Builder{}
	
	// 按长度 n 分割字符串
	for i := 0; i < len(s); i += n {
		end := i + n
		if end > len(s) {
			end = len(s)
		}
		chunk := s[i:end]
		result.WriteString(dedup(chunk))
	}
	
	return result.String()
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	scanner.Scan()
	firstLine := scanner.Text()
	
	var s string
	var n int
	
	// 处理可能出现的逗号分隔格式
	if strings.Contains(firstLine, ",") {
		parts := strings.Split(firstLine, ",")
		s = strings.TrimSpace(parts[0])
		n, _ = strconv.Atoi(strings.TrimSpace(parts[1]))
	} else {
		s = strings.TrimSpace(firstLine)
		scanner.Scan()
		n, _ = strconv.Atoi(scanner.Text())
	}
	
	result := processChunks(s, n)
	fmt.Println(result)
}

C语言

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/**
 * 华为OD机试真题 - 字符串处理
 */

/**
 * 去重函数:只保留字符最后一次出现的位置
 */
char* dedup(const char* chunk) {
    int len = strlen(chunk);
    
    // 记录每个字符最后出现的位置
    int lastPos[256] = {0};
    for (int i = 0; i < len; i++) {
        lastPos[(unsigned char)chunk[i]] = i;
    }
    
    // 分配结果字符串
    char* result = (char*)malloc((len + 1) * sizeof(char));
    int resultLen = 0;
    
    // 只保留每个字符最后一次出现的位置
    for (int i = 0; i < len; i++) {
        if (lastPos[(unsigned char)chunk[i]] == i) {
            result[resultLen++] = chunk[i];
        }
    }
    result[resultLen] = '\0';
    
    return result;
}

/**
 * 核心算法:处理字符串块
 */
char* processChunks(const char* s, int n) {
    int len = strlen(s);
    char* result = (char*)malloc((len + 1) * sizeof(char));
    int resultLen = 0;
    
    // 按长度 n 分割字符串
    for (int i = 0; i < len; i += n) {
        int chunkLen = (i + n < len) ? n : (len - i);
        char* chunk = (char*)malloc((chunkLen + 1) * sizeof(char));
        strncpy(chunk, s + i, chunkLen);
        chunk[chunkLen] = '\0';
        
        char* deduped = dedup(chunk);
        strcpy(result + resultLen, deduped);
        resultLen += strlen(deduped);
        
        free(chunk);
        free(deduped);
    }
    result[resultLen] = '\0';
    
    return result;
}

int main() {
    char firstLine[2000];
    gets(firstLine);
    
    char s[1001];
    int n;
    
    // 处理可能出现的逗号分隔格式
    char* commaPos = strchr(firstLine, ',');
    if (commaPos != NULL) {
        *commaPos = '\0';
        sscanf(firstLine, "%s", s);
        sscanf(commaPos + 1, "%d", &n);
    } else {
        sscanf(firstLine, "%s", s);
        scanf("%d", &n);
    }
    
    char* result = processChunks(s, n);
    printf("%s\n", result);
    
    free(result);
    return 0;
}

完整用例

用例1

输入:

abaabacbda,3

用例2

输入:

aaabbb,2

用例3

输入:

a,1

用例4

输入:

a,1000

用例5

输入:

abcabcabc,3

用例6

输入:

abcdefghi,4

用例7

输入:

zzzz,2

用例8

输入:

hello,3

用例9

输入:

abacabadabacaba,5

用例10

输入:

abc,100

在这里插入图片描述

更多推荐