LeetCode24.两两交换链表中的节点
遇到的一些问题:
代码变量的名称,要尽量避开原有的属性,否则很容易搞混淆。
空指针异常,经常出现在取next节点时,一定要记得保证当前节点不为空
class Solution { public ListNode swapPairs(ListNode head) { ListNode dummy = new ListNode(-1 , head); ListNode pre = dummy; ListNode firstNode = pre.next; while(firstNode != null && firstNode.next != null){ //循环条件这里,喜欢把secNode也作为条件,但是会出现空指针异常,如果想避免,可能要加很多个判断保证firstNode不为空,才能使用secNode,但是直接用firstNode.next就可以避免了。 ListNode secNode = firstNode.next; pre.next = secNode; firstNode.next = secNode.next; secNode.next = firstNode; pre = firstNode; firstNode = pre.next; if(firstNode != null){ secNode = pre.next.next; } } return dummy.next; } }
LeetCode19.删除链表的倒数第 N 个结点
遇到的问题:
一开始想的是让slow.next去指向fast,这显然不对,只是在我刚开始的例子中,n恰好等于2,slow和fast的相对位置恰好就是slow.next.next,但是n是别的情况就不是了。 换句话说,重点不是fast和slow的相对位置,fast只是起到一个帮助遍历的作用,重点是slow本身,它指向了要删除的节点的前一个节点,接下来就是很简单的删除逻辑,与fast无关
class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { int size = 0; ListNode dummy = new ListNode(-1 , head); ListNode fast = dummy; ListNode slow = dummy; //为了统一删除操作,快慢指针都从一个虚拟头节点出发 for(int i = 0 ; i < n ; i++){ fast = fast.next; } while(fast.next != null){ fast = fast.next; slow = slow.next; } slow.next = slow.next.next; return dummy.next; } }
LeetCode面试题 02.07. 链表相交
public class Solution { public ListNode getIntersectionNode(ListNode headA, ListNode headB) { /** 找到的是相交的节点,不是相等的值 遇到的问题: 1. 两条链表长度不一定一样,遍历肯定不能直接放在一个循环同时遍历 2. 如何去确定要找到的节点 思路: 1. 相交的节点有什么特点吗? 看了《随想录》得出的思路 答:后续链表的长度相等 2. 所以求出两个链表的长度差,运用快慢指针的思想,让快指针先遍历长链表,遍历长度为链表长度差。 3. 再去比较两个链表剩余部分的首个节点,是否存在相同节点 */ if(headA == null || headB == null){ return null; } ListNode preA = new ListNode(-1,headA); ListNode preB = new ListNode(-1,headB); int sizeA = 0; int sizeB = 0; while(preA.next != null){ sizeA++; preA = preA.next; } while(preB.next != null){ sizeB++; preB = preB.next; } int n; if(sizeA > sizeB){ n = sizeA - sizeB; for(int i = 0 ; i < n ; i++){ headA = headA.next; } }else if(sizeA < sizeB){ n = sizeB - sizeA; for(int i = 0 ; i < n ; i++){ headB = headB.next; } } while(headA != null){ /** 注意这里的终止条件,用头节点本身, 用headA.next的话就判断不了头节点就是相交节点的情况 */ if (headA == headB){ return headA; } headA = headA.next; headB = headB.next; } return null; } }
LeetCode142.环形链表II
public class Solution { 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 = head; ListNode index2 = fast; while(index1 != index2){ index1 = index1.next; index2 = index2.next; } return index1; } } return null; /** 随想录太牛了点,讲解的很清晰,思路也很巧妙 思路如下: 先是利用快慢指针确定是否存在环,快指针走两步,慢指针走一步。这样快指针永远只比慢指针快一个节点,换句话说,就是每一次向下走就以一个节点的速度追上慢节点,所以如果存在环的话,慢节点一定能跟快节点相遇。 然后就是求环的起始节点,这个思路更是牛波一。取头结点到环的起始节点的长度为x,起始节点到快慢指针的相遇节点为y,相遇节点到起始节点为z。根据快慢指针的定义,得出公式,化简,当n=1时,x=z,说明相遇节点到起始节点的长度=头结点到起始节点的长度。而当n>1时,无非就是快指针多走了几圈才遇到头结点出发的指针。 */ } }