news 2026/5/8 15:38:34

用100道题拿下你的算法面试(链表篇-6):给链表表示的数字加 1

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用100道题拿下你的算法面试(链表篇-6):给链表表示的数字加 1

一、面试问题

一个数字以链表形式存储,每位数字对应链表中的一个节点。任务是给这个数字加 1。

示例 1:

输入:链表头节点:4 -> 5 -> 6

输出:链表头节点:4 -> 5 -> 7

解释:对链表所表示的数字加 1,即 456 + 1 = 457。

示例 2:

输入:头节点链表:2 -> 1 -> 6 -> 9

输出:头节点链表:2 -> 1 -> 7 -> 0

解释:将链表表示的数字加 1,即 2169 + 1 = 2170。

二、【解法-1】递归法 —— 时间复杂度 O (n),空间复杂度 O (n)

(一) 解法思路

递归遍历链表,先走到最后一个节点。

这样可以优先处理最低位数字。给最后一个节点的值加 1,并计算本次加法产生的进位。

回溯过程中,根据后一个节点传递过来的进位,依次更新每个节点的值。

遍历结束后,若进位不为 0,则新建一个以进位值为数据的节点,插入到链表头部。

(二) 使用 6 种语言实现

1. C++

// C++ 程序:使用递归法给链表表示的数字加 1 #include <iostream> using namespace std; // 链表节点类 class Node { public: int data; Node *next; // 构造函数:创建新节点 Node(int x) { data = x; next = nullptr; } }; // 递归函数:从链表尾部向头部依次加1,并返回进位 int addWithCarry(Node *head) { // 递归终止条件:链表为空,返回进位 1(因为我们要 +1) if (head == nullptr) { return 1; } // 递归调用下一个节点,接收返回的进位,并与当前节点值相加 int res = head->data + addWithCarry(head->next); // 更新当前节点的值(取个位) head->data = res % 10; // 返回新的进位(取十位) return res / 10; } // 主函数:给链表数字加 1 Node *addOne(Node *head) { // 调用递归函数,处理所有节点并获取最终进位 int carry = addWithCarry(head); // 如果最终还有进位(如 999 -> 1000),新建节点插入到头部 if (carry) { Node *newNode = new Node(carry); newNode->next = head; // 新节点成为新的头节点 return newNode; } return head; } // 打印链表 void printList(Node *head) { Node *curr = head; while (curr != nullptr) { cout << curr->data << " "; curr = curr->next; } cout << endl; } // 主函数测试 int main() { // 创建链表: 1 -> 9 -> 9 -> 9 (表示数字 1999) Node *head = new Node(1); head->next = new Node(9); head->next->next = new Node(9); head->next->next->next = new Node(9); // 给链表数字 +1 head = addOne(head); // 打印结果:2 0 0 0 printList(head); return 0; }

2. C

// C 程序:给链表表示的数字加 1 #include <stdio.h> #include <stdlib.h> struct Node { int data; struct Node* next; }; struct Node* createNode(int data); // 递归地从尾部向头部加 1,并处理完所有节点后返回进位 int addWithCarry(struct Node* head) { // 如果链表为空,返回进位 1 if (head == NULL) { return 1; } // 加上下一个节点调用返回的进位 int res = head->data + addWithCarry(head->next); // 更新数据并返回新的进位 head->data = res % 10; return res / 10; } struct Node* addOne(struct Node* head) { // 从尾部向头部给链表加 1 int carry = addWithCarry(head); // 如果更新所有节点后仍有进位,则需要向链表添加一个新节点 if (carry) { struct Node* newNode = createNode(carry); newNode->next = head; // 新节点成为新的头节点 return newNode; } return head; } void printList(struct Node* head) { struct Node* curr = head; while (curr != NULL) { printf("%d ", curr->data); curr = curr->next; } printf("\n"); } struct Node* createNode(int data) { struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); newNode->data = data; newNode->next = NULL; return newNode; } int main() { // 创建一个硬编码的链表: // 1 -> 9 -> 9 -> 9 struct Node* head = createNode(1); head->next = createNode(9); head->next->next = createNode(9); head->next->next->next = createNode(9); head = addOne(head); printList(head); return 0; }

