反转链表
解题思路分析:考虑创建一个新的链表,每次在假头的下一个节点处添加数据,这个假头就是起到辅助添加真头的作用。==特别注意添加的第一节点的下一个节点一定要使他的下一个节点为空null,这是一个单向链表的基本要求。==还要注意需要一个辅助变量来存放原始链表指针的下一个节点,否则出现无法真正的更新原来链表指针的移动。
/**
* 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) {
if(head==null||head.next==null){
return head;
}
ListNode pre=null;
ListNode temp=head;
while(temp!=null){
ListNode nex=temp.next;
//更新链表的新头
temp.next=pre;
pre=temp;
temp=nex;//更新链表的指针
}
return pre;
}
}
K个一组翻转链表
本组节点个数的判断+本组链表的反转+加本组链表拼接回原始的链表
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode hair = new ListNode(0);
hair.next = head;//永远指向链表的头部的一个假头
ListNode pre = hair;//本组链表的头结点的前一个节点
while (head != null) {
//本组链表尾部获取的指针
ListNode tail = pre;
// 查看剩余部分长度是否大于等于 k(若小于就直接剩余部分不需要反转了)
for (int i = 0; i < k; ++i) {
tail = tail.next;
if (tail == null) {
return hair.next;
}
}
//存储下一组链表的头部,为了拼接链表链表
ListNode nex = tail.next;
//对当前链表小组进行翻转(根据尾部和头)
ListNode[] reverse = myReverse(head, tail);
head = reverse[0];
tail = reverse[1];
// 把子链表重新接回原链表
pre.next = head;//前一组的尾结点指向本组的头结点
tail.next = nex;//本组的尾结点指向下一组的头结点
//更新新的下一组链表的前一个节点pre(即本组节点的尾结点),以及下一组链表的头部
pre = tail;
head = tail.next;
}
return hair.next;
}
//进行部分链表的反转操作
public ListNode[] myReverse(ListNode head, ListNode tail) {
//临时的假头节点
ListNode prev = new ListNode(0);
//待翻转链表的指针所在位置
ListNode p = head;
//每次将获取的节点放在新的链表的头部
while (prev != tail) {//终止的条件是这个新链表的头等于原链表的尾部节点
ListNode nex = p.next;
p.next = prev;//将当前节点指向新链表的头部
prev = p;//更新新链表的头部
p = nex;
}
return new ListNode[]{tail, head};
}
}