我新建的个人博客,欢迎访问:hmilzy.github.io
24. 两两交换链表中的节点 题目链接: 两两交换链表中的节点
方法一:同样设置虚拟头结点。这里需要操作的结点数很多,数四个分别为 cur、firstNode、secondNode、temp,判断循环结束的条件需要注意一下,避免出现空指针异常
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 class Solution { public ListNode swapPairs (ListNode head) { ListNode dummyhead = new ListNode (0 ); dummyhead.next = head; ListNode cur = dummyhead; ListNode temp; ListNode firstNode; ListNode secondNode; while (cur.next != null && cur.next.next != null ){ temp = cur.next.next.next; firstNode = cur.next; secondNode = cur.next.next; cur.next = secondNode; secondNode.next = firstNode; firstNode.next = temp; cur = firstNode; } return dummyhead.next; } }
方法二:递归法(此处有点难以理解,需要多画图吧)
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 class Solution { public ListNode swapPairs (ListNode head) { if (head == null || head.next == null ){ return head; } ListNode temp = head.next; ListNode newNode = swapPairs(temp.next); temp.next = head; head.next = newNode; return temp; } }
19. 删除链表的倒数第 N 个结点 题目链接: 删除链表的倒数第 N 个结点
第一个思路:肯定是先遍历链表,得到链表长度。然后重新从头结点开始遍历,找到要删除结点的前一个结点即可。
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 class Solution { public ListNode removeNthFromEnd (ListNode head, int n) { ListNode dummyhead = new ListNode (0 ); dummyhead.next = head; ListNode cur = dummyhead; int size = 0 ; while (cur.next != null ){ cur = cur.next; size++; } cur = dummyhead; for (int i = 0 ; i < size - n; i++){ cur = cur.next; } cur.next = cur.next.next; return dummyhead.next; } }
第二个方法:倒数第n个结点,可以从头节点开始,找到一个大小为n的窗口,也就是双指针。 当右指针遍历到链表尾部的时候,左指针就正好是要删除的结点的前一个结点,然后再删除即可。 多画图!!!
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 class Solution { public ListNode removeNthFromEnd (ListNode head, int n) { ListNode dummyhead = new ListNode (0 ); dummyhead.next = head; ListNode fast = dummyhead; ListNode slow = dummyhead; for (int i = 0 ;i < n + 1 ;i++){ fast = fast.next; } while (fast != null ){ fast = fast.next; slow = slow.next; } slow.next = slow.next.next; return dummyhead.next; } }
面试题 02.07. 链表相交 题目链接: 链表相交 参考题解:思路十分巧妙
1 2 3 4 5 6 7 8 9 10 public class Solution { public ListNode getIntersectionNode (ListNode headA, ListNode headB) { ListNode A = headA, B = headB; while (A != B) { A = A != null ? A.next : headB; B = B != null ? B.next : headA; } return A; } }
142. 环形链表 II 题目链接: 环形链表 II 具体思路可以看卡哥文章,很清晰。
要判断是否成环。这里采用快慢指针的思路,满指针走一步,快指针走两步,看是否会相遇。
成环之后,要返回进入环的位置。可以先找到相遇点位置,让一个指针从头结点开始走,另一个指针从相遇点开始走,最后一定相遇,且相遇的地方就是环入口。
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 public class Solution { public ListNode detectCycle (ListNode head) { ListNode fast = head; ListNode slow = head; while (true ) { if (fast == null || fast.next == null ) return null ; fast = fast.next.next; slow = slow.next; if (fast == slow) break ; } fast = head; while (slow != fast) { slow = slow.next; fast = fast.next; } return fast; } }