网站首页 > 精选教程 正文
反转链表是算法中的一个经典问题,它要求我们改变链表中节点的指向,使得原本指向后一个节点的指针现在指向前一个节点。下面,我会详细解释如何使用双指针和递归的方法来解决这个问题,并提供相应的Java代码。
双指针解法
思路:
- 使用两个指针,一个prev指向前一个节点,初始为null;一个curr指向当前节点,初始为头节点。
- 遍历链表,每次迭代做如下操作:
- 将curr的next指向prev。
- 将prev和curr都向前移动一步。
- 当curr为null时,遍历结束,此时prev就是新的头节点。
Java代码:
public class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while (curr != null) {
ListNode nextTemp = curr.next; // 保存下一个节点
curr.next = prev; // 反转当前节点的指向
prev = curr; // prev前进一步
curr = nextTemp; // curr前进一步
}
return prev; // prev现在是新的头节点
}
时间复杂度:O(n),其中n是链表的长度,需要遍历整个链表一次。
空间复杂度:O(1),只使用了常数级别的额外空间。
递归解法
思路:
- 使用两个参数——curr 和 newHead——允许我们在递归过程中同时处理这两个方面。curr 表示当前处理的节点,而 newHead 表示反转后的新头节点。
- 递归的起始点是链表的头节点,此时新头节点是 null,因为反转前没有头节点。在递归的每一步中,我们执行以下操作:
- 保存下一个节点:在改变当前节点 curr 的指向之前,我们先保存它的下一个节点 nextNode。这是因为一旦我们改变了 curr 的指向,我们就失去了对原始链表中下一个节点的引用。
- 反转当前节点的指向:我们将 curr 的 next 指针指向 newHead。这样,我们就实现了当前节点的反转。
- 递归调用:然后,我们递归调用 reverseListRecursive 方法,传入 nextNode 作为新的当前节点,并将 curr 作为新的头节点传入。这是因为,在递归的下一步中,curr 将成为新链表中的前一个节点。
- 返回新头节点:递归调用的结果(即新的头节点)会被返回,并继续向上传递到上一层递归调用中。这样,每一层递归都能知道反转后的新头节点是什么,并在适当的时候更新它。
Java代码:
public class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
public ListNode reverseList(ListNode head) {
return reverseListRecursive(head, null);
}
private ListNode reverseListRecursive(ListNode curr, ListNode newHead) {
if (curr == null) {
return newHead; // 递归终止条件:当前节点为空,返回新头节点
}
ListNode nextNode = curr.next; // 保存下一个节点
curr.next = newHead; // 反转当前节点的指向
// 递归调用,处理下一个节点,并更新新头节点
return reverseListRecursive(nextNode, curr);
}
时间复杂度:O(n),其中n是链表的长度,递归需要遍历整个链表一次。
空间复杂度:O(n),递归调用栈的深度取决于链表的长度,最坏情况下需要n层递归调用栈。
总结
反转链表是一个基础的链表操作,可以使用双指针和递归两种方法实现。双指针方法空间复杂度低,但需要手动维护两个指针;递归方法代码简洁,但空间复杂度较高。在实际应用中,可以根据具体需求和场景选择合适的方法。
注:个人觉得解决链表问题的时候,画图可以清晰展示每个节点的指向,帮助解决问题。
猜你喜欢
- 2024-11-02 LeetCode-025-K 个一组翻转链表 每k个一组翻转链表
- 2024-11-02 C++算法(五)反转链表 反转链表c#
- 2024-11-02 61. 旋转链表 反转链表 头插法
- 2024-11-02 字节面试算法集第三题链表反转 #算法
- 2024-11-02 Java数据结构和算法—链表 java中的链表数据结构
- 2024-11-02 面试现场:如何实现链表的逆序? 链表逆置是什么意思
- 2024-11-02 LeetCode-206-反转链表 反转链表 迭代
- 2024-11-02 迭代法 链表翻转 #软件开发 迭代法程序
- 2024-11-02 每日算法---单链表反转和是否有环
- 2024-11-02 C++:挑战鹅厂面试题(一)--反转链表
你 发表评论:
欢迎- 04-11Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- 04-11Java中你知道几种从字符串中找指定的字符的数量
- 04-11探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- 04-11Python字符串详解与示例(python字符串的常见操作)
- 04-11java正则-取出指定字符串之间的内容
- 04-11String s1 = new String("abc");这句话创建了几个字符串对象?
- 04-11java判断字符串中是否包含某个字符
- 04-11关于java开发中正确的发牌逻辑编写规范
- 最近发表
-
- Java面试“字符串三兄弟”String、StringBuilder、StringBuffer
- Java中你知道几种从字符串中找指定的字符的数量
- 探秘Java面试中问的最多的String、StringBuffer、StringBuilder
- Python字符串详解与示例(python字符串的常见操作)
- java正则-取出指定字符串之间的内容
- String s1 = new String("abc");这句话创建了几个字符串对象?
- java判断字符串中是否包含某个字符
- 关于java开发中正确的发牌逻辑编写规范
- windows、linux如何后台运行jar(并且显示进程名)
- 腾讯大佬私人收藏,GitHub上最受欢迎的100个JAVA库,值得学习
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)