目录

题目

思路

Code


题目

给定一组命令行字符串和一个命令前缀,需要找出所有以前缀开头的命令行表达式中,前缀之后的第一个关键字,并将这些关键字按字典序排序后返回。
如果找不到匹配前缀则返回空;匹配出多个相同关键字时只返回一个。

完整示例

示例1:
给定命令行表达式 ["display device","display port status"],输入前缀是 "display",则返回 ["device","port"]。

示例2:
给定命令行表达式 ["set negotiation mode","set port down"],输入前缀是 "",则返回 ["set"]。

示例3:
给定命令行表达式 ["git commit -m message","git push origin master","git pull"],输入前缀是 "git",则返回 ["commit","pull","push"]。

补充说明:

  1. 命令行条数 0~1000,每个命令行长度为 [1,200]
  2. 每个命令行表达式中的关键字由小写字母、- 组成
  3. 命令行关键字不包含空格,关键字之间用空格分隔
  4. 只有关键字之间的空格有意义,字符串首尾空格需要忽略,如 "a" 等价于 "a "," a b" 等价于 "a b"

输入描述:

  • 第一行输入前缀
  • 从第二行到结束,每行输入一个命令行

输出描述:

  • 找出所有以前缀开头的命令行表达式中,前缀之后的第一个关键字,并按字典序排序后输出,以空格分割

样例1
输入:

display
display port status
display device

输出:

device port

说明:
每个命令行都和前缀 "display" 匹配,返回每个命令的第二个关键字。

样例2
输入:

set negotiation mode

set port down

输出:

set

说明:
首先匹配 "" 的命令关键字为 2 个 "set",去重后返回 1 个 "set"。

思路

字符串模拟操作类型的题目,较为简单。

先把前缀和每条命令都按空白字符拆成关键字数组。如果命令的前若干个关键字和前缀关键字完全一致,就说明匹配成功。此时取“前缀之后的第一个关键字”加入集合去重,最后将集合排序并用空格拼接输出。

关键点有两个:

  • 要先 strip + split,这样才能正确处理题目说的“首尾空格无意义”
  • 如果前缀刚好等于整条命令,没有“后一个关键字”,这种情况不能加入结果

Code

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;

public class Main {
    static List<String> normalize(String command) {
        command = command.trim();
        if (command.isEmpty()) {
            return new ArrayList<>();
        }

        // 按一个或多个空白字符切分,兼容多空格情况。
        return Arrays.asList(command.split("\\s+"));
    }

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        List<String> lines = new ArrayList<>();
        String line;

        // 保留第一行前缀;其余行作为命令输入。
        while ((line = br.readLine()) != null) {
            lines.add(line);
        }

        if (lines.isEmpty()) {
            return;
        }

        List<String> prefixTokens = normalize(lines.get(0));
        Set<String> result = new TreeSet<>();

        for (int i = 1; i < lines.size(); i++) {
            List<String> commandTokens = normalize(lines.get(i));

            // 空命令行不产生结果。
            if (commandTokens.isEmpty()) {
                continue;
            }

            // 如果前缀比命令还长,不可能匹配。
            if (prefixTokens.size() > commandTokens.size()) {
                continue;
            }

            boolean match = true;

            // 逐个关键字判断前缀是否匹配。
            for (int j = 0; j < prefixTokens.size(); j++) {
                if (!prefixTokens.get(j).equals(commandTokens.get(j))) {
                    match = false;
                    break;
                }
            }

            if (!match) {
                continue;
            }

            // 前缀之后必须还有一个关键字,才加入答案。
            if (commandTokens.size() > prefixTokens.size()) {
                result.add(commandTokens.get(prefixTokens.size()));
            }
        }

        System.out.print(String.join(" ", result));
    }
}

C

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

#define MAX_LINES 1005
#define MAX_LEN 205
#define MAX_TOKENS 205

void normalize(const char *command, char tokens[][MAX_LEN], int *count) {
    char buffer[MAX_LEN];
    strcpy(buffer, command);

    *count = 0;
    char *token = strtok(buffer, " \t\r\n");
    while (token != NULL) {
        strcpy(tokens[*count], token);
        (*count)++;
        token = strtok(NULL, " \t\r\n");
    }
}

