【华为OD机考 统一考试机试】单向链表中间节点(C++ Java JavaScript Python )

40 阅读5分钟

华为OD机考:统一考试 C卷 + D卷 + B卷 + A卷

2023年11月份,华为官方已经将 华为OD机考:OD统一考试(A卷 / B卷)切换到 OD统一考试(C卷)和 OD统一考试(D卷) 。根据考友反馈:目前抽到的试卷为B卷或C卷/D卷,其中C卷居多 ,按照之前的经验C卷部分考题会复用A卷,B卷题,博主正积极从考过的同学收集C卷和D卷真题。 可以先继续刷B卷, C卷和D卷的题目会放在现在大家购买的专栏内,不需要重新购买,请大家放心。

专栏:2023华为OD机试( A卷+B卷+C卷+D卷)(C++JavaJSPy)

华为OD面试真题精选:华为OD面试真题精选

在线OJ:点击立即刷题,模拟真实机考环境\ 华为OD机考B卷C卷华为OD机考华为OD机考B卷华为OD机试B卷华为OD机试C卷华为OD机考C卷华为OD机考D卷题目华为OD机考C卷/D卷答案华为OD机考C卷/D卷解析华为OD机考C卷和D卷真题华为OD机考C卷和D卷题解

题目描述

求单向链表中间的节点值,如果奇数个节点取中间,偶数个取偏右边的那个值。

输入描述

第一行 链表头节点地址 后续输入的节点数n

后续输入每行表示一个节点,格式 节点地址 节点值 下一个节点地址(-1表示空指针)

输入保证链表不会出现环,并且可能存在一些节点不属于链表。

输出描述

单向链表中间的节点值

用例

输入00010 4
00000 3 -1
00010 5 12309
11451 6 00000
12309 7 11451
输出6
说明
输入10000 3
76892 7 12309
12309 5 -1
10000 1 76892
输出7
说明

题目解析

可以参考下面的题解:

876. 链表的中间结点 - 力扣(LeetCode)

代码思路

题目要求求解单向链表中间的节点值,如果奇数个节点取中间,偶数个取偏右边的那个值。首先需要读入链表的头节点地址和节点数n,然后循环读入n个节点的信息,存入一个unordered_map中,其中key为节点地址,value为一个pair,存储节点的值和下一个节点的地址。接下来需要用快慢指针的方法找到链表的中间节点。初始化时,慢指针的值和下一个节点的地址为头节点的值和下一个节点的地址,快指针的下一个节点的地址为慢指针下一个节点的下一个节点的地址。然后进行循环,当快指针的下一个节点的地址不为空时,慢指针移动到下一个节点,快指针移动两个节点。当快指针到达链表的末尾时,慢指针所指向的节点即为链表的中间节点。最后输出慢指针所指向的节点的值即可。

C++

#include <iostream>
#include <unordered_map>
using namespace std;

int main() {
  string headAddress;
  int n;
  cin >> headAddress >> n;

  unordered_map<string, pair<string, string>> nodeMap;
  // 循环读入n个节点的信息,存入nodeMap中
  for (int i = 0; i < n; i++) {
    string address, value, nextAddress;
    cin >> address >> value >> nextAddress;
    nodeMap[address] = {value, nextAddress};
  }

  // 初始化慢指针的值和下一个节点的地址
  string slowNodeValue = nodeMap[headAddress].first;
  string slowNodeNextAddress = nodeMap[headAddress].second;
  // 初始化快指针的下一个节点的地址
  string fastNodeNextAddress = nodeMap[slowNodeNextAddress].second;

  // 当快指针的下一个节点的地址不为空时,进行循环
  while (fastNodeNextAddress != "") {
    // 慢指针移动到下一个节点
    slowNodeValue = nodeMap[slowNodeNextAddress].first;
    slowNodeNextAddress = nodeMap[slowNodeNextAddress].second;
    // 快指针移动两个节点
    fastNodeNextAddress = nodeMap[nodeMap[fastNodeNextAddress].second].second;
  }

  // 输出慢指针所指向的节点的值
  cout << slowNodeValue << endl;
  // 返回0表示程序正常结束
  return 0;
}

