删除中间节点
问题描述: 若链表中的某个节点,既不是链表头节点,也不是链表尾节点,则称其为该链表的「中间节点」。
假定已知链表的某一个中间节点,请实现一种算法,将该节点从链表中删除。(by leetcode 02.03)
例如,传入节点 c(位于单向链表 a->b->c->d->e->f 中),将其删除后,剩余链表为 a->b->d->e->f
示例:
输入:节点 5 (位于单向链表 4->5->1->9 中)
输出:不返回任何数据,从链表中删除传入的节点 5,使链表变为 4->1->9
思路: 用当前点冒充下一个点,删除下一个点。
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} node
* @return {void} Do not return anything, modify node in-place instead.
*/
var deleteNode = function(node) {
node.val=node.next.val;
node.next=node.next.next;
};
两数相加 II
问题描述: 给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。(by lkeetcode 445)
示例1:
输入:l1 = [7,2,4,3], l2 = [5,6,4]
输出:[7,8,0,7]
思路: 利用栈的数据结构,把链表分别压入两个栈中,求和压入新的栈中,求和注意记录上一次求和是否需要进位。最后把栈转成链表。
/**
* 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 stack1=[],stack2=[];
while(l1){
stack1.push(l1.val);
l1=l1.next
}
while(l2){
stack2.push(l2.val);
l2=l2.next
}
let temp=0;
let ans=null;
while(stack1.length||stack2.length||temp==1){
if(!stack1.length){
stack1.push(0)
}
if(!stack2.length){
stack2.push(0)
}
let ele=stack1[stack1.length-1]+stack2[stack2.length-1]+temp;
if(ele>9){
ele=ele-10;
temp=1;
}else{
temp=0;
}
stack1.pop()
stack2.pop()
let newhead=new ListNode(ele);
newhead.next=ans;
ans=newhead;
}
return ans
};
重排链表
问题描述: 给定一个单链表 L 的头节点 head ,单链表 L 表示为:
L0 → L1 → … → Ln - 1 → Ln
请将其重新排列后变为:
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。(by leetcode 143)
示例 :
输入:head = [1,2,3,4]
输出:[1,4,2,3]
思路: 方法一:用数组来处理。 方法二:优化版本见代码
/**
* 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 {void} Do not return anything, modify head in-place instead.
*/
var reorderList = function(head) {
if(head==null)return
let stack=[];
while(head!=null){
stack.push(head);
head=head.next
}
let i=0,j=stack.length-1;
while(i<j){
stack[i].next=stack[j];
i++;
if(i==j)break;
stack[j].next=stack[i];
j--
}
stack[i].next=null;
};
//优化版本
//反转链表
function reverse(head){
if(head==null||head.next==null){return head}
let pre=null,cur=head;
while(cur){
let next=cur.next;
cur.next=pre;
pre=cur;
cur=next;
}
return pre;
}
var reorderList = function(head) {
// 找到中间节点,将链表一分为二(用快慢指针)
let slow=head,fast=head;
while(fast.next!==null&&fast.next.next!==null){
slow=slow.next;fast=fast.next.next;
}
fast=slow.next;
slow.next=null;
// 后段链表反转
fast=reverse(fast);
// 两条链表拼接
while(head!==null&&fast!==null){
let headn=head.next;
let fastn=fast.next;
head.next=fast;
fast.next=headn;
head=headn;
fast=fastn
}
};
移除无效的括号
问题描述: 给你一个由 '('、')' 和小写字母组成的字符串 s。
你需要从字符串中删除最少数目的 '(' 或者 ')' (可以删除任意位置的括号),使得剩下的「括号字符串」有效。
请返回任意一个合法字符串。(by leetcode 1249)
有效「括号字符串」应当符合以下 任意一条 要求:
-
空字符串或只包含小写字母的字符串
-
可以被写作
AB(A连接B)的字符串,其中A和B都是有效「括号字符串」 -
可以被写作
(A)的字符串,其中A是一个有效的「括号字符串」
示例 :
输入:s = "lee(t(c)o)de)"
输出:"lee(t(c)o)de"
解释:"lee(t(co)de)" , "lee(t(c)ode)" 也是一个可行答案。
思路: 采用计数的方式 先把多余的右括号去掉,然后从后往前看,多余的左括号先删除(因为左括号是在左边,所以从右开始,避免返回的无效)
/**
* @param {string} s
* @return {string}
*/
var minRemoveToMakeValid = function(s) {
s=s.split("");
let str=[],count=0;
for(let i=0,len=s.length;i<len;i++){
if(s[i]=="("){count++;str.push(s[i])}
else if(s[i]==")"){
count--;
if(count<0){count=0;}
else{str.push(s[i])}
}
else{
str.push(s[i])
}
}
let i=str.length-1
while(count>0){
if(str[i]=="("){
count--;
str.splice(i,1,"");
}
i--;
}
return str.join("")
};
复杂链表的复制
问题描述: 请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。(by leetcode 35)
示例 :
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
思路:
/**
* // Definition for a Node.
* function Node(val, next, random) {
* this.val = val;
* this.next = next;
* this.random = random;
* };
*/
/**
* @param {Node} head
* @return {Node}
*/
var copyRandomList = function(head) {
if (head === null) {
return head;
}
let p=head;
while(p){
const nodeNew = new Node(p.val, p.next, null);
p.next = nodeNew;
p=nodeNew.next;
}
p=head;
while(p){
const nodeNew = p.next;
nodeNew.random = (p.random !== null) ? p.random.next : null;
p=nodeNew.next;
}
p=head;
let headNew=head.next
while(p){
let node=p.next;
p.next=node.next;
node.next = (node.next !== null) ? node.next.next : null;
p=p.next;
}
return headNew;
};