【华为笔试题汇总】2024-05-22-华为春招笔试题-三语言题解(Python/Java/Cpp)

🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员

✨ 本系列打算持续跟新小米近期的春秋招笔试题汇总~

💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导

👏 感谢大家的订阅➕ 和 喜欢💗

📧 清隆这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 清隆领取,会在飞书进行同步的跟新。

🧷 01.获取公共链表片段

问题描述

给定两个链表,找出它们中相同节点值的最大连续片段。如果没有公共片段,返回 -1。

输入格式

第一行表示链表 1,第二行表示链表 2。每条链表长度不超过 20 个元素,链表不会为空。

输出格式

输出两个链表中相同节点值的最大连续片段。如果没有公共片段,返回 -1。

样例输入

1 2 2 3 9 1 5
9 2 2 3 6 8

样例输出

2 2 3

数据范围

链表长度不超过 20 个元素。

题解

本题数据范围比较小,怎么做都可以,使用双重循环遍历两个链表,并在找到相同节点时,继续向后比较,直到不相同为止。记录最长的公共片段并输出。

参考代码

  • Python
a, b = list(map(int, input().split())), list(map(int, input().split()))
n, m = len(a), len(b)
max_len = 0
res = []
for i in range(n):
    for j in range(m):
        if a[i] == b[j]:
            z = i
            for k in range(j, m):
                if b[k] != a[z]:
                    break
                z += 1
            if z - i > max_len:
                max_len = z - i
                res = a[i:z]
print(*res if res else -1)
  • Java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        List<Integer> a = new ArrayList<>();
        List<Integer> b = new ArrayList<>();
        
        while (sc.hasNextInt()) {
            a.add(sc.nextInt());
        }
        sc.nextLine();
        while (sc.hasNextInt()) {
            b.add(sc.nextInt());
        }
        
        int n = a.size();
        int m = b.size();
        int maxLen = 0;
        List<Integer> res = new ArrayList<>();
        
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (a.get(i).equals(b.get(j))) {
                    int z = i;
                    int k = j;
                    while (k < m && z < n && a.get(z).equals(b.get(k))) {
                        z++;
                        k++;
                    }
                    if (z - i > maxLen) {
                        maxLen = z - i;
                        res = a.subList(i, z);
                    }
                }
            }
        }
        
        if (res.isEmpty()) {
            System.out.println(-1);
        } else {
            for (int num : res) {
                System.out.print(num + " ");
            }
        }
    }
}
  • Cpp
#include <iostream>
#include <vector>
using namespace std;

int main() {
    vector<int> a, b;
    int num;
    while (cin >> num) {
        a.push_back(num);
        if (cin.get() == '\n') break;
    }
    while (cin >> num) {
        b.push_back(num);
        if (cin.get() == '\n') break;
    }
    
    int n = a.size(), m = b.size();
    int max_len = 0;
    vector<int> res;
    
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            if (a[i] == b[j]) {
                int z = i;
                int k = j;
                while (k < m && z < n && a[z] == b[k]) {
                    ++z;
                    ++k;
                }
                if (z - i > max_len) {
                    max_len = z - i;
                    res.assign(a.begin() + i, a.begin() + z);
                }
            }
        }
    }
    
    if (res.empty()) {
        cout << -1 << endl;
    } else {
        for (int num : res) {
            cout << num << " ";
        }
    }
    
    return 0;
}

🔗 02.矿车运输成本

问题描述

露天矿采矿作业的特点是规模大,矿石和废料的移动量达到百万吨,运输成本开销较大,需要寻求一种最优的运输路径节省成本。

已知矿场可以划分成 N × M N \times M N×M 的网格图,每个网格存在地形的差异,因此通过不同网格时,成本开销存在差异。

网格有以下 5 种类型:

  1. 标志为 ‘S’ 的网格为运输起点;
  2. 标志为 ‘E’ 的网格为运输终点;
  3. 标志为 ‘B’ 的网格为阻塞点,不允许通行;
  4. 标志为 ‘C’ 的网格为检查点,矿车在运输路径中,至少需要进入一次检查点;
  5. 标志为数字的网格,其数字表示经过该网格的成本开销。

