两两交换链表中的节点
文章:代码随想录 (programmercarl.com)
题目:24. 两两交换链表中的节点
视频:帮你把链表细节学清楚! | LeetCode:24. 两两交换链表中的节点_哔哩哔哩_bilibili(尊嘟讲的很好,可以去看看!)
奇数节点:最后会多出来一个节点,但是因为没有多出来的节点可以和其交换,所以我们不交换最后一个节点
偶数节点:两两交换即可
【思路】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Solution { public ListNode swapPairs(ListNode head) { ListNode dummyNode = new ListNode(0); dummyNode.next = head; ListNode cur = dummyNode; while(cur.next != null && cur.next.next!= null){ ListNode temp = cur.next; ListNode temp1 = cur.next.next.next;
cur.next = cur.next.next; cur.next.next = temp; temp.next = temp1; cur = cur.next.next; } return dummyNode.next; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| func swapPairs(head *ListNode) *ListNode { dummyNode := &ListNode{0,head} cur := dummyNode for cur.Next != nil && cur.Next.Next != nil{ temp := cur.Next temp1:= cur.Next.Next.Next
cur.Next = cur.Next.Next cur.Next.Next = temp temp.Next = temp1 cur = cur.Next.Next } return dummyNode.Next
}
|
删除链表的倒数第N个结点
文章:6. 删除链表的倒数第N个节点
题目:19. 删除链表的倒数第 N 个结点
【思路】
本题是我自己想出来的办法(一年前有写过该题),大概思路为使用快慢指针,先将fast指针提前先走N步,随后fast和slow指针一起遍历,直到fast指针的next为空(即fast指针已经指向链表的末尾),这时prev指针指向的正好是需要删除的倒数第N-1个结点处。我们只需要修改第N-1个结点的next指针即可完成对倒数第N个结点的删除。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class Solution { public ListNode removeNthFromEnd(ListNode head, int n) { ListNode dummyNode = new ListNode(0); dummyNode.next = head; ListNode cur = dummyNode; ListNode prev = dummyNode;
for(int i = 0 ;i < n;i++){ cur = cur.next; } while( cur.next!= null){ cur = cur.next; prev = prev.next; } prev.next = prev.next.next; return dummyNode.next;
} }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| func removeNthFromEnd(head *ListNode, n int) *ListNode { dummyNode := &ListNode{} dummyNode.Next = head fast := dummyNode slow := dummyNode
for i:= 0 ;i < n;i++{ fast = fast.Next } for fast.Next != nil{ fast = fast.Next slow = slow.Next } slow.Next = slow.Next.Next return dummyNode.Next }
|
链表相交
文章:7. 链表相交
题目:面试题 02.07. 链表相交
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 getIntersectionNode(ListNode headA, ListNode headB) { int lenA = 0; int lenB = 0; ListNode dummyNodeA = headA; ListNode dummyNodeB = headB;
while(dummyNodeA != null){ lenA++; dummyNodeA = dummyNodeA.next; } while(dummyNodeB !=null){ lenB++; dummyNodeB = dummyNodeB.next; } dummyNodeA = headA; dummyNodeB = headB;
if(lenB > lenA){ int temlem = lenA; lenA = lenB; lenB = temlem; ListNode temNode = dummyNodeA; dummyNodeA = dummyNodeB; dummyNodeB = temNode; } int gap = lenA - lenB; while(gap -- > 0){ dummyNodeA = dummyNodeA.next; } while(dummyNodeA != null){ if(dummyNodeA == dummyNodeB){ return dummyNodeA; } dummyNodeA = dummyNodeA.next; dummyNodeB = dummyNodeB.next; } return null; } }
|
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
| func getIntersectionNode(headA, headB *ListNode) *ListNode { lenA ,lenB := 0 , 0 dummyA , dummyB := headA,headB for dummyA!= nil{ lenA+=1 dummyA = dummyA.Next } for dummyB != nil{ lenB+=1 dummyB = dummyB.Next } dummyA ,dummyB = headA,headB if lenA < lenB{ lenA,lenB = lenB,lenA dummyA,dummyB = dummyB,dummyA } gap := lenA-lenB for gap >0 { dummyA = dummyA.Next gap-- } for dummyA != nil { if dummyA == dummyB{ return dummyA } dummyA = dummyA.Next dummyB = dummyB.Next } return nil }
|
环形数组II
【思路】
- 快慢指针,如果链表有环,快慢指针会相遇
- Java实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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(slow == fast){ ListNode index1 = fast; ListNode index2 = head; while(index1 != index2){ index1 = index1.next; index2 = index2.next; } return index1; } } return null; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| func detectCycle(head *ListNode) *ListNode { fast,slow := head,head for fast != nil && fast.Next != nil{ fast = fast.Next.Next slow = slow.Next if(fast == slow){ index1 , index2 := fast,head for index1 != index2 { index1 = index1.Next index2 = index2.Next } return index1 } } return nil }
|
【算法总结】
- 两两交换链表中的节点采用虚拟头结点的方式来两两交换节点,交换完后虚拟节点直接去第三个节点;需要注意循环的终止条件!
- 删除链表的倒数第N个节点采用快慢指针的方式进行节点删除,通过保持快指针和慢指针之间的距离来对倒数第N个节点进行操作;需要注意快慢指针最好是同一个起点,这样比较方便判断!同时需要注意循环的终止条件!
- 链表相交采用判断链表长度、交换链表头结点、将两链表的长度对齐的方法进行是否相交的判断;需要注意是判断指针是否相同,而不是判断指针的值是否相同
- 环形数组II采用快慢指针的方式来判断链表是否有环、寻找环的入口在哪;需要注意循环的终止条件,(易错点)很容易循环到null值!;不得不说卡尔劳斯的推导真的很精彩,感谢!
需要强调的一点:需要注意指针next属性的使用,很容易跳过头出现null
ORnil
的情形。