华为OD机试 - 单向链表中间节点(Python/JS/C/C++ 2024 E卷 100分)

在这里插入图片描述

华为OD机试 2024E卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

给定一个 单链表 L,请编写程序输出 L 中间结点保存的数据。

如果有两个中间结点,则输出其中第二个中间结点保存的数据。

例如:

给定 L 为 1→7→5,则输出应该为 7;
给定 L 为 1→2→3→4,则输出应该为 3。

二、输入描述

每个输入包含 1 个 测试用例。每个测试用例:

第一行给出链表首结点的地址L。结点总个数正整数 N(≤105)。

结点的地址是 5 位非负整数,NULL 地址用 −1 表示。

接下来有 N 行,每行格式为:

Address Data Next

其中 Address 是结点地址,Data 是结点保存的整数数据 (0 ≤ Data ≤ 108),Next 是下一个结点的地址。

三、输出描述

对每个测试用例,在一行中输出 L 中间结点保存的数据。

如果有两个中间结点,则输出其中第二个中间结点保存的数据。

(如果多个节点取中间值相同,偶数个取偏右边的那个)

四、测试用例

测试用例1:

1、输入

00010 4
00000 3 -1
00010 5 12309
11451 6 00000
12309 7 11451

2、输出

6

3、说明

链表为 00010→12309→11451→00000,数据为 5→7→6→3,中间结点为 7 和 6,选择第二个中间结点 6。

测试用例2:

1、输入

10000 3
76892 7 12309
12309 5 -1
10000 1 76892

2、输出

7

3、说明

链表为 10000→76892→12309,数据为 1→7→5,中间结点为 7。

五、解题思路

  1. 输入处理:
    • 首先读取链表的首结点地址和结点总数。
    • 接着读取每个结点的详细信息(地址、数据、下一个结点的地址)。
    • 使用 HashMap 将每个地址映射到其对应的结点数据和下一个结点的地址,以便快速访问。
  2. 链表遍历:
    • 从首结点地址开始,按照 Next 地址依次遍历链表,并将结点的数据存入一个 ArrayList 中。
    • 这样,我们可以得到链表中所有结点的数据按顺序排列。
  3. 寻找中间结点:
    • 根据链表的长度,计算中间结点的位置。
    • 如果链表长度为奇数,则中间结点为 (length / 2)。
    • 如果链表长度为偶数,则中间结点为 (length / 2)(即偏右的那个结点)。
  4. 输出结果:
    • 输出计算得到的中间结点的数据。

六、Python算法源码

# Python 版本
import sys

def main():
    # 读取标准输入的所有行
    lines = sys.stdin.read().splitlines()
    if not lines:
        return

    # 第一行包含首结点地址和结点总数
    head_address, N = lines[0].split()
    N = int(N)

    # 创建一个字典来存储地址到结点数据和下一个地址的映射
    node_map = {}
    for i in range(1, N + 1):
        parts = lines[i].split()
        address = parts[0]
        data = int(parts[1])
        next_addr = parts[2]
        node_map[address] = (data, next_addr)

    # 遍历链表,按照顺序存储结点的数据
    data_list = []
    current = head_address
    while current != "-1":
        if current not in node_map:
            break  # 如果地址不存在,结束遍历
        data, next_addr = node_map[current]
        data_list.append(data)
        current = next_addr

    # 计算中间结点的位置
    if not data_list:
        print()
    else:
        mid = len(data_list) // 2
        print(data_list[mid])

if __name__ == "__main__":
    main()

七、JavaScript算法源码

// JavaScript 版本
const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let inputLines = [];
rl.on('line', function(line) {
    inputLines.push(line);
}).on('close', function() {
    // 第一行包含首结点地址和结点总数
    const firstLine = inputLines[0].split(' ');
    const headAddress = firstLine[0];
    const N = parseInt(firstLine[1]);

    // 创建一个Map来存储地址到结点数据和下一个地址的映射
    const nodeMap = new Map();
    for(let i=1; i<=N; i++) {
        const parts = inputLines[i].split(' ');
        const address = parts[0];
        const data = parseInt(parts[1]);
        const nextAddr = parts[2];
        nodeMap.set(address, {data: data, next: nextAddr});
    }

    // 遍历链表,按照顺序存储结点的数据
    const dataList = [];
    let current = headAddress;
    while(current !== "-1") {
        if(!nodeMap.has(current)) break; // 如果地址不存在,结束遍历
        const node = nodeMap.get(current);
        dataList.push(node.data);
        current = node.next;
    }

    // 计算中间结点的位置
    if(dataList.length === 0){
        console.log('');
    }
    else{
        const mid = Math.floor(dataList.length / 2);
        console.log(dataList[mid]);
    }
});

八、C算法源码

/* C 版本 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 定义结点结构体
typedef struct Node {
    char address[6];    // 5位地址加终止符
    int data;
    char next[6];
} Node;

int main(){
    char head_address[6];
    int N;
    
    // 读取首结点地址和结点总数
    scanf("%s %d", head_address, &N);
    
    // 创建一个数组存储所有结点
    Node nodes[N];
    for(int i=0; i<N; i++){
        scanf("%s %d %s", nodes[i].address, &nodes[i].data, nodes[i].next);
    }
    
    // 遍历链表,按照顺序存储结点的数据
    int *data_list = (int*)malloc(N * sizeof(int));
    int count = 0;
    char current[6];
    strcpy(current, head_address);
    
    while(strcmp(current, "-1") != 0){
        // 在数组中查找当前地址的结点
        int found = 0;
        for(int i=0; i<N; i++){
            if(strcmp(nodes[i].address, current) == 0){
                data_list[count++] = nodes[i].data;
                strcpy(current, nodes[i].next);
                found = 1;
                break;
            }
        }
        if(!found){
            break; // 如果地址不存在,结束遍历
        }
    }
    
    // 计算中间结点的位置并输出
    if(count == 0){
        // 如果链表为空,什么也不输出
    }
    else{
        int mid = count / 2;
        printf("%d\n", data_list[mid]);
    }
    
    // 释放动态分配的内存
    free(data_list);
    
    return 0;
}

九、C++算法源码

// C++ 版本
#include <bits/stdc++.h>
using namespace std;

struct Node {
    string address; // 结点地址
    int data;       // 结点数据
    string next;    // 下一个结点地址
};

int main(){
    string head_address;
    int N;
    
    // 读取首结点地址和结点总数
    cin >> head_address >> N;
    
    // 创建一个unordered_map来存储地址到结点数据和下一个地址的映射
    unordered_map<string, pair<int, string>> node_map;
    for(int i=0; i<N; i++){
        string address, next;
        int data;
        cin >> address >> data >> next;
        node_map[address] = make_pair(data, next);
    }
    
    // 遍历链表,按照顺序存储结点的数据
    vector<int> data_list;
    string current = head_address;
    while(current != "-1"){
        if(node_map.find(current) == node_map.end()) break; // 如果地址不存在,结束遍历
        data_list.push_back(node_map[current].first);
        current = node_map[current].second;
    }
    
    // 计算中间结点的位置并输出
    if(data_list.empty()){
        // 如果链表为空,什么也不输出
    }
    else{
        int mid = data_list.size() / 2;
        cout << data_list[mid] << endl;
    }
    
    return 0;
}


🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值