一.两两交换链表
两两链表交换跟之前的k个一组链表反转类似,当k等于2是就是两两交换,也比k个一组翻转更简单,因为要改变表头,所以需要设置一个虚拟头.描述如下:
示例 1:
输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例 2:
输入:head = [] 输出:[] 示例 3:
输入:head = [1] 输出:[1]
代码思路:1.先判断当前链表是否支持翻转
2.支持翻转就开始翻转,不支持就返回当前链表;
var swapPairs = function(head) {
//判断链表是否需要翻转
if(!head || !head.next) return head;
//定义一个虚拟头,将p赋值头结点是0的链表,q是头结点的下一个节点
let pre = new ListNode(0,head),p = pre,q = p.next;
// reverN(q,2)判断是否够反转,如果等于q就说明不需要翻转了
while((p.next = reverN(q,2)) != q){
//此时q = 翻转后p节点的下一个节点,将新的q赋值给p
p = q;
//q = p.next,得到的是未反转的节点,将剩下的节点进行翻转操作
q = p.next;
}
return pre.next;
};
var reverN = function(head,n){
//因为知道是两个节点翻转,所以如果head.next不存在就可以返回链表了,不需要判断是否满足kge
if(!head || !head.next) return head;
//满足条件进行翻转
return _reverN(head,n);
}
var _reverN = function(head,n){
if( n == 1 ) return head;
//tail是待翻转节点的,p是翻转的头结点
let tail = head.next,p = _reverN(head.next,n-1);
//head是待反转的一组节点,head.next = null,此时将head切断等于head第一个节点
head.next = tail.next;
//将切断的节点,拼接在未翻转节点下一个节点完成反转
tail.next = head;
return p;
}
二.删除链表的倒数第N个节点
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
示例 1:
输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5] 示例 2:
输入:head = [1], n = 1 输出:[] 示例 3:
输入:head = [1,2], n = 1 输出:[1]
解析:1.因为可能删除第一个节点,所以需要定义一个虚拟头,定义两个指针p,q;
2.让q先走需要删除的n步,然后p,q一切一起向后走,当q等于null,p的下一个节点就是需要删除的节点;
代码如下:
var removeNthFromEnd = function(head, n) {
//当节点不存在返回空链表
if(!head ) return [];
//定义虚拟头pre,将带有虚拟头的新链表赋值给p,q等于需要删除的链表
let pre = new ListNode(0,head),p = pre,q = head;
//先让q走n步
while(n --) q = q.next;
//如果链表是[1,2,3,4,5],n等于2,就是需要删除倒数第二个节点也就是4,此时q = [3,4,5],p = [0,1,2,3,4,5]
while(q){
p = p.next;
q = q.next;
}
//q走了三步等于null所以此时怕= [3,4,5],此时p.next = [4,5],p.next = p.next.next就是将节点4删除.
p.next = p.next.next;
return pre.next;
};
验证:加入head = [1,2,3,4,5,6,7,8,9],n=3,所以需要删除的是7;
while(n --) q = q.next; 此时q = [4,5,6,7,8,9],p = [0,1,2,3,4,5,6,7,8,9]
while(q){
p = p.next;
q = q.next;
}
q向后走6步,此时q = null,p = [6,7,8,9],所以p.next的关于6,让6指向8,就这样把7删除了.