1. 反转链表1
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
限制:
0 <= 节点个数 <= 5000
(1) 双指针
1.创建一个指针temp,保存下一个链表节点地址
2.依次反转即可
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null;
while(head != null){
ListNode temp = head.next; //一定要放在循环里面,记录每一个head的下一个节点
head.next = pre; //反转一个节点
pre = head; //pre后移一位
head = temp; //head后移一位
}
return pre; //head为空时,pre串联了所有反转链表
}
}
(2) 递归
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
return rescur(head, null);
}
public ListNode rescur(ListNode cur, ListNode pre){
if(cur == null)
return pre;
ListNode res = rescur(cur.next, cur);
cur.next =pre;
return res;
}
}
2. 反转链表2
(1)朴素解法
建立一个虚拟头结点 dummy,使其指向 head,最终返回 dummy.next。
黄色部分的节点代表需要「翻转」的部分:
之后就是常规的模拟:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseBetween(ListNode head, int left, int right) {
ListNode dummy = new ListNode(0);
dummy.next = head;
right = right - left; //存储left -> right之间的节点个数
ListNode node = dummy;
//找到left所对应的节点的前一个位置node:因为node初始为head的前一个节点,且节点从1开始计数,所以>1
while (left > 1){
node = node.next;
left--;
}
//反转left -> right之间的节点
ListNode a = node.next, b = a.next;
while (right > 0) {
ListNode tmp = b.next;
b.next = a;
a = b;
b = tmp;
right--;
}
//连接反转节点的前后
node.next.next = b;
node.next = a;
return dummy.next;
}
}