JavaScript

const readline = require("readline");

// 创建readline接口实例
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

// 存储输入的每一行数据
const lines = [];

// 链表头节点地址
let headAddr;

// 节点数
let nodeCount;

// 监听line事件,逐行读取输入的数据
rl.on("line", (line) => {
  // 将读取到的数据存入数组
  lines.push(line);

  // 如果是第一行数据,获取链表头节点地址和节点数
  if (lines.length === 1) {
    [headAddr, nodeCount] = lines[0].split(" ");
  }

  // 如果已经读取了节点数n行数据(链表中的节点数据),则进行处理
  if (nodeCount && lines.length === parseInt(nodeCount) + 1) {
    // 将第一行(节点数n)从数组中删除
    lines.shift();

    // 存储节点数据的对象
    const nodes = {};

    // 遍历每一个节点数据,将其存储到nodes对象中
    lines.forEach((line) => {
      const [addr, val, nextAddr] = line.split(" ");
      nodes[addr] = [val, nextAddr];
    });

    // 慢指针
    let slowPtr = nodes[headAddr];
    // 快指针
    let fastPtr = nodes[slowPtr[1]];

    // 当快指针存在时,快指针每次移动两步,慢指针每次移动一步
    while (fastPtr) {
      slowPtr = nodes[slowPtr[1]];
      fastPtr = nodes[fastPtr[1]];
      if (fastPtr) {
        fastPtr = nodes[fastPtr[1]];
      } else {
        break;
      }
    }

    // 输出慢指针指向的节点值
    console.log(slowPtr[0]);
  }
});

Java

import java.util.HashMap;
import java.util.Scanner;

public class Main {
  public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);

    // 输入链表头节点地址和节点数
    String headAddress = sc.next();
    int n = sc.nextInt();

    // 创建 HashMap 存储每个节点的值和下一个节点的地址
    HashMap<String, String[]> nodeMap = new HashMap<>();
    for (int i = 0; i < n; i++) {
      String address = sc.next();
      String value = sc.next();
      String nextAddress = sc.next();
      nodeMap.put(address, new String[] {value, nextAddress});
    }

    // 定义慢指针和快指针,初始值均为头节点
    String[] slowNode = nodeMap.get(headAddress);
    String[] fastNode = nodeMap.get(slowNode[1]);

    // 快指针每次走两步,慢指针每次走一步,直到快指针到达链表末尾
    while (fastNode != null) {
      slowNode = nodeMap.get(slowNode[1]);
      fastNode = nodeMap.get(fastNode[1]);
      if (fastNode != null) {
        fastNode = nodeMap.get(fastNode[1]);
      } else {
        break;
      }
    }

    // 输出慢指针指向的节点的值
    System.out.println(slowNode[0]);
  }
}

Python

head_addr, n = input().split()

# 创建一个空字典nodes来存储所有节点的信息
nodes = {}

# 循环读取每个节点的地址、值和下一个节点的地址,并将其存储在nodes字典中
for i in range(int(n)):
    node_addr, node_val, next_addr = input().split()
    nodes[node_addr] = [node_val, next_addr]

# 使用快慢指针寻找链表的中间节点
slow = nodes.get(head_addr)  # 慢指针指向链表的头节点
fast = nodes.get(slow[1])   # 快指针指向链表的第二个节点

while fast is not None:
    slow = nodes.get(slow[1])  # 慢指针向后移动一步
    fast = nodes.get(nodes.get(fast[1])[1] if nodes.get(fast[1]) is not None else None)  # 快指针向后移动两步

# 输出链表的中间节点的值
print(slow[0])

@[TOC]

doutub_gif