题目描述1
笔者分析1.1
我的常规想法是新建两个逆序链表,从后往前比较,但我发现我理解错题目意思了。这个题并不是问两个链表值相等的后缀,它是真的相交与同一链表,所以原来想法不仅复杂了,而且也解决不了问题。看到评论区的大佬解法,链表用的这么秀也是太大佬了。平时我们遍历链表都喜欢用while(node.next),而且一遍遍历解决问题,但如果一遍遍历解决不了问题的话就开始慌了。这题的解法巧妙之处在于while(pA!=pB)这样可以遍历两次链表,而且确实需要两次遍历链表,通过交叉遍历来达到同步的目的是真的六,学废了,学废了。
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
/**
定义两个指针, 第一轮让两个到达末尾的节点指向另一个链表的头部, 最后如果相遇则为交点(在第一轮移动中恰好抹除了长度差)
两个指针等于移动了相同的距离, 有交点就返回, 无交点就是各走了两条指针的长度
**/
if(headA == null || headB == null) return null;
ListNode pA = headA, pB = headB;
// 在这里第一轮体现在pA和pB第一次到达尾部会移向另一链表的表头, 而第二轮体现在如果pA或pB相交就返回交点, 不相交最后就是null==null
while(pA != pB) {
pA = pA == null ? headB : pA.next;
pB = pB == null ? headA : pB.next;
}
return pA;
}
}
题目描述2
笔者解答2.1
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode dummyHead=new ListNode(0);
ListNode cur=dummyHead;
while(l1!=null&&l2!=null){
if(l1.val<l2.val){
cur.next=l1;
cur=cur.next;
l1=l1.next;
}else{
cur.next=l2;
cur=cur.next;
l2=l2.next;
}
}
if(l1==null){
cur.next=l2;
}else{
cur.next=l1;
}
return dummyHead.next;
}
}
笔者分析2.2
记录这题并不是因为这题有多难,这题很简单,但有个注意点。自己新创建链表时可先创建一个哨兵结点,方便之后的连接,返回链表时,返回哨兵结点的下一个结点。
题目描述3
笔者解答3.1
class Solution {
public boolean isPalindrome(ListNode head) {
ListNode slow=head;
ListNode fast=head;
ListNode last=null;
while(fast!=null){
slow=slow.next;
fast=fast.next==null?fast.next:fast.next.next;
}
while(slow!=null){
ListNode temp=slow.next;
slow.next=last;
last=slow;
slow=temp;
}
while(head!=null&&last!=null){
if(head.val!=last.val){
return false;
}
head=head.next;
last=last.next;
}
return true;
}
}
笔者分析3.2
原来想过要是能将链表逆序就好了,可看了题目要求说要O(1)空间复杂度,最后想可以不用新建链表,只需要将原来链表修改指针方向就行。逆序的核心代码如下:
while(slow!=null){
ListNode temp=slow.next;
slow.next=last;
last=slow;
slow=temp;
}
总结
核心:交互相交链表,换指针逆序链表每日打卡二十三天,以下图为证