1. 删除链表的倒数第a个结点
给你一个链表,删除链表的倒数第
a个结点,并且返回链表的头结点。
1.1 双指针解题思路
如果要删除链表的倒数第a个结点,我们需要知道倒数第a个结点的前一个节点是哪个,然后将这个节点的next指向倒数第a个结点的next姐可以了。 想要要删除链表的倒数第a个结点,我们可以设置两个指针p、q,先让p走a个节点,再p、q同时走,这样等到p走到结尾的时候,q此时的位置就是倒数第a个节点的前一个节点了。
代码实现如下:
var removeNthFromEnd = function(head, n) {
let newHead = new ListNode(0, head);
let p = newHead;
let q = newHead;
while(n > 0) {
p = p.next;
n -= 1;
}
while(p.next !== null) {
q = q.next;
p = p.next;
}
q.next = q.next.next;
return newHead.next;
};
2. 旋转链表
给你一个链表的头节点
head,旋转链表,将链表每个节点向右移动k个位置。
2.1 解题思路
首先,我们需要知道,当k等于链表长度(n)的时候,是不用移动的,所以k大于链表的长度的时候,需要求真正的移动次数,而它应该等于k%n。其次,就是链表移动k个位置,就是将指针从开始移动到n-k%n的位置,然后将当前的节点next指向null,再将最后的节点指向开始的节点就可以了。
代码实现如下:
var rotateRight = function(head, k) {
if (!head) return null;
let p = head;
let i = 1;
while(p.next) {
i += 1;
p = p.next;
}
p.next = head;
k = k % i;
k = i - k;
while(k !== 0) {
p = p.next;
k -= 1;
}
const temp = p.next;
p.next = null;
return temp || p;
};
3. 删除排序链表中的重复元素
存在一个按升序排列的链表,给你这个链表的头节点
head,请你删除所有重复的元素,使每个元素 只出现一次 。返回同样按升序排列的结果链表。
3.1 解题思路
首先这个链表是已经排序好的,所以,重复的是连续的,所以在遍历的时候,将当前节点的值与它下一个节点比较,如果相同,则将它的next指向它的下一个节点的next,同时将当前节点变成下一个节点,不相同,就将当前节点变成下一个节点。
代码实现如下:
var deleteDuplicates = function(head) {
let p = head;
while(p) {
if (p.next && p.val === p.next.val) {
p.next = p.next.next;
} else {
p = p.next;
}
}
return head;
};
4. 反转链表
给你单链表的头节点
head,请你反转链表,并返回反转后的链表。
4.1 解题思路
反转链表其实就是将当前节点的next指向它的上一个节点,所以我们可以定义两个变量,一个表示上一个节点,一个表示当前节点。
代码实现如下:
var reverseList = function(head) {
if (!head || !head.next) return head;
let p = head;
let pre = null;
while(p.next) {
let temp = p;
p = p.next;
temp.next = pre;
pre = temp;
}
p.next = pre;
return p;
};
5. K个一组翻转链表
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
点此解题LeetCode吧
5.1 解题思路
我个人理解,这个题和反转链表可以使用差不多的思路去解决,只不过这个只是分组内的反转链表。需要明白的是,一组的链表反转完成后,它的头部节点会变成尾节点,尾节点变成头部节点,而它的尾节点的next应该指向的是下一个分组的头部节点。
代码实现如下
var reverseKGroup = function(head, k) {
if (k === 0 || k === 1) {
return head;
}
let i = 1;
let newHead;
let curGroupLastNode;
let curGroupHead = head;
let p = head;
while(true) {
if (i % k === 0) {
if (curGroupLastNode) {
curGroupLastNode.next = p;
}
curGroupLastNode = curGroupHead;
curGroupHead = p.next;
p.next = null;
let q = reverseList(curGroupLastNode);
if (!newHead) {
newHead = q;
}
curGroupLastNode.next = curGroupHead;
p = curGroupHead;
} else {
p = p.next;
}
if (!p) {
return newHead;
}
i += 1;
}
function reverseList(head) {
if (!head || !head.next) return head;
let p = head;
let pre = null;
while(p.next) {
let temp = p;
p = p.next;
temp.next = pre;
pre = temp;
}
p.next = pre;
return p;
};
return head;
};
6. 返回倒数第 k 个节点
实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。
6.1 解题思路
这道题与删除链表倒数第a个结点的思路是一样的,只不过这个地方是返回next的val值。
代码实现如下:
var kthToLast = function(head, k) {
let newHead = new ListNode(0, head);
let p = newHead;
let q = newHead;
while(k > 0) {
p = p.next;
k -= 1;
}
while(p.next !== null) {
q = q.next;
p = p.next;
}
return q.next.val;
};