3. Java

// Java 程序:给链表表示的数字加 1 class Node { int data; Node next; Node(int data) { this.data = data; this.next = null; } } // 递归地从尾部向头部加 1,并处理完所有节点后返回进位 class DSA { static int addWithCarry(Node head) { // 如果链表为空,返回进位 1 if (head == null) { return 1; } // 加上下一个节点调用返回的进位 int res = head.data + addWithCarry(head.next); // 更新数据并返回新的进位 head.data = res % 10; return res / 10; } static Node addOne(Node head) { // 从尾部向头部给链表加 1 int carry = addWithCarry(head); // 如果更新所有节点后仍有进位,则需要向链表添加一个新节点 if (carry > 0) { Node newNode = new Node(carry); newNode.next = head; // 新节点成为新的头节点 return newNode; } return head; } static void printList(Node head) { Node curr = head; while (curr != null) { System.out.print(curr.data + " "); curr = curr.next; } System.out.println(); } public static void main(String[] args) { // 创建一个硬编码的链表: // 1 -> 9 -> 9 -> 9 Node head = new Node(1); head.next = new Node(9); head.next.next = new Node(9); head.next.next.next = new Node(9); head = addOne(head); printList(head); } }

4. Python

# Python 程序:给链表表示的数字加 1 class Node: def __init__(self, data): self.data = data self.next = None # 递归地从尾部向头部加 1,并处理完所有节点后返回进位 def addWithCarry(head): # 如果链表为空,返回进位 1 if head is None: return 1 # 加上下一个节点调用返回的进位 res = head.data + addWithCarry(head.next) # 更新数据并返回新的进位 head.data = res % 10 return res // 10 def addOne(head): # 从尾部向头部给链表加 1 carry = addWithCarry(head) # 如果更新所有节点后仍有进位,则需要向链表添加一个新节点 if carry: newNode = Node(carry) newNode.next = head # 新节点成为新的头节点 return newNode return head def printList(head): curr = head while curr: print(curr.data, end=" ") curr = curr.next print() if __name__ == "__main__": # 创建一个硬编码的链表: # 1 -> 9 -> 9 -> 9 head = Node(1) head.next = Node(9) head.next.next = Node(9) head.next.next.next = Node(9) head = addOne(head) printList(head)

5. C#

// C# 程序:给链表表示的数字加 1 using System; class Node { public int data; public Node next; public Node(int data) { this.data = data; this.next = null; } } class DSA { // 递归地从尾部向头部加 1,并处理完所有节点后返回进位 static int addWithCarry(Node head) { // 如果链表为空,返回进位 1 if (head == null) { return 1; } // 加上下一个节点调用返回的进位 int res = head.data + addWithCarry(head.next); // 更新数据并返回新的进位 head.data = res % 10; return res / 10; } static Node addOne(Node head) { // 从尾部向头部给链表加 1 int carry = addWithCarry(head); // 如果更新所有节点后仍有进位,则需要向链表添加一个新节点 if (carry > 0) { Node newNode = new Node(carry); newNode.next = head; // 新节点成为新的头节点 return newNode; } return head; } static void printList(Node head) { Node curr = head; while (curr != null) { Console.Write(curr.data + " "); curr = curr.next; } Console.WriteLine(); } static void Main() { // 创建一个硬编码的链表: // 1 -> 9 -> 9 -> 9 Node head = new Node(1); head.next = new Node(9); head.next.next = new Node(9); head.next.next.next = new Node(9); head = addOne(head); printList(head); } }

6. JavaScript