运输矿车只能上下左右 4 个方向运行,不允许斜对角进入其他网格。必要时可重复进入网格。请根据输入的网格图,寻求一条从 ‘S’ 网格到 ‘E’ 网格,并且至少经过一次检查点的最低成本运输路径,并输出其成本开销。

输入格式

第一行包含两个正整数 N N N M M M,表示网格图的行数和列数,使用空格隔开。

接下来的 N N N 行,每行包含 M M M 个元素,元素可以为 ‘S’,‘E’,‘B’,‘C’ 或者数字 [0, 100],并且有且仅有一个 ‘S’ 和一个 ‘E’,同时存在一个或者多个 ‘C’,并依次使用空格隔开。

输出格式

输出运输最低成本开销。如果不存在可达通路,请输出 -1。

样例输入

3 3
S 4 5
7 B 3
C 9 E

样例输出

16

数据范围

  • 3 ≤ N ≤ 200 3 \leq N \leq 200 3N200
  • 3 ≤ M ≤ 200 3 \leq M \leq 200 3M200

题解

为了找到从起点 ‘S’ 到终点 ‘E’ 并且至少经过一次检查点 ‘C’ 的最低成本路径,可以跑两次 dijkstra。首先从起点 ‘S’ 到每个检查点 ‘C’ 计算最短路径,然后从每个检查点 ‘C’ 到终点 ‘E’ 计算最短路径,最后取所有路径中成本最小的路径即可。

参考代码

  • Python
import heapq

def bfs(grid, start, end, n, m):
    dx = [-1, 0, 1, 0]
    dy = [0, 1, 0, -1]
    pq = [(0, start[0], start[1])]
    dist = [[float('inf')] * m for _ in range(n)]
    dist[start[0]][start[1]] = 0
    
    while pq:
        d, x, y = heapq.heappop(pq)
        if (x, y) == end:
            return d
        if d > dist[x][y]:
            continue
        for i in range(4):
            nx, ny = x + dx[i], y + dy[i]
            if 0 <= nx < n and 0 <= ny < m and grid[nx][ny] != 'B':
                cost = 0 if grid[nx][ny] in 'SEC' else int(grid[nx][ny])
                if dist[nx][ny] > dist[x][y] + cost:
                    dist[nx][ny] = dist[x][y] + cost
                    heapq.heappush(pq, (dist[nx][ny], nx, ny))
    return float('inf')

def main():
    n, m = map(int, input().split())
    grid = [input().split() for _ in range(n)]
    start, end, checkpoints = None, None, []
    
    for i in range(n):
        for j in range(m):
            if grid[i][j] == 'S':
                start = (i, j)
            elif grid[i][j] == 'E':
                end = (i, j)
            elif grid[i][j] == 'C':
                checkpoints.append((i, j))
    
    min_cost = float('inf')
    for checkpoint in checkpoints:
        cost = bfs(grid, start, checkpoint, n, m) + bfs(grid, checkpoint, end, n, m)
        min_cost = min(min_cost, cost)
    
    print(min_cost if min_cost != float('inf') else -1)

if __name__ == "__main__":
    main()
  • Java
import java.util.*;

public class Main {
    static int[] dx = {-1, 0, 1, 0};
    static int[] dy = {0, 1, 0, -1};

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int m = sc.nextInt();
        sc.nextLine();
        String[][] grid = new String[n][m];
        int[] start = new int[2];
        int[] end = new int[2];
        List<int[]> checkpoints = new ArrayList<>();

        for (int i = 0; i < n; i++) {
            grid[i] = sc.nextLine().split(" ");
            for (int j = 0; j < m; j++) {
                if (grid[i][j].equals("S")) {
                    start[0] = i;
                    start[1] = j;
                } else if (grid[i][j].equals("E")) {
                    end[0] = i;
                    end[1] = j;
                } else if (grid[i][j].equals("C")) {
                    checkpoints.add(new int[]{i, j});
                }
            }
        }

