环形链表 II
问题描述: 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。(by leetcode 142)
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
示例 1:
思路: 设置快慢指针,慢指针每次走一步,快指针每次走两步,若相遇,则说明有环,反之没有坏。有环的情况下,将慢指针重新指向头节点,快慢指针依次走一步,他们相遇的节点便是环开始的节点。
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
//注意事项:慢指针初始走一步,快指针初始走两步。
var detectCycle = function(head) {
if(head==null) return null;
let slow=head.next;
let fast;
if(head.next&&head.next.next){
fast=head.next.next;
}else{
return null
}
while(fast!==null&&fast.next!==null&&fast!==slow){
fast=fast.next.next;
slow=slow.next;
}
if(fast===slow){
slow=head;
while(fast!==slow){
fast=fast.next;
slow=slow.next;
}
return slow
}
return null
};
反转链表
问题描述: 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。(by leetcode 206)
示例 1:
输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
思路: 设置pre,cur指针,原本pre.next=cur;改变两个指针的方向(注意pre指针一开始是null,因为要切断head的next指向,所以pre需要设置为null.),并依次往后走。直到cur.next没有,说明走到倒数第二个节点,再改变两个指针的指向,此时返回当前cur则是反转后的链表头节点。
/**
* 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) {
if(head==null||head.next==null)return head;
let pre=null;
let cur=head;
while(cur.next){
let next=cur.next;
cur.next=pre;
pre=cur;
cur=next
}
cur.next=pre
return cur;
};
反转链表 II
问题描述: 给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。(by leetcode 92)
示例 1:
输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]
思路: 找到left节点前一个节点pre,将需要翻转链上的节点依次往前拿,让pre指向拿过来的节点,且拿过来的节点指向pre原本的下一个节点。直到将第right个节点也拿过来。由于头节点可能被改变,因此需要虚拟节点,返回虚拟节点下一个节点即可。
/**
* 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} left
* @param {number} right
* @return {ListNode}
*/
var reverseBetween = function(head, left, right) {
if(head==null||head.next==null) return head;
let dummy=new ListNode();
dummy.next=head;
let pre=dummy;
for(let i=0;i<left-1;i++){
pre=pre.next;
}
let cur=pre.next;
for(let i=0;i<right-left;i++){
let next=cur.next;
cur.next=next.next;
next.next=pre.next;
pre.next=next
}
return dummy.next
};
删除链表的倒数第 N 个结点
问题描述: 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。(by leetcode 19)
示例 1:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
思路: 先循环链表,算出链表长度,便可以找到倒数第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} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
if(head==null)return head;
let dummy=new ListNode()
dummy.next=head;
let cur=head;
let num=0;
while(cur){
cur=cur.next;
num++;
}
let pre=dummy;
cur=dummy.next;
for(let i=0;i<num-n;i++){
pre=pre.next;
cur=cur.next;
}
pre.next=cur.next;
cur.next=null;
return dummy.next
};
删除排序链表中的重复元素
问题描述: 存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除所有重复的元素,使每个元素 只出现一次 。
返回同样按升序排列的结果链表。(by leetcode 83)
示例 1:
输入:head = [1,1,2]
输出:[1,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 deleteDuplicates = function(head) {
if(head==null||head.next==null)return head;
let dummy=new ListNode(0)
dummy.next=head;
let cur=head;
while(cur!=null){
let news=cur.next;
while(news!==null&&cur.val==news.val){
cur.next=news.next;
news.next=null;
news=cur.next
}
cur=cur.next;
}
return dummy.next
};
删除排序链表中的重复元素 II
问题描述: 存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 的数字。(by leetcode 82)
存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 **的数字。
返回同样按升序排列的结果链表。
示例 1:
输入: head = [1,2,3,3,4,4,5]
输出: [1,2,5]
返回同样按升序排列的结果链表。
示例 1:
输入: head = [1,2,3,3,4,4,5]
输出: [1,2,5]
思路: 建立虚拟指针,指向head,向后遍历,一旦后两个节点相同,则记录该值,一直向后走,有跟该值一致的,则将该节点剔除,直到某一节点后面没有至少两个节点。
/**
* 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 deleteDuplicates = function(head) {
if(head==null||head.next==null) return head;
let dummy=new ListNode(0);
dummy.next=head;
let cur=dummy;
while(cur.next&&cur.next.next){
if(cur.next.val==cur.next.next.val){
let temp=cur.next.val;
while(cur.next&&cur.next.val==temp){
cur.next=cur.next.next;
}
}
else{
cur=cur.next
}
}
return dummy.next;
};