// Javascript 程序:给链表表示的数字加 1 class Node { constructor(data) { this.data = data; this.next = null; } } // 递归地从尾部向头部加 1,并处理完所有节点后返回进位 function addWithCarry(head) { // 如果链表为空,返回进位 1 if (head === null) { return 1; } // 加上下一个节点调用返回的进位 const res = head.data + addWithCarry(head.next); // 更新数据并返回新的进位 head.data = res % 10; return Math.floor(res / 10); } function addOne(head) { // 从尾部向头部给链表加 1 const carry = addWithCarry(head); // 如果更新所有节点后仍有进位,则需要向链表添加一个新节点 if (carry > 0) { const newNode = new Node(carry); newNode.next = head; // 新节点成为新的头节点 return newNode; } return head; } function printList(head) { let curr = head; while (curr !== null) { console.log(curr.data + " "); curr = curr.next; } console.log(); } // 创建一个硬编码的链表: // 1 -> 9 -> 9 -> 9 let head = new Node(1); head.next = new Node(9); head.next.next = new Node(9); head.next.next.next = new Node(9); head = addOne(head); printList(head);

(三)代码输出和算法复杂度

输出:

2 0 0 0

时间复杂度:O(n)。

空间复杂度:O(n)。

三、【解法-2】迭代法 —— 时间复杂度 O (n),空间复杂度 O (1)

(一) 解法思路

  1. 反转给定的链表。例如,1->9->9->9 反转为 9->9->9->1。
  2. 从最左侧的节点开始遍历链表,并给它加 1。如果存在进位,则移动到下一个节点。只要有进位,就继续移动到下一个节点。这一步得到 0->0->0->2。
  3. 遍历结束后,如果进位不等于 0,则创建一个以进位值为数据的新节点,并将其插入到头部。在本例中,进位为 0。
  4. 反转修改后的链表并返回头节点。最终得到 2->0->0->0。

(二) 使用 6 种语言实现

1. C++

// C++ 程序:给链表表示的数字加 1 #include <bits/stdc++.h> using namespace std; class Node { public: int data; Node *next; Node(int x) { data = x; next = nullptr; } }; // 反转链表的函数 Node* reverse(Node* head) { Node *curr = head, *prev = nullptr, *next; while (curr != nullptr) { next = curr->next; curr->next = prev; prev = curr; curr = next; } return prev; } // 给链表加 1 并返回结果链表头节点的函数 Node *addOneUtil(Node *head) { Node *res = head; Node *curr = head; Node *last = nullptr; // 初始化进位为 1(用于加 1) int carry = 1; int sum; while (curr != nullptr) { // 计算进位与当前节点数据的和 sum = carry + curr->data; // 更新下一位的进位 carry = (sum >= 10) ? 1 : 0; // 将当前节点数据更新为和对 10 取模 curr->data = sum % 10; // 移动到下一个节点 last = curr; curr = curr->next; } // 如果仍有剩余进位,添加一个携带进位值的新节点 if (carry > 0) { last->next = new Node(carry); } return res; } // 给链表加 1 的主函数 Node *addOne(Node *head) { // 反转链表 head = reverse(head); // 给反转后的链表加 1 head = addOneUtil(head); // 再次反转链表,恢复原始顺序 return reverse(head); } void printList(Node *head) { Node *curr = head; while (curr != nullptr) { cout << curr->data << " "; curr = curr->next; } cout << endl; } int main() { // 创建一个硬编码的链表: // 1 -> 9 -> 9 -> 9 Node *head = new Node(1); head->next = new Node(9); head->next->next = new Node(9); head->next->next->next = new Node(9); head = addOne(head); printList(head); return 0; }

2. C

// C 程序:给链表表示的数字加 1 #include <stdio.h> #include <stdlib.h> struct Node { int data; struct Node* next; }; struct Node* createNode(int data); // 反转链表的函数 struct Node* reverse(struct Node* head) { struct Node* curr = head; struct Node* prev = NULL; struct Node* next; while (curr != NULL) { next = curr->next; curr->next = prev; prev = curr; curr = next; } return prev; } // 给链表加 1 并返回结果链表头节点的函数 struct Node* addOneUtil(struct Node* head) { struct Node* res = head; struct Node* curr = head; struct Node* last = NULL; // 初始化进位为 1(用于加 1) int carry = 1; int sum; while (curr != NULL) { // 计算进位与当前节点数据的和 sum = carry + curr->data; // 更新下一位的进位 carry = (sum >= 10) ? 1 : 0; // 将当前节点数据更新为和对 10 取模 curr->data = sum % 10; // 移动到下一个节点 last = curr; curr = curr->next; } // 如果仍有剩余进位,添加一个携带进位值的新节点 if (carry > 0) { last->next = createNode(carry); } return res; } // 给链表加 1 的主函数 struct Node* addOne(struct Node* head) { // 反转链表 head = reverse(head); // 给反转后的链表加 1 head = addOneUtil(head); // 再次反转链表,恢复原始顺序 return reverse(head); } void printList(struct Node* head) { struct Node* curr = head; while (curr != NULL) { printf("%d ", curr->data); curr = curr->next; } printf("\n"); } struct Node* createNode(int data) { struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); newNode->data = data; newNode->next = NULL; return newNode; } int main() { // 创建一个硬编码的链表: // 1 -> 9 -> 9 -> 9 struct Node* head = createNode(1); head->next = createNode(9); head->next->next = createNode(9); head->next->next->next = createNode(9); head = addOne(head); printList(head); return 0; }

