「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」。
反转链表
题目描述
给你单链表的头结点head,请你反转链表,并返回反转后的链表。
示例1:
输入:head=[1,2,3,4,5]
输出:[5,4,3,2,1]
示例2:
输入:[1,2]
输出:[2,1]
示例3:
输入:head=[]
输出:[]
解析
其实这就是一个将链表中各元素逆置的问题,我们只需要将结点的指针指向反转就可以解决这个问题 。首先我们定义一个指向头结点的cur指针,再定义一个pre指针指向cur前一个位置,初始化我们设置为null,我们只要讲cur.next指向pre就可以反转第一个结点,依次操作各个结点,就可以实现反转链表功能。
代码
public ListNode reverseList(ListNode head) {
//定义一个pre指针,初始化置为null
ListNode pre=null;
//定义cur指针,指向头结点
ListNode cur=head;
//对链表中的各结点依次进行操作
while(cur!=null){
//定义结点temp临时存储cur信息
ListNode temp=cur.next;
//反转结点的指针指向,将结点反转
cur.next=pre;
//pre,cur依次向后移动
pre=cur;
cur=temp;
}
return pre;
}
}
反转链表II
题目描述
给你单链表的头指针head和两个整数left和right,其中left<=right。请你反转从位置left到位置right的链表节点,返回反转后的链表。
输入:head=[1,2,3,4,5],left=2,right=4
输出:[1,4,3,2,5]
示例2:
输入:head=[5],left=1,right=1
输出:[5]
解析
这道题目与上面的题目区别在于在反转链表的基础上设置了条件,必须要在一定的区间内反转链表。核心思想就是保留区间外的链表不变,然后截取条件区间内的链表进行反转操作,然后将截取的链表和区间外的链表再次拼接,即可解决上述问题。详细步骤如下所述:
- 设置虚拟头结点,在这里设置虚拟头结点的目的是方便对原链表中的所有结点包括头结点可以按照统一的方式进行各项处理,而不用单独去处理原来头结点,使得操作更为方便。
ListNode dummyNode=new ListNode(-1);
dummyNode.next=head;
ListNode pre=dummyNode;
2.从虚拟结点到left结点的前一个结点,即[0,left-1)这段链表保持不变
for(int i=0;i<left-1;i++){
pre=pre.next;
}
3.从pre到right-left+1,到right结点
ListNode rightNode=pre;
for(int i=0;i<right-left+1;i++){
rightNode=rightNode.next;
}
- 截取区间内的链表,并切断链接(将pre.next和rightNode.next全置为null)。
ListNode leftNode=pre.next;
ListNode cur=rightNode.next;
pre.next=null;
rightNode.next=null;
- 将区间内的链表进行反转,具体反转操作参照第一题
reverseLinkedList(leftNode);
public void reverseLinkedList(ListNode head){
ListNode pre=null;
ListNode cur=head;
while(cur!=null){
ListNode temp=cur.next;
cur.next=pre;
pre=cur;
cur=temp;
}
- 将反转后的链接拼接到原来的位置,这样就完成了对应位置的反转
pre.next=rightNode;
leftNode.next=cur;
return dummyNode.next;