#P3051. 寻找链表的中间结点(100分)
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 143
            Accepted: 46
            Difficulty: 2
            
          
          
          
                       所属公司 : 
                              华为od
                                
            
                      
          
 
- 
                        算法标签>链表          
 
寻找链表的中间结点(100分)
题目描述
给定一个单链表 L ,请编写程序输出 L 中间结点保存的数据。
- 如果链表有一个中间结点,输出该结点数据;
 - 如果链表有两个中间结点,输出第二个中间结点的数据。
 
输入格式:
每个输入包含一个测试用例。
- 第一行给出链表首结点的地址和结点总个数 N ( N <= 10^5 )。
 - 接下来有 N 行,每行包含三个内容:结点地址、结点数据、下一结点地址。
 
解题思路
- 构建链表:首先将所有结点的信息(地址、数据、下一结点地址)存储在一个字典 
nodes中,地址作为键,值为一个包含数据和下一结点地址的元组。 - 遍历链表:从给定的头结点地址开始遍历链表,同时计数。由于链表中的结点数已知,所以中间结点的位置可以通过总长度计算得出。如果总结点数为奇数,直接定位到中间位置;如果为偶数,定位到第二个中间结点的位置。
 - 输出结果:在遍历到目标位置后,输出该结点的数据。
 
复杂度分析
- 时间复杂度: O(N) 。遍历链表时访问所有结点。
 - 空间复杂度: O(N) 。存储所有结点的地址信息。
 
代码实现
C++
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
    string head;
    cin >> head;
    int n;
    cin >> n;
    map<string, pair<int, string>> nodes;
    for (int i = 0; i < n; i++) {
        string addr;
        cin >> addr;
        int val;
        cin >> val;
        string nextAddr;
        cin >> nextAddr;
        nodes[addr] = {val, nextAddr};
    }
    string now = head;
    int id = 1;
    while (now != "-1") {
        if (id == (n / 2 + 1)) {
            cout << nodes[now].first << endl;
            break;
        }
        now = nodes[now].second;
        id++;
    }
    return 0;
}
Java
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String head = sc.next();
        int n = sc.nextInt();
        
        Map<String, Node> nodes = new HashMap<>();
        for (int i = 0; i < n; i++) {
            String addr = sc.next();
            int val = sc.nextInt();
            String nextAddr = sc.next();
            nodes.put(addr, new Node(val, nextAddr));
        }
        
        String now = head;
        int id = 1;
        while (!now.equals("-1")) {
            if (id == (n / 2 + 1)) {
                System.out.println(nodes.get(now).data);
                break;
            }
            now = nodes.get(now).next;
            id++;
        }
        
        sc.close();
    }
}
class Node {
    int data;
    String next;
    Node(int data, String next) {
        this.data = data;
        this.next = next;
    }
}
Python
def find_middle_node(head, nodes_info, n):
    nodes = {}
    for addr, val, next_addr in nodes_info:
        nodes[addr] = (val, next_addr)
    
    now = head
    id = 1
    while now != "-1":
        if id == (n // 2 + 1):
            print(nodes[now][0])
            break
        now = nodes[now][1]
        id += 1
# 读取输入
head = input().strip()
n = int(input().strip())
nodes_info = [input().strip().split() for _ in range(n)]
nodes_info = [(addr, int(val), next_addr) for addr, val, next_addr in nodes_info]
find_middle_node(head, nodes_info, n)
        题目描述
给定一个单链表 L ,请编写程序输出 L 中间结点保存的数据。
如果有两个中间结点,则输出第二个中间结点保存的数据。例如:
给定 L 为 1→7→5,则输出应该为 7 ;
给定 L 为 1→2→3→4,则输出应该为 3 ;
输入描述
每个输入包含 1 个测试用例。
每个测试用例:
第一行给出链表首结点的地址、结点总个数正整数 N(≤105)。
结点的地址是 5 位非负整数,NULL 地址用 −1 表示。
接下来有 N 行,每行格式为:
AddressDataNext
其中 Address 是结点地址,Data 是该结点保存的整数数据(0≤Data≤108),Next 是下一结点的地址。
输出描述
对每个测试用例,在一行中输出 L 中间结点保存的数据。
如果有两个中间结点,则输出第二个中间结点保存的数据。
备注
已确保输入的结点所构成的链表 L 不会成环,但会存在部分输入结点不属于链表 L 情况 。
样例1
输入
00010 4
00000 3 -1
00010 5 12309
11451 6 00000
12309 7 11451
输出
6
样例2
输入
10000 3
76892 7 12309
12309 5 -1
10000 1 76892
输出
7