3. Java

// Java 程序:给链表表示的数字加 1 class Node { int data; Node next; Node(int x) { this.data = x; this.next = null; } } // 反转链表的函数 class DSA { static Node reverse(Node head) { Node curr = head, prev = null, next; while (curr != null) { next = curr.next; curr.next = prev; prev = curr; curr = next; } return prev; } // 给链表加 1 并返回结果链表头节点的函数 static Node addOneUtil(Node head) { Node res = head; Node curr = head; Node last = null; // 初始化进位为 1(用于加 1) int carry = 1; int sum; while (curr != null) { // 计算进位与当前节点数据的和 sum = carry + curr.data; // 更新下一位的进位 carry = (sum >= 10) ? 1 : 0; // 将当前节点数据更新为和对 10 取模 curr.data = sum % 10; // 移动到下一个节点 last = curr; curr = curr.next; } // 如果仍有剩余进位,添加一个携带进位值的新节点 if (carry > 0) { last.next = new Node(carry); } return res; } // 给链表加 1 的主函数 static Node addOne(Node head) { // 反转链表 head = reverse(head); // 给反转后的链表加 1 head = addOneUtil(head); // 再次反转链表,恢复原始顺序 return reverse(head); } static void printList(Node head) { Node curr = head; while (curr != null) { System.out.print(curr.data + " "); curr = curr.next; } System.out.println(); } public static void main(String[] args) { // 创建一个硬编码的链表: // 1 -> 9 -> 9 -> 9 Node head = new Node(1); head.next = new Node(9); head.next.next = new Node(9); head.next.next.next = new Node(9); head = addOne(head); printList(head); } }

4. Python

# Python3 程序:给链表表示的数字加 1 class Node: def __init__(self, data): self.data = data self.next = None # 反转链表的函数 def reverse(head): curr = head prev = None while curr: next = curr.next curr.next = prev prev = curr curr = next return prev # 给链表加 1 并返回结果链表头节点的函数 def addOneUtil(head): res = head curr = head last = None # 初始化进位为 1(用于加 1) carry = 1 while curr: # 计算进位与当前节点数据的和 sum = carry + curr.data # 更新下一位的进位 carry = 1 if sum >= 10 else 0 # 将当前节点数据更新为和对 10 取模 curr.data = sum % 10 # 移动到下一个节点 last = curr curr = curr.next # 如果仍有剩余进位,添加一个携带进位值的新节点 if carry > 0: last.next = Node(carry) return res # 给链表加 1 的主函数 def addOne(head): # 反转链表 head = reverse(head) # 给反转后的链表加 1 head = addOneUtil(head) # 再次反转链表,恢复原始顺序 return reverse(head) def printList(head): curr = head while curr: print(curr.data, end=" ") curr = curr.next print() if __name__ == '__main__': # 创建一个硬编码的链表: # 1 -> 9 -> 9 -> 9 head = Node(1) head.next = Node(9) head.next.next = Node(9) head.next.next.next = Node(9) head = addOne(head) printList(head)

5. C#