        int minCost = Integer.MAX_VALUE;
        for (int[] checkpoint : checkpoints) {
            int cost = bfs(grid, start, checkpoint, n, m) + bfs(grid, checkpoint, end, n, m);
            minCost = Math.min(minCost, cost);
        }

        System.out.println(minCost == Integer.MAX_VALUE ? -1 : minCost);
    }

    private static int bfs(String[][] grid, int[] start, int[] end, int n, int m) {
        PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));
        pq.add(new int[]{0, start[0], start[1]});
        int[][] dist = new int[n][m];
        for (int[] row : dist) Arrays.fill(row, Integer.MAX_VALUE);
        dist[start[0]][start[1]] = 0;

        while (!pq.isEmpty()) {
            int[] curr = pq.poll();
            int d = curr[0], x = curr[1], y = curr[2];
            if (x == end[0] && y == end[1]) return d;
            if (d > dist[x][y]) continue;

            for (int i = 0; i < 4; i++) {
                int nx = x + dx[i], ny = y + dy[i];
                if (nx >= 0 && nx < n && ny >= 0 && ny < m && !grid[nx][ny].equals("B")) {
                    int cost = grid[nx][ny].matches("\\d") ? Integer.parseInt(grid[nx][ny]) : 0;
                    if (dist[nx][ny] > dist[x][y] + cost) {
                        dist[nx][ny] = dist[x][y] + cost;
                        pq.add(new int[]{dist[nx][ny], nx, ny});
                    }
                }
            }
        }
        return Integer.MAX_VALUE;
    }
}
  • Cpp
#include <iostream>
#include <vector>
#include <queue>
#include <array>
#include <string>
#include <limits>

using namespace std;

int dx[] = {-1, 0, 1, 0};
int dy[] = {0, 1, 0, -1};

int bfs(const vector<vector<string>>& grid, pair<int, int> start, pair<int, int> end, int n, int m) {
    priority_queue<array<int, 3>, vector<array<int, 3>>, greater<array<int, 3>>> pq;
    pq.push({0, start.first, start.second});
    vector<vector<int>> dist(n, vector<int>(m, numeric_limits<int>::max()));
    dist[start.first][start.second] = 0;

    while (!pq.empty()) {
        auto [d, x, y] = pq.top();
        pq.pop();
        if (make_pair(x, y) == end) return d;
        if (d > dist[x][y]) continue;

        for (int i = 0; i < 4; ++i) {
            int nx = x + dx[i], ny = y + dy[i];
            if (nx >= 0 && nx < n && ny >= 0 && ny < m && grid[nx][ny] != "B") {
                int cost = (grid[nx][ny] != "S" && grid[nx][ny] != "E" && grid[nx][ny] != "C") ? stoi(grid[nx][ny]) : 0;
                if (dist[nx][ny] > dist[x][y] + cost) {
                    dist[nx][ny] = dist[x][y] + cost;
                    pq.push({dist[nx][ny], nx, ny});
                }
            }
        }
    }
    return numeric_limits<int>::max();
}

int main() {
    int n, m;
    cin >> n >> m;
    vector<vector<string>> grid(n, vector<string>(m));
    pair<int, int> start, end;
    vector<pair<int, int>> checkpoints;

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            cin >> grid[i][j];
            if (grid[i][j] == "S") start = {i, j};
            else if (grid[i][j] == "E") end = {i, j};
            else if (grid[i][j] == "C") checkpoints.push_back({i, j});
        }
    }

    int minCost = numeric_limits<int>::max();
    for (const auto& checkpoint : checkpoints) {
        int cost = bfs(grid, start, checkpoint, n, m) + bfs(grid, checkpoint, end, n, m);
        minCost = min(minCost, cost);
    }

    cout << (minCost == numeric_limits<int>::max() ? -1 : minCost) << endl;
    return 0;
}

📎 03.最优索引选择

题目描述

K小姐是一名数据库管理员,最近她接到了一个新的任务。公司的数据库系统有 N N N 个表,每个表都可以建立索引以提高查询效率,但建立索引也会占用一定的存储空间。通过对业务查询的分析,K小姐得到了每个表建立索引的查询效率提升值和存储空间开销。

