要求:翻转一个链表的指定区间,比如链表1->2->3->4->5,翻转第二个元素到第四个元素之后的新链表为:1->4->3->2->5
思路:首先找到要翻转的第一个元素的前一个元素,比如现在我要翻转的区间是[2,4],那我首先要找到节点1。然后节点2置为翻转区间的头结点(在整个翻转过程中整个元素是不变的)。
这里以翻转2、3节点为例子:
首先将节点1的next指针指向节点3,然后将节点2的next指针指向节点4,最后再将节点3的next指针指向节点2。
下图是翻转第二个节点到第四个节点组成的区间的示意图:
代码实现:
public class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
}
}
public class Main {
public static void main(String[] args) {
Main main = new Main();
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
ListNode node5 = new ListNode(5);
node1.next = node2;
node2.next = node3;
node3.next = node4;
node4.next = node5;
ListNode tem = node1;
System.out.print("交换之前:");
while (tem != null) {
System.out.print(tem.val + " ");
tem = tem.next;
}
System.out.println();
main.reverseBetween(node1, 2, 4);
tem = node1;
System.out.print("交换之后:");
while (tem != null) {
System.out.print(tem.val + " ");
tem = tem.next;
}
}
public ListNode reverseBetween(ListNode head, int m, int n) {
if (head == null || m >= n) {
return head;
}
ListNode sentinel = new ListNode(-1);
sentinel.next = head;
ListNode node = sentinel;
// move the "node" pointer in front of the m-th node
for (int i = 1; i < m; ++i) {
node = node.next;
}
// reverse nodes
ListNode originalSubHead = node.next;
for (int i = m; i < n; ++i) {
ListNode preNode = node.next;
node.next = originalSubHead.next;
originalSubHead.next = originalSubHead.next.next;
node.next.next = preNode;
}
return sentinel.next;
}
}