https://leetcode.cn/circle/discuss/jq9Zke/
迭代法 1 2 3 4 5 6 7 8 9 10 11 12 13 fun removeElements (head: ListNode ?, target: Int ) : ListNode? { val dummyHead = ListNode() dummyHead.next = head var p: ListNode? = dummyHead while (p?.next != null ) { if (p.next?.`val ` == target) { p.next = p.next?.next } else { p = p.next } } return dummyHead.next }
递归法 https://leetcode-cn.com/problems/remove-linked-list-elements/solution/yi-chu-lian-biao-yuan-su-by-leetcode-sol-654m/
some notice
注意这里不是dummyHead.next
// 注意: 之前这个放在上边的if里面
注意这里之前是 index >= size
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 class MyLinkedList () { private val dummyHead = ListNode() var size = 0 fun get (index: Int ) : Int { if (index < -1 || index > size - 1 ) return -1 var pIndex = index var curr = dummyHead.next while (pIndex-- > 0 ) { curr = curr?.next } return curr?.`val ` ?: -1 } fun addAtHead (`val `: Int ) { val newNode = ListNode(`val `) val headNode = dummyHead.next dummyHead.next = newNode if (headNode != null ) { newNode.next = headNode } size++ } fun addAtTail (`val `: Int ) { val newNode = ListNode(`val `) var p: ListNode? = dummyHead while (p != null ) { if (p.next == null ) { p.next = newNode size++ break } p = p.next } } fun addAtIndex (index: Int , `val `: Int ) { if (index > size) return val newNode = ListNode(`val `) var pIndex = index var curr = dummyHead while (pIndex-- > 0 ) { curr = curr.next!! } val temp = curr.next curr.next = newNode newNode.next = temp size++ } fun deleteAtIndex (index: Int ) { if (index >= size || index < 0 ) { return } var pIndex = index var curr: ListNode? = dummyHead while (pIndex-- > 0 ) { curr = curr?.next } if (curr?.next != null ) { curr.next = curr.next?.next } size-- } }
双指针 1 2 3 4 5 6 7 8 9 10 11 12 13 14 fun reverseList (head: ListNode ?) : ListNode? { var pre = head var curr: ListNode? = null while (pre != null ) { val termPre = pre.next pre.next = curr curr = pre if (termPre == null ) { return pre } pre = termPre } return pre }
after watching the https://leetcode.cn/problems/reverse-linked-list/solution/fan-zhuan-lian-biao-shuang-zhi-zhen-di-gui-yao-mo-/
return curr point is better
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 class Solution { fun reverseList (head: ListNode ?) : ListNode? { var pre = head var curr: ListNode? = null while (pre != null ) { val termPre = pre.next pre.next = curr curr = pre pre = termPre } return curr } }
递归写法 迭代法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 fun swapPairs (head: ListNode ?) : ListNode? { val dumpNode = ListNode() dumpNode.next = head var temp = dumpNode while (temp.next?.next != null ) { val n1 = temp.next val n2 = n1?.next n1?.next = n2?.next temp.next = n2 n2?.next = n1 temp = n1!! } return dumpNode.next }
accoding the idea https://leetcode.cn/problems/swap-nodes-in-pairs/solution/liang-liang-jiao-huan-lian-biao-zhong-de-jie-di-91/
the subject most inportant is temp = n1 , I didn’t know how to do the next cycle before
like author said 如果 temp
的后面没有节点或者只有一个节点,则没有更多的节点需要交换,因此结束交换. is also important
双指针 fast Node go n steps firstly, then fast slow Node go , at last slow point at the delete Node that last Node (慢指针 指向待删除指针的上一个指针)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 fun removeNthFromEnd (head: ListNode ?, n: Int ) : ListNode? { val dumpNode = ListNode() dumpNode.next = head var fp = dumpNode var sp = dumpNode var lastIndex = n while (lastIndex-- > 0 ) { if (fp.next != null ) { fp = fp.next!! } } while (dumpNode.next != null ) { if (fp.next == null ) { break } fp = fp.next!! sp = sp.next!! } sp.next = sp.next?.next return dumpNode.next }
栈
https://leetcode.cn/problems/remove-nth-node-from-end-of-list/solution/shan-chu-lian-biao-de-dao-shu-di-nge-jie-dian-b-61/
走对方的路,两条链表相加 路程相等
相互第2个连接的链表走完后,下个节点都是null 循环就结束了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 fun getIntersectionNode (headA: ListNode ?, headB: ListNode ?) : ListNode? { var pA = headA var pB = headB if (pA == null || pB == null ) { return null } while (pA != pB) { pA = if (pA == null ) { headB } else { pA.next } pB = if (pB == null ) { headA } else { pB.next } } return pA }
https://leetcode.cn/problems/intersection-of-two-linked-lists/solution/xiang-jiao-lian-biao-by-leetcode-solutio-a8jn/
https://leetcode.cn/problems/intersection-of-two-linked-lists/solution/shuang-zhi-zhen-yyds-dai-ma-jian-ji-teng-0bch/
https://leetcode.cn/problems/linked-list-cycle-ii/solution/142-huan-xing-lian-biao-ii-jian-hua-gong-shi-jia-2/
很生动的图
因为fast已经在环里, Slow只能走一圈,fast不能跳过,所以 slow的 步数 是 x+y 而不是 x + 若干环的长度 + y
根据公式推到结果 ,有环的话,先相遇,然后分别从head 相遇点 往相交点走.
下面这个答案就是拼出来的
解法一 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 fun detectCycle (head: ListNode ?) : ListNode? { var fp = head var sp = head while (true ) { fp = fp?.next?.next sp = sp?.next if (fp == null ) { return null } else if (fp == sp) { break } } var secondPoint = head while (sp?.next != null && secondPoint != sp) { secondPoint = secondPoint?.next!! sp = sp.next } return secondPoint }
解法二 下面写法,看了随想录的思路,第二天重写的。
可以在第一个循环的内部,head point 和相遇点开始走.
公式推导过程理解了就好了,然后记住结论。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 fun detectCycle (head: ListNode ?) : ListNode? { var fp = head var sp = head while (fp != null && sp != null ) { fp = fp.next?.next sp = sp.next if (fp!=null &&fp == sp) { var node1 = head while (sp?.next != null && node1 != sp) { node1 = node1?.next!! sp = sp.next } return node1 } } return null }
复杂度分析
时间复杂度:O(N)O(N),其中 NN 为链表中节点的数目。在最初判断快慢指针是否相遇时,\textit{slow}slow 指针走过的距离不会超过链表的总长度;随后寻找入环点时,走过的距离也不会超过链表的总长度。因此,总的执行时间为 O(N)+O(N)=O(N)O(N)+O(N)=O(N)。
空间复杂度:O(1)O(1)。我们只使用了 \textit{slow}, \textit{fast}, \textit{ptr}slow,fast,ptr 三个指针。
作者:LeetCode-Solution 链接:https://leetcode.cn/problems/linked-list-cycle-ii/solution/huan-xing-lian-biao-ii-by-leetcode-solution/ 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。