为了方便管理,K小姐将所有的索引分成了 M M M 组,并且这些索引组之间存在一定的依赖关系和互斥关系:

  1. 依赖关系:如果要选择一个索引组中的索引,必须先选择它的父索引组中的至少一个索引。
  2. 互斥关系:每条从根节点到叶子节点的路径都代表一个互斥关系,即不能同时选择两个不同路径上的索引。
  3. 组内限制:对于每个索引组,必须至少选择其中的一个索引。

K小姐希望在总存储空间开销不超过 B B B 的情况下,选择一些索引使得总的查询效率提升值最大。你能帮助K小姐完成这个任务吗?

输入格式

第一行包含三个正整数 B B B, N N N, M M M,分别表示总存储空间开销上限、表的数量和索引组的数量。

接下来 N N N 行,每行包含三个正整数 G i G_i Gi, V i V_i Vi, C i C_i Ci,分别表示第 i i i 个表的索引所属的组号、查询效率提升值和存储空间开销。

最后一行包含 M M M 个整数,第 i i i 个整数 F i F_i Fi 表示第 i i i 个索引组的父索引组编号。如果 F i = − 1 F_i=-1 Fi=1,则表示第 i i i 个索引组没有父索引组,即它是根索引组。

输出格式

输出一个整数,表示在满足总存储空间开销上限的情况下,可以获得的最大查询效率提升值。

样例输入

40 4 2
0 10 10
1 30 10
0 5 20
1 60 40
-1 0

样例输出

45

数据范围

  • 1 ≤ B ≤ 5000 1 \le B \le 5000 1B5000
  • 1 ≤ N ≤ 10000 1 \le N \le 10000 1N10000
  • 1 ≤ M ≤ 100 1 \le M \le 100 1M100
  • 0 ≤ G i < M 0 \le G_i < M 0Gi<M
  • 1 ≤ V i , C i ≤ 100 1 \le V_i,C_i \le 100 1Vi,Ci100

题解

本题可以使用树形DP来解决。设 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示以第 i i i 个索引组为根,总存储空间开销不超过 j j j 的情况下,可以获得的最大查询效率提升值。

对于每个索引组,我们首先需要在组内至少选择一个索引。我们可以使用01背包的方法,计算出在组内选择任意个索引的最优解,存储在数组 f [ j ] f[j] f[j] 中。

