24. 两两交换链表中的节点
题目链接: 24. 两两交换链表中的节点
参考文档:代码随想录
状态:已完成,耗时一小时
思路:设置虚拟头节点,并将虚拟节点外的每两个节点作为一个整体去处理,至于虚拟头节点指向null或者只有一个元素的情况则额外处理
var swapPairs = function(head) {
let cur = new ListNode(0, head);
if(head == null || head.next == null){
return head;
}
let ret = head.next;
while(cur.next!=null && cur.next.next!=null){
let temp1 = cur.next;
let temp2 = cur.next.next.next
cur.next = cur.next.next;
cur.next.next = temp1;
temp1.next = temp2;
cur = cur.next.next;
}
return ret;
};
19. 删除链表的倒数第N个结点
题目链接: 19. 删除链表的倒数第N个结点
参考文档:代码随想录
状态:已完成,耗时一小时
思路一:遍历整个链表得到总的结点数,再从头遍历SUM-N次链表找到节点,代码实现如下:
var removeNthFromEnd = function(head, n) {
let cur = new ListNode(0, head);
let count = 0;
if(head == null) return null; //处理链表为空的情况
while(cur.next != null){ //获取链表长度
count++;
cur = cur.next;
}
if(count<n) return null; //处理n大于链表长度的情况
let temp = new ListNode(0, head); //记录链表头节点
let cur2 = temp;
while(count-n>0){ //找倒数第n个节点
count--;
cur2 = cur2.next;
}
cur2.next = cur2.next.next
return temp.next;
};
思路二:使用快慢指针,让快指针比慢指针快N步,当快指针指向链表最后一个节点,慢指针就指向倒数第N个节点的前一个节点,代码如下:
var removeNthFromEnd = function(head, n) {
let temp = new ListNode(0, head);
let cur = temp;
let pre = temp;
while(n){ //让快指针先走n步
n--;
cur = cur.next;
}
while(cur.next != null){ //快慢指针同步往前移
cur = cur.next;
pre = pre.next;
}
pre.next = pre.next.next; //删除倒数第N节点
return temp.next;
};
面试题 02.07. 链表相交
题目链接: 02.07. 链表相交
参考文档:代码随想录
状态:已完成,半小时
思路一:没有思路,看了答案发现可以通过指针相等来判定,于是想着先遍历两条链表的长度,并求差值,对较长的链表先走“差值”步—这样就可以让两条链表的剩余长度一致,后续两条链表一直往后遍历即可
var getIntersectionNode = function(headA, headB) {
let tempA = new ListNode(0,headA);
let tempB = new ListNode(0,headB);
pA = tempA;
pB = tempB;
let lengthA = 0;
let lengthB = 0;
while(pA.next != null){
lengthA++;
pA = pA.next;
}
while(pB.next != null){
lengthB++;
pB = pB.next;
}
pA = tempA;
pB = tempB;
if(lengthA>lengthB){
while(lengthA-lengthB){
lengthA--;
pA = pA.next;
}
}
else{
while(lengthB-lengthA){
lengthB--;
pB = pB.next;
}
}
while(pA.next != pB.next && pA.next !=null && pB.next !=null){
pA = pA.next;
pB = pB.next;
}
return pA.next;
};
当时写完还以为自己写复杂了,看了代码随想录里面的答案,发现也差不多。后面又翻了下官方的解法:
解法一:利用哈希集合储存点(数组存也可以,不过哈希查找的速度是O(1),数组是O(n)),代码:
var getIntersectionNode = function(headA, headB) {
const visited = new Set();
let temp = headA;
while (temp !== null) {
visited.add(temp);
temp = temp.next;
}
temp = headB;
while (temp !== null) {
if (visited.has(temp)) {
return temp;
}
temp = temp.next;
}
return null;
};
解法二,也是双指针,但是非常巧妙,核心思想是链表A+B和链表B+A得到的链表元素个数相同,且结尾肯定是相交的部分
var getIntersectionNode = function(headA, headB) {
if (headA === null || headB === null) {
return null;
}
let pA = headA, pB = headB;
while (pA !== pB) {
pA = pA === null ? headB : pA.next;
pB = pB === null ? headA : pB.next;
}
return pA;
};
142.环形链表II
题目链接: 142.环形链表II
参考文档:代码随想录
状态:已完成,一小时
思路:没有思路,看答案需要进行一定的数学推导,直接照抄答案,看随想录的觉得不够简单,去找了下leetcode的大神给的答案,参考了该答案后自己写了一份代码:
var detectCycle = function(head) {
let fast = new ListNode(0,head);
let slow = new ListNode(0,head);
if(fast.next === null || fast.next.next === null) return null;
while(fast!==slow){
fast=fast.next.next;
slow=slow.next;
if(fast===null||fast.next===null) return null;
}
fast = new ListNode(0,head);
while(fast!==slow){
fast=fast.next;
slow=slow.next;
}
return fast;
};