难度:中等
频次:116
题目:给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
解题思路: 反转链表+遍历
注意:
- 简单的链表反转实现 【头插法,其实也有很多其他种方法,但是这种出错率低,可以用的地方也多】
- 虚拟头节点 但逢需要考虑左右边界节点,用上虚拟节点准没错
- 其实就是g p两个固定节点,然后一个移动节点temp
- g的作用就是用来连接反转过来的节点,p的节点只有一个作用,就是指向下一个需要反转的节点
- 这种头插法,最后的部分也是连在一起的
/**
* 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 dummyhead=new ListNode(-1);
dummyhead.next=head;
ListNode p=head,g=dummyhead;
if(head==null) return head;
while(p.next!=null){//这里选用p.next很大的一个原因就是p指向下一个要反转的节点的
ListNode temp=p.next;
p.next=temp.next;
temp.next=g.next;
g.next=temp;
}
return dummyhead.next;
}
}
- 两个数字之间数字的个数: x到y一共多个数字=y-x+1,比如1-100一共有=100-1+1个数字
- 先移动g和p到我们需要反转的地方
代码
/**
* 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 dummyhead=new ListNode(-1);
dummyhead.next=head;
ListNode g=dummyhead,p=head;
for(int i=0;i<left-1;i++){ //p点(其实位置是1)的移动次数 从left-1+1-1
g=g.next;
p=p.next;
}
for(int j=0;j<right-left+1-1;j++){
ListNode temp=p.next;
p.next=temp.next;
temp.next=g.next;
g.next=temp;
//p。g都是不动的,只有其他的节点动
}
return dummyhead.next;
}
}