题目描述
输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
思路
unshift
function printListFromTailToHead(head)
{
// write code here
if(!head) return [];//空链表/单链表
if(!head.next) return [head.val];//空链表/单链表
let res =[];
let cur=head;
while(cur){
res.unshift(cur.val);
cur =cur.next;
}
return res;
}
题目描述
输入一个链表,输出该链表中倒数第k个结点。
思路
特殊情况
:空链表和k小于0fast
,一个慢指针slow
,初始位置为头节点fast
向后移动k-1
次,如果移动中下一个节点为空,那么k值过小,返回fast
和慢指针slow
一起向后移动,直到fast为尾节点,返回slow指向的节点function FindKthToTail(head, k) {
// write code here
if (!head || k <= 0) return null;
let fast = head;
let slow = head;
//fast指针向后移动k-1
for (let i = 1; i < k; i++) {
if (fast.next) {
//下一个节点不空,指向下一个
fast = fast.next;
} else {
return null; //下一个节点空,说明k过小
}
}
//fast和slow一起后移,直到fast是尾节点
while (fast.next) {
fast = fast.next;
slow = slow.next;
}
return slow;//后面节点的位置就是倒数第k个节点
}
题目描述
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5
思路
newHead
,放在头节点前面,当头节点需要被删除时,方便返回结果
pre
指针指向前一个节点(初始为newHead
)cur
指向当前节点(初始为头节点),next
指向下一个节点(初始为null)cur.next
pre.next = next;
),cur指向next的当前位置newHead.next
function deleteDuplication(pHead) {
if (!pHead || !pHead.next) return pHead;
let newHead = new ListNode("head"); //新建一个节点
newHead.next = pHead; //充当新的头节点,当head节点被删除时可以返回正确的头节点
let pre = newHead; //pre指向前一个节点
let cur = pHead; //cur指向当前节点
let next = null; //next指向下一个节点
while (cur && cur.next) {
//当前节点不空且下一个节点不空时,进入比较循环
next = cur.next; //next存放下个节点的位置
if (next.val === cur.val) {
//cur和next值相等
//进入循环向后查找所有重复元素
while (next && next.val === cur.val) {
next = next.next; //next后移一位
}
//next空或者next和cur值不相等,退出循环
pre.next = next; //删除中间重复的节点
cur = next; //cur指针指向next的位置
} else {
//cur和next值不相等
pre = cur; //pre和cur都后移
cur = next;
}
}
return newHead.next;
}
(leetcode 206. Reverse Linked List)
leetcode 206. Reverse Linked List
https://leetcode.com/problems/reverse-linked-list/
var reverseList = function(head) {
if(!head||!head.next){//空链表/单链表,不需要反转
return head;
}
let pre,next=null;
while (head) {
next=head.next;//next先保存下一个节点
head.next=pre;//next指向pre,反转
pre=head;//pre和head向后移动一位
head=next;
}
return pre;//pre指向反转以后的头节点
};
题目描述
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
思路
特殊情况
:两个链表中有任意一个空链表,输出为另外一个链表minHead
作为合并头节点。maxHead
。minHead.next
指向下一次合并得出的头节点,这是一个递归
的过程,参数为minHead.next
和maxHead
,递归过程如下。minHead
function Merge(pHead1, pHead2) {
// write code here
//有一个链表为空,合并结果为另一个链表
if (!pHead1 || !pHead2) return pHead1 || pHead2;
//链表都不为空
let minHead, //头节点中值较小的
maxHead = null; //头节点中值较大的
pHead1.val < pHead2.val
? ((minHead = pHead1), (maxHead = pHead2))
: ((minHead = pHead2), (maxHead = pHead1));
minHead.next = Merge(minHead.next, maxHead);
return minHead;
}
题目:给定单链表,将所有奇数节点组合在一起,然后是偶数节点。
思路
特殊情况
,空/单/双链表不需要修改顺序odd
指向奇数节点,even
指向偶数节点,evenHead
保存第一个偶节点even && odd && even.next
,因为even.next需要even存在,所以要先判断even,因为odd.next夹在了中间,所以只需要判断最后的额 even.next存在odd
在even
前,所以先移动odd
——先改变.next
指针,再将odd/even
指向.next
的位置。head
var oddEvenList = function(head) {
if (!head || !head.next || !head.next.next) {
return head;
}
let odd = head, //odd指向奇数节点
evenHead= head.next,
even = head.next; //even指向偶数节点,evenHead保存第一个偶节点
while (even && odd && even.next) {
odd.next = even.next; //奇节点指向奇节点
odd = odd.next; //odd指针移向下一个奇节点
even.next = odd.next; //偶节点指向偶节点
even = even.next; //even指针移向下一个奇节点
}
odd.next = evenHead; //连接奇偶链表
return head;
};
题目:一个链表,奇数位升序偶数位降序,让链表变成升序的。
思路
这道题可以分成三步:
function sortOddEvenList(head) {
if (!head || !head.next) return null;
let evenHead = splitLists(head); //拆分节点,保存偶链表的头节点
reverseList(evenHead); //反转偶链表
// evenHead = reverseList(evenHead); //反转偶链表
return mergeLists(head, evenHead); //合并两个奇偶链表
}
// 拆分链表
function splitLists(head) {
if (!head || !head.next) return head;
let odd = head,
even = head.next,
evenHead = head.next;
while (odd && even && even.next) {
odd.next = even.next; //拆分,先拆奇节点
odd = odd.next; //后移
even.next = odd.next; //拆分
even = even.next; //后移
}
return evenHead;
}
// 反转链表
function reverseList(head) {
if (!head || !head.next) return head;
let pre = null,
cur = head,
next = null;
while (cur) {
next = cur.next; //保存下一位
cur.next = pre; //反转
pre = cur; //后移
cur = next; //后移
}
// return pre;
evenHead = pre;
}
//合并两个有序链表
function mergeLists(head1, head2) {
if (!head1 || !head2) return head1 || head1;
let minHead,
maxHead = null;
head1.val < head2.val
? ((minHead = head1), (maxHead = head2))
: ((minHead = head2), (maxHead = head1));
minHead.next = mergeLists(minHead.next, maxHead);
return minHead;
}
sortOddEvenList({
val: 1,
next: { val: 4, next: { val: 2, next: { val: 3, next: null } } }
});
141.Linked List Cycle:https://leetcode.com/problems/linked-list-cycle/submissions/
如何判断有环的存在?
在追及问题中,我们可以用两个速度不同
的物体从同一地点出发,如果相遇则证明存在环(可用反证法证明,若不存在环,则速度不同的物体从同一地点出发则一定不会相遇),因此可以类比过来,定义两个指针fast、slow
,令两指针以不同速度向后指,则相遇时证明有环存在
,若fast指向NULL,则不存在环。
注意相遇点不一定是环的入口
var hasCycle = function(head) {
if (!head || !head.next) {
//空链表/单链表,无环
return false;
}
let slow = head,
fast = head.next;
while (fast != slow) {
if (!fast || !fast.next) {
//fast指针链表到头,无环
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
};
题目,给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
怎么找到环的入口结点
在问题一中两指针相遇后,让一个指针从头结点
开始,另一个从相遇结点
开始,并以相同速度向后指,再次相遇时
就是环的入口结点。
function EntryNodeOfLoop(pHead) {
// write code here
//空链表/单链表,无环
if (!pHead) return 1;
if (!pHead.next) return null;
let slow = pHead, //慢指针
fast = pHead, ///快指针
head = pHead; //头节点指针
while (fast.next != null && slow != null) {//指针不为空,进入循环,继续后移
slow = slow.next;
fast = fast.next.next;
if (slow == fast) break;//相遇,跳出循环
}
while (fast != head) {//相遇,跳出循环
head = head.next;
fast = fast.next;
}
return head;
}
参考:https://blog.csdn.net/liushall/article/details/80444753