R / Richie全部文章 ↑

Python · 2 分钟阅读

Python:将链表转换为字符串

目录


把单链表 val -> val -> val -> ... 序列化为字符串是常见操作,比如把一道
LeetCode 链表题的结果打印或比较。本章讨论不同方向、不同需求下的写法。

链表约定:头节点 = 数字的最低位(与 02.两数相加 题目一致)。


1. 节点定义

from __future__ import annotations
from typing import Optional, Iterable


class ListNode:
    def __init__(self, val: int = 0, next: Optional["ListNode"] = None) -> None:
        self.val = val
        self.next = next

2. 拼接出字符串

2.1 头是低位 → 数字字符串

def list_to_number_str(head: Optional[ListNode]) -> str:
    """7 -> 0 -> 8  →  '807'"""
    parts: list[str] = []
    while head:
        parts.append(str(head.val))
        head = head.next
    return "".join(reversed(parts))

要点:

  • 把每个 val 转字符串、放入列表;
  • reversed 后 join —— 一次性分配好结果串,比反复 s = str(x) + s
    快很多
    。
  • 空链表返回 ""。

2.2 头是高位 → 顺序字符串

def list_to_str(head: Optional[ListNode]) -> str:
    """'a' -> 'b' -> 'c'  →  'abc'"""
    return "".join(str(node.val) for node in iter_list(head))


def iter_list(head: Optional[ListNode]) -> Iterable[ListNode]:
    while head:
        yield head
        head = head.next

3. 完整可运行示例

def build(values: Iterable[int]) -> Optional[ListNode]:
    dummy = ListNode(0)
    cur = dummy
    for v in values:
        cur.next = ListNode(v)
        cur = cur.next
    return dummy.next


if __name__ == "__main__":
    # 例 1:头是低位(7 -> 0 -> 8 → 807)
    n = build([7, 0, 8])
    assert list_to_number_str(n) == "807"

    # 例 2:头是高位
    n = build([1, 2, 3])
    assert list_to_str(n) == "123"

    # 例 3:空链表
    assert list_to_number_str(None) == ""
    assert list_to_str(None) == ""

    # 例 4:负数 / 多位 val
    n = ListNode(12, ListNode(34))   # 12 -> 34
    assert list_to_str(n) == "1234"
    print("ok")

如果链表的 val 是两位以上数字,先决定 拼接规则 是“直接连接”(12, 34 →
"1234")还是“按数值格式化”(12, 34 → "12 34")。本文例子使用前者。


4. 性能 / 复杂度

实现 时间 空间(除输入外)
s = str(x) + s(头低位) O(n²) O(n)
list + reversed + join O(n) O(n)
list + 直接 join(头高位) O(n) O(n)

Python 的 str 是不可变的,反复 s = str(x) + s 会 每次创建新字符串,
长度 n 的链表累计 O(n²) 操作。join 一次到位。


5. 工具函数:转回链表 / 转列表

def list_to_pylist(head: Optional[ListNode]) -> list[int]:
    """转成 Python 列表(从头到尾的顺序)。"""
    out: list[int] = []
    while head:
        out.append(head.val)
        head = head.next
    return out


def str_to_list(s: str) -> Optional[ListNode]:
    """把字符串每个字符转成 ListNode(头是高位)。"""
    if not s:
        return None
    head = ListNode(int(s[0]))
    cur = head
    for ch in s[1:]:
        cur.next = ListNode(int(ch))
        cur = cur.next
    return head

6. 与反序列化的对比:复杂度提示

链表 ↔ 字符串互转都是 O(n),因为要遍历每个节点。但如果加上“验证这是合法数字”
(例如不能有前导零),单次遍历就够,不必再走一遍。

def is_valid_number_str(head: Optional[ListNode]) -> bool:
    s = list_to_number_str(head)
    if not s:
        return False
    return s.lstrip("0") == s or s == "0"

7. 常见错误

  • 空指针没处理:第一个节点就为 None 时函数必须能直接返回。
  • 混淆高低位:一定要明确“头是高位还是低位”,否则结果整段颠倒。
  • 数字位数 ≠ 字符位数:上面 val=12 的例子要特别留意,要么规定 val
    是 0~9,要么明确格式化规则。
  • 拼接性能:见第 4 节。str(x) + s 写法在 n 大时会显著变慢。