然后,我们再考虑当前索引组的子索引组。对于每个子索引组,我们可以枚举当前索引组选择的存储空间开销 j ′ j' j,然后将子索引组的最优解 d p [ s o n ] [ j − j ′ ] dp[son][j-j'] dp[son][jj] 加到 f [ j ′ ] f[j'] f[j] 上。这样,我们就可以得到以当前索引组为根,考虑了子索引组的最优解。

最后,根索引组的 d p [ r o o t ] [ B ] dp[root][B] dp[root][B] 就是整个问题的最优解。

时间复杂度 O ( B × N ) O(B \times N) O(B×N),空间复杂度 O ( B × M ) O(B \times M) O(B×M)

参考代码

  • Python
B, N, M = map(int, input().split())
indexes = [[] for _ in range(M)]
for _ in range(N):
    g, v, c = map(int, input().split())
    indexes[g].append((v, c))

father = list(map(int, input().split()))
graph = [[] for _ in range(M)]
root = 0
for i in range(M):
    if father[i] == -1:
        root = i
    else:
        graph[father[i]].append(i)

dp = [[0] * (B + 1) for _ in range(M)]

def dfs(u, limit):
    f = [0] * (limit + 1)
    for v, c in indexes[u]:
        for j in range(limit, c - 1, -1):
            f[j] = max(f[j], f[j - c] + v)
    
    dp[u][limit] = f[limit]
    for son in graph[u]:
        cur = 0
        for j in range(limit):
            dfs(son, limit - j)
            if f[j] != 0:
                cur = max(cur, f[j] + dp[son][limit - j])
        dp[u][limit] = max(dp[u][limit], cur)

dfs(root, B)
print(dp[root][B])
  • Java
import java.io.*;
import java.util.*;

public class Main {
    int B, N, M;
    int[][] indexes;
    int[] father;
    List<Integer>[] graph;
    int[][] dp;

    public static void main(String[] args) throws IOException {
        new Main().run();
    }

    void run() throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] ss = br.readLine().split(" ");
        B = Integer.parseInt(ss[0]);
        N = Integer.parseInt(ss[1]);
        M = Integer.parseInt(ss[2]);

        indexes = new int[M][];
        for (int i = 0; i < M; i++) {
            indexes[i] = new int[0];
        }
        for (int i = 0; i < N; i++) {
            ss = br.readLine().split(" ");
            int g = Integer.parseInt(ss[0]);
            int v = Integer.parseInt(ss[1]);
            int c = Integer.parseInt(ss[2]);
            indexes[g] = Arrays.copyOf(indexes[g], indexes[g].length + 2);
            indexes[g][indexes[g].length - 2] = v;
            indexes[g][indexes[g].length - 1] = c;
        }

        father = new int[M];
        ss = br.readLine().split(" ");
        for (int i = 0; i < M; i++) {
            father[i] = Integer.parseInt(ss[i]);
        }

        graph = new List[M];
        for (int i = 0; i < M; i++) {
            graph[i] = new ArrayList<>();
        }
        int root = 0;
        for (int i = 0; i < M; i++) {
            if (father[i] == -1) {
                root = i;
            } else {
                graph[father[i]].add(i);
            }
        }

        dp = new int[M][B + 1];
        dfs(root, B);
        System.out.println(dp[root][B]);
    }

    void dfs(int u, int limit) {
        int[] f = new int[limit + 1];
        for (int i = 0; i < indexes[u].length; i += 2) {
            int v = indexes[u][i];
            int c = indexes[u][i + 1];
            for (int j = limit; j >= c; j--) {
                f[j] = Math.max(f[j], f[j - c] + v);
            }
        }

        dp[u][limit] = f[limit];
        for (int son : graph[u]) {
            int cur = 0;
            for (int j = 0; j < limit; j++) {
                dfs(son, limit - j);
                if (f[j] != 0) {
                    cur = Math.max(cur, f[j] + dp[son][limit - j]);
                }
            }
            dp[u][limit] = Math.max(dp[u][limit], cur);
        }
    }
}
  • Cpp
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

const int MAXB = 5000;
const int MAXM = 100;

int B, N, M;
vector<pair<int, int>> indexes[MAXM];
vector<int> graph[MAXM];
int father[MAXM];
int dp[MAXM][MAXB + 1];

void dfs(int u, int limit) {
    vector<int> f(limit + 1);
    for (auto& p : indexes[u]) {
        int v = p.first, c = p.second;
        for (int j = limit; j >= c; j--) {
            f[j] = max(f[j], f[j - c] + v);
        }
    }

    dp[u][limit] = f[limit];
    for (int son : graph[u]) {
        int cur = 0;
        for (int j = 0; j < limit; j++) {
            dfs(son, limit - j);
            if (f[j] != 0) {
                cur = max(cur, f[j] + dp[son][limit - j]);
            }
        }
        dp[u][limit] = max(dp[u][limit], cur);
    }
}

int main() {
    cin >> B >> N >> M;
    for (int i = 0; i < N; i++) {
        int g, v, c;
        cin >> g >> v >> c;
        indexes[g].emplace_back(v, c);
    }

    int root = 0;
    for (int i = 0; i < M; i++) {
        cin >> father[i];
        if (father[i] == -1) {
            root = i;
        } else {
            graph[father[i]].push_back(i);
        }
    }

    dfs(root, B);
    cout << dp[root][B] << endl;

    return 0;
}

写在最后

📧 清隆这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注后私信一下 清隆领取,会在飞书进行同步的跟新。

在这里插入图片描述
在这里插入图片描述

  • 12
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为华为

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值