//给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 //迭代法 public ListNode swapPairs1(ListNode head) { ListNode dummyHead=new ListNode(0,head); ListNode cur=head,prev=dummyHead; while(cur!=null&&cur.next!=null){ prev.next=cur.next; ListNode store=cur.next; cur.next=store.next; store.next=cur; prev=cur; cur=cur.next; } return dummyHead.next; } //递归 public ListNode swapPairs2(ListNode head) { if(head==null||head.next==null) return head; ListNode temp=head.next; ListNode node=swapPairs1(temp.next); temp.next=head; head.next=node; return temp; } 递归先找结束条件与返回的东西,再补充每次递归时调用的步骤 //给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。 //暴力无脑法 public ListNode removeNthFromEnd1(ListNode head, int n) { ListNode dummyHead=new ListNode(0,head); if (head==null||head.next==null) return null; ListNode cur=dummyHead; int num=0; for(ListNode p=head;p!=null;p=p.next){ num++; } for(int i=0;i<(num-n);i++){ cur=cur.next; } cur.next=cur.next.next; return dummyHead.next; } //双指针使得中间距离等于n+1,当快指针到达尾部,慢指针就在要删除节点的前一个节点上 public ListNode removeNthFromEnd2(ListNode head, int n) { ListNode dummyHead=new ListNode(0,head); if (head==null||head.next==null) return null; ListNode fastNode=dummyHead,slowNode=dummyHead; for(int i=0;i<n+1;i++){ fastNode=fastNode.next; } while(fastNode!=null) {//快指针移出尾部时相距n+1个距离 // 慢指针就在倒数第几个数的前一个节点 fastNode=fastNode.next; slowNode=slowNode.next; } slowNode.next=slowNode.next.next; return dummyHead.next; }
//给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。 //情况一:两个链表相交 //链表 headA 和 headB 的长度分别是 m 和 n。假设链表 headA 的不相交部分有 a 个节点,链表 headB 的不相交部分有 b 个节点,两个链表相交的部分有 c 个节点,则有 a+c=m,b+c=n。 //如果 a=b,则两个指针会同时到达两个链表相交的节点,此时返回相交的节点; //如果 a=b,则指针 pA 会遍历完链表 headA,指针 pB 会遍历完链表 headB,两个指针不会同时到达链表的尾节点,然后指针 pA 移到链表 headB 的头节点, // 指针 pB 移到链表 headA 的头节点,然后两个指针继续移动,在指针 pA 移动了 a+c+b 次、指针 pB 移动了 b+c+a 次之后,两个指针会同时到达两个链表相交的节点,该节点也是两个指针第一次同时指向的节点,此时返回相交的节点。 //情况二:两个链表不相交 //链表 headA 和 headB 的长度分别是 m 和 n。考虑当 m=n 和 m=n 时,两个指针分别会如何移动: //如果 m=n,则两个指针会同时到达两个链表的尾节点,然后同时变成空值 null,此时返回 null; //如果 m=n,则由于两个链表没有公共节点,两个指针也不会同时到达两个链表的尾节点,因此两个指针都会遍历完两个链表,在指针 pA 移动了 m+n 次、指针 pB 移动了 n+m 次之后,两个指针会同时变成空值 null,此时返回 null。 public ListNode getIntersectionNode1(ListNode headA, ListNode headB) { if (headA == null || headB == null) { return null; } ListNode pA = headA, pB = headB; while (pA != pB) { pA = pA == null ? headB : pA.next; pB = pB == null ? headA : pB.next; } return pA; } //方法2:对齐长度,如果相交,两者尾部肯定有部分相同, //算出较短的链表长度和另一个链表从尾部对齐,相同的指针位置即为交点 public ListNode getIntersectionNode2(ListNode headA, ListNode headB) { int lenA=0,lenB=0; for(ListNode pA=headA;pA!=null;pA=pA.next){ lenA++; } for(ListNode pB=headB;pB!=null;pB=pB.next){ lenB++; } ListNode pA=headA,pB=headB; if(lenB>lenA){ int temp=lenA; lenA=lenB; lenB=temp; pA=headB; pB=headA; } for(int i=0;i<lenA-lenB;i++) pA= pA.next; while (pA!=null){ if (pA==pB) return pA; pA= pA.next; pB=pB.next; } return null; }
//给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 //如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环, // 评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1, // 则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。 public ListNode detectCycle(ListNode head) { ListNode fast=head; ListNode slow=head; while(fast!=null&&fast.next!=null){ fast= fast.next.next; slow=slow.next; if (fast==slow){ ListNode index1=fast; ListNode index2=head; while(index1!=index2){ index2=index2.next; index1=index1.next; } return index2; } } return null; }