int main() {
    char lines[MAX_LINES][MAX_LEN];
    int lineCount = 0;

    while (fgets(lines[lineCount], sizeof(lines[lineCount]), stdin)) {
        lines[lineCount][strcspn(lines[lineCount], "\r\n")] = '\0';
        lineCount++;
    }

    if (lineCount == 0) {
        return 0;
    }

    char prefixTokens[MAX_TOKENS][MAX_LEN];
    int prefixCount = 0;
    normalize(lines[0], prefixTokens, &prefixCount);

    char result[MAX_TOKENS][MAX_LEN];
    int resultCount = 0;

    for (int i = 1; i < lineCount; i++) {
        char commandTokens[MAX_TOKENS][MAX_LEN];
        int commandCount = 0;
        normalize(lines[i], commandTokens, &commandCount);

        // 空命令行跳过。
        if (commandCount == 0) {
            continue;
        }

        if (prefixCount > commandCount) {
            continue;
        }

        int match = 1;
        for (int j = 0; j < prefixCount; j++) {
            if (strcmp(prefixTokens[j], commandTokens[j]) != 0) {
                match = 0;
                break;
            }
        }

        if (!match) {
            continue;
        }

        if (commandCount > prefixCount) {
            char *candidate = commandTokens[prefixCount];

            // 手动去重。
            int exists = 0;
            for (int k = 0; k < resultCount; k++) {
                if (strcmp(result[k], candidate) == 0) {
                    exists = 1;
                    break;
                }
            }

            if (!exists) {
                strcpy(result[resultCount++], candidate);
            }
        }
    }

    // 简单字典序排序。
    for (int i = 0; i < resultCount; i++) {
        for (int j = i + 1; j < resultCount; j++) {
            if (strcmp(result[i], result[j]) > 0) {
                char tmp[MAX_LEN];
                strcpy(tmp, result[i]);
                strcpy(result[i], result[j]);
                strcpy(result[j], tmp);
            }
        }
    }

    for (int i = 0; i < resultCount; i++) {
        if (i > 0) {
            printf(" ");
        }
        printf("%s", result[i]);
    }

    return 0;
}

GO

package main

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

func normalize(command string) []string {
	// strings.Fields 会自动忽略首尾空格,并按连续空白切分。
	return strings.Fields(command)
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	lines := make([]string, 0)

	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}

	if len(lines) == 0 {
		return
	}

	prefixTokens := normalize(lines[0])
	resultSet := make(map[string]bool)

	for i := 1; i < len(lines); i++ {
		commandTokens := normalize(lines[i])

		// 空命令行不会贡献关键字。
		if len(commandTokens) == 0 {
			continue
		}

		if len(prefixTokens) > len(commandTokens) {
			continue
		}

		match := true
		for j := 0; j < len(prefixTokens); j++ {
			if prefixTokens[j] != commandTokens[j] {
				match = false
				break
			}
		}

		if !match {
			continue
		}

		if len(commandTokens) > len(prefixTokens) {
			resultSet[commandTokens[len(prefixTokens)]] = true
		}
	}

	result := make([]string, 0, len(resultSet))
	for word := range resultSet {
		result = append(result, word)
	}

	sort.Strings(result)
	fmt.Print(strings.Join(result, " "))
}

【华为od机试真题Python+JS+Java+Go合集】【超值优惠】:Py/JS/Java/Go合集

【华为od机试真题Python】:Python真题题库

【华为od机试真题JavaScript】:JavaScript真题题库

【华为od机试真题Java&Go】:Java&Go真题题库

【华为od机试真题C++】:C++真题题库

【华为od机试真题C语言】:C语言真题题库

【华为od面试手撕代码题库】:面试手撕代码题库

【华为od机试面试交流群】【文章底部有二维码链接,可扫码加交流群】

华为OD机试:二本院校有机会吗?
有机会,但不大,大神除外!机考分数越高越好,所以需要提前刷题。机考通过后,如果没有收到面试邀请,也不要着急,非目标院校面试邀请发的时间比较晚。非目标院校今年有点难,机试至少要考到350分,所以需要疯狂刷题,华为OD机考是有题库的,最好在考前完所有题库题目。华为OD机试:跨专业可以参加华为OD可以,但是如果你的本科院校比较差,上岸概率不大。华为OD机试:华为OD简历被锁定机试通过,性格测试也通过,但是没人联系面试,发现简历被锁定。此时需要主动去联系HR。让他帮助你查询原因。

更多推荐