24 两两交换链表中的节点
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。 你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例:
给定 1->2->3->4, 你应该返回 2->1->4->3.
链接:leetcode-cn.com/problems/sw…
解题思路1(迭代)
用三个指针分别指向前一个,要交换的第一个,要交换的第二个,进行相应交换之后继续向后遍历,如果是偶数个节点first会先到Null,如果是奇数个节点second会先到null。 这里要专门处理一下前两个节点(也可以设置一个哑元节点)
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var swapPairs = function(head) {
if(head === null || head.next === null)//判断为空或者只有一个节点的情况
return head;
let pre = null;//第一个节点的前一个
let first = head;//要交换的第一个节点
let second = first.next;//要交换的第二个节点
while(second != null){
if(pre === null){//处理链表表头
first.next = second.next;
second.next = first;
head = second;
}else{
pre.next = second;
first.next = second.next;
second.next = first;
}
first = first.next;
if(first === null)//只有偶数个节点
break;
pre = second.next;
second = first.next;//second===null说明有奇数个节点
}
return head;
};
解题思路2(递归)
递归方法就是把链表所有节点都分为两组,那么递归的功能就是返回交换后的第一个节点,所以在递归里面就可以只解决内部两个节点的交换问题。
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var swapPairs = function(head) {
if(head === null || head.next === null)//判断为空或者只有一个节点的情况为递归出口
return head;
let after = head.next;
head.next = swapPairs(after.next);//下一组交换节点返回的交换后的第一个
after.next = head;
return after;//返回这两个中的交换后的第一个
};
203 移除链表元素
删除链表中等于给定值 val 的所有节点。
示例:
输入: 1->2->6->3->4->5->6, val = 6
输出: 1->2->3->4->5
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} val
* @return {ListNode}
*/
var removeElements = function(head, val) {
let dummy = new ListNode(0,head);//设立一个哑元节点
let pre = dummy;
while(pre.next != null){
let cur = pre.next;
if(cur.val === val)
pre.next = cur.next;
else
pre = pre.next;
}
return dummy.next;
};
2 两数相加
给出两个非空的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。 您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
输入:l1 = [0], l2 = [0]
输出:[0]
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
链接:leetcode-cn.com/problems/ad…
解题思路
用变量res表示进位,把对应的数相加,然后加上进位进行计算。这里要注意的是如果两个链表长度不等,那么还要继续计算剩下链表的部分;如果最后进位不为0,那么还要多加一个节点存储进位。
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
var addTwoNumbers = function(l1, l2) {
let res = 0;//表示进位
let pre = new ListNode(0,null);
let newhead = pre;
while(l1 || l2 || res){//在最后res不为0时也要继续加一个节点
let a = !l1 ? 0 : l1.val;
let b = !l2 ? 0 : l2.val;
let sum = a + b + res;
res = Math.floor(sum/10);//计算进位
sum = sum - res * 10;
let cur = new ListNode(sum,null);//生成结果节点
pre.next = cur;
pre = pre.next;
l1 = l1? l1.next : null;
l2 = l2? l2.next : null;
}
return newhead.next;
};
19删除链表的倒数第N个节点
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
示例:
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
说明:
给定的 n 保证是有效的。
链接:leetcode-cn.com/problems/re…
思路解析
使用快慢指针,快指针先和慢指针隔开n的距离,之后一起遍历,当快指针到末尾的时候,慢指针正好指向被删除的节点。(这里还是用了一个bre指针指向被删节点的前一个节点,方便删除时使用)
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
let dummy = new ListNode(0,head);
let bre = dummy;//被删节点的前一个结点
let cur = head;//被删节点
let pre = head;//先行节点
while(--n)
pre = pre.next;
while(pre.next){
pre = pre.next;
cur = cur.next;
bre = bre.next;
}
bre.next = cur.next;
return dummy.next;
};
206 反转链表
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
链接:leetcode-cn.com/problems/re…
解题思路
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
let pre = null;
let cur = head;
while(cur != null){
let next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
};
92.反转链表 II
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
解题思路
部分反转需要记录四个位置,分别是m-1,m,n,n+1,这样才可以在反转完[m,n]之后和其余的节点正常连接。 反转部分借用上一题的代码,稍微更改一下返回值。
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} m
* @param {number} n
* @return {ListNode}
*/
var reverseBetween = function(head, m, n) {
let sliceStart = null;//m位置
let sliceEnd = null;//n位置
let pre = null;//m的前一个位置
let tail = null;//n的后一个位置
let count = 1;
let cur = head;
while(count <= n){
if(count === m-1){
pre = cur;
}
if(count === m){
sliceStart = cur;
}
if(count === n){
sliceEnd = cur;
}
cur = cur.next;
count++;
}
tail = sliceEnd.next;
sliceEnd.next = null;
[sliceStart,sliceEnd] = reverseList(sliceStart);
if(pre){
pre.next = sliceStart;
}else{
head = sliceStart;
}
sliceEnd.next = tail;
return head;
};
var reverseList = function(head) {
let pre = null;
let cur = head;
while(cur != null){
let next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return [pre,head];
};