代码随想录算法训练营第四天|LeetCode 24,19,面试题 02.07,142
24. 两两交换链表中的节点
题目要求不能修改节点内部的值,只能通过交换节点进行,最开始打算在链表反转上做改动,但存在无法获取最终的头结点,无法将当前的second.next更新为下一次交换后的first等问题。为了保持一致性,考虑加入虚拟头节点。
public ListNode swapPairs(ListNode head) {
ListNode dummy = new ListNode();
dummy.next = head;
ListNode pre = dummy;
ListNode tmp = head;
while ((tmp!=null)&&(tmp.next != null)){
ListNode first = tmp;
ListNode second = first.next;
first.next = second.next;
tmp = second.next;
second.next = first;
pre.next = second;
pre = first;
}
return dummy.next;
}
与反转链表类似,本题同样可以考虑递归方法
public ListNode swapPairs(ListNode head){
//base case 退出递交
if(head == null || head.next == null) return head;
//获取当前节点的下一个节点
ListNode next = head.next;
//进行递归
ListNode newNode = swapPairs(next.next);
//进行交换
next.next = head;
head.next = newNode;
return next;
}
19. 删除链表的倒数第 N 个结点
根据题目提示,不用考虑n的有效性的问题。由于是单链表,在一次循环中完成操作的话,可以考虑双指针,两个指针之间的距离为n,当后面一个指针达到链表尾部的时候,前面一个指针正好指向倒数第n个节点的前一个节点。
public ListNode removeNthFromEnd(ListNode head, int n) {
//加入头结点。
ListNode dummy = new ListNode();
dummy.next = head;
ListNode start = dummy;
ListNode end = dummy;
//将start与end拉开n距离。start正好指向第n-1个几点
for(int i = 0; i < n; i++){
end = end.next;
}
//移动指针
while(end.next != null){
end = end.next;
start = start.next;
}
//移除第n个节点
start.next = start.next.next;
return head;
}
面试题 02.07. 链表相交
第一想法是暴力,但是时间复杂度会很高。看到题目提示后,想到list A和listB可能存在长度不一样,那么可以将较长的链表的头节点往后移动到与较短节点头结点一致的位置,就可以同时往后移动两个指针进行比较了。
此外本题目需要注意的一点是:节点的值一样,也不一定是相交的点。
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
int a = 0;
int b = 0;
//获取链表A的长度
ListNode tmp = headA;
while (tmp!=null){
a++;
tmp = tmp.next;
}
//获取链表B的长度
tmp = headB;
while (tmp!=null){
b++;
tmp = tmp.next;
}
//获取较长与较短的链表
ListNode longList;
int longLen ;
ListNode shortList;
int shortLen;
if(a > b){
longList = headA;
longLen = a;
shortList = headB;
shortLen = b;
}else {
longList = headB;
longLen = b;
shortList = headA;
shortLen = a;
}
//将较长的节点往后移动至与较短节点一直的位置
for(int i = 0 ; i <(longLen - shortLen);i++){
longList = longList.next;
}
for(int i = 0; i < shortLen;i++){
if (longList == shortList){
return longList;
}
longList = longList.next;
shortList = shortList.next;
}
return null;
}
142. 环形链表 II
本题存在一定的难度,如何判断有环以及如何寻找环的入口都需要考虑。可以通过快慢指针来判断是否有环。环的入口可以通过将fast追上slow时的条件列出公式从而获得判断条件
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
ListNode index1 = fast;
ListNode index2 = head;
while (index1 != index2) {
index1 = index1.next;
index2 = index2.next;
}
return index1;
}
}
return null;
}
}