24. 两两交换链表中的节点
注意*:最开始代码编写均使用普通思路,对于复杂思路后续单独编写。
思路:使用虚拟头节点,更改链表指向即可,但是要注意交换的两个链表必须都不为空,不然会抛出空指针异常。
class Solution {
public ListNode swapPairs(ListNode head) {
ListNode dummynode=new ListNode(0);//虚拟头节点
dummynode.next=head;
ListNode cur=dummynode;//当前便利的节点
while(cur.next!=null&&cur.next.next!=null){//要删除的两个节点必须都不为空
ListNode tail=cur.next.next.next;//保存下一次便利的两个节点中的第一个
//进行交换链表操作
ListNode temp=cur.next;
cur.next=cur.next.next;
cur.next.next=temp;
temp.next=tail;
cur=temp;//链表移动
}
return dummynode.next;
}
}
思路:普通思路,统计链表节点数量,根据索引数量向后遍历即可
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head==null){
return head;
}
//统计链表中节点数量;
int count=0;
ListNode cur=head;
while(cur!=null){
count++;
cur=cur.next;
}
//判断删除节点索引是否合适
if(n>count||n<=0){
return head;
}
ListNode dummynode=new ListNode(0);
dummynode.next=head;
cur=dummynode;
int index=count-n;
while(index>0){
cur=cur.next;
index--;
}
cur.next=cur.next.next;
return dummynode.next;
}
}
思路:假设A链表长度为a。B链表长度为b,
假设有公共部分,长度记为c,从头开始遍历AB节点,若A节点遍历到末尾之后继续从B节点开始遍历,B节点同理,当链表白能力到公共部分开始节点是,刚好走过的节点数量相等,也就是说,此时链表有公共部分且开始的节点就是当前遍历的节点,直接返回
假设没公共部分,那莫AB链表遍历完之后,两个指针遍历的长度相等,且都为null
评价:此题虽为简单题,但是从某种意义上来说绝对超越简单题
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode a=headA,b=headB;
//假如两个链表可以相交
//分析链表A长度a,B长度b,公共部分长度c,
//当ab同时出发开始遍历,若a链表遍历结束,继续遍历b链表,b同理
//ab相交,那么 A遍历到相交的地方时走过的长度为a+b-c
// B走过的长度为b+a-c
//此时长度必然相等,所以链表相交此时a=b=相交的节点
//假如两个链表不相交
//循环就会将ab全部便利完长度为a+b=b+a,最终a=b=null
while(a!=b){
a=a==null?headB:a.next;
b=b==null?headA:b.next;
}
return a;
}
}
思路一:普通思路,基于hashset实现,就是将所有节点遍历存入集合,当存在环时,指针在此遍历集合,集合中中必然包括此节点,直接返回,如果没有环,退出循环之后,指针指向null,直接返回。
思路二:基于双指针实现,有一部没想明白,改日再谈
public class Solution {
public ListNode detectCycle(ListNode head) {
Set<ListNode> container=new HashSet<>();//使用hashset,元素随机不重复,遍历链表
ListNode cur=head;
while (cur!=null){
if(container.contains(cur)){
return cur;
}
container.add(cur);
cur=cur.next;
}
return cur;
}
}
Write The Code, Change The World!!!
三条直线围墙