// C# 程序:给链表表示的数字加 1 using System; class Node { public int data; public Node next; public Node(int x) { this.data = x; this.next = null; } } class DSA { // 反转链表的函数 static Node Reverse(Node head) { Node curr = head, prev = null, next = null; while (curr != null) { next = curr.next; curr.next = prev; prev = curr; curr = next; } return prev; } // 给链表加 1 并返回结果链表头节点的函数 static Node AddOneUtil(Node head) { Node res = head; Node curr = head; Node last = null; // 初始化进位为 1(用于加 1) int carry = 1; int sum; while (curr != null) { // 计算进位与当前节点数据的和 sum = carry + curr.data; // 更新下一位的进位 carry = (sum >= 10) ? 1 : 0; // 将当前节点数据更新为和对 10 取模 curr.data = sum % 10; // 移动到下一个节点 last = curr; curr = curr.next; } // 如果仍有剩余进位,添加一个携带进位值的新节点 if (carry > 0) { last.next = new Node(carry); } return res; } // 给链表加 1 的主函数 static Node AddOne(Node head) { // 反转链表 head = Reverse(head); // 给反转后的链表加 1 head = AddOneUtil(head); // 再次反转链表,恢复原始顺序 return Reverse(head); } static void PrintList(Node head) { Node curr = head; while (curr != null) { Console.Write(curr.data + " "); curr = curr.next; } Console.WriteLine(); } static void Main() { // 创建一个硬编码的链表: // 1 -> 9 -> 9 -> 9 Node head = new Node(1); head.next = new Node(9); head.next.next = new Node(9); head.next.next.next = new Node(9); head = AddOne(head); PrintList(head); } }

6. JavaScript

// Javascript 程序:给链表表示的数字加 1 class Node { constructor(data) { this.data = data; this.next = null; } } // 反转链表的函数 function reverse(head) { let curr = head, prev = null, next; while (curr != null) { next = curr.next; curr.next = prev; prev = curr; curr = next; } return prev; } // 给链表加 1 并返回结果链表头节点的函数 function addOneUtil(head) { let res = head; let curr = head; let last = null; // 初始化进位为 1(用于加 1) let carry = 1; let sum; while (curr != null) { // 计算进位与当前节点数据的和 sum = carry + curr.data; // 更新下一位的进位 carry = (sum >= 10) ? 1 : 0; // 将当前节点数据更新为和对 10 取模 curr.data = sum % 10; // 移动到下一个节点 last = curr; curr = curr.next; } // 如果仍有剩余进位,添加一个携带进位值的新节点 if (carry > 0) { last.next = new Node(carry); } return res; } // 给链表加 1 的主函数 function addOne(head) { // 反转链表 head = reverse(head); // 给反转后的链表加 1 head = addOneUtil(head); // 再次反转链表,恢复原始顺序 return reverse(head); } function printList(head) { let curr = head; while (curr != null) { console.log(curr.data + " "); curr = curr.next; } console.log(); } // 创建一个硬编码的链表: // 1 -> 9 -> 9 -> 9 let head = new Node(1); head.next = new Node(9); head.next.next = new Node(9); head.next.next.next = new Node(9); head = addOne(head); printList(head);

(三)代码输出和算法复杂度

输出:

2 0 0 0

时间复杂度:O(n)。

空间复杂度:O(1)。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/8 15:38:33

2026年性价比之王:HOWO卡车出口平台全解析

在当前全球化的背景下&#xff0c;物流行业的发展日益迅速&#xff0c;对运输工具的需求也越来越大。作为中国重型卡车行业的领军企业之一&#xff0c;济南海诺尔贸易有限公司凭借其卓越的产品质量和完善的售后服务&#xff0c;在国际市场上赢得了广泛的认可。本文将从多个角度…

作者头像 李华
网站建设 2026/5/8 15:33:45

ChatGPT代码分析插件:TypeScript项目智能解析与AI集成实战

1. 项目概述&#xff1a;一个为ChatGPT打造的TypeScript代码分析插件 如果你和我一样&#xff0c;日常开发重度依赖TypeScript&#xff0c;并且对ChatGPT这类AI助手在代码理解上的潜力感到兴奋&#xff0c;那么 kesor/chatgpt-code-plugin 这个项目绝对值得你花时间研究。简单…

作者头像 李华