文章目录
- 31 反转链表
- 32 回文链表
- 33 环形链表
- 34 环形链表Ⅱ
- 35 合并两个有序链表
31 反转链表
- 初始化:cur = head,pre = null。
- pre和cur一起向前移。
- 由于反转链表时,cur.next指向pre,导致cur在下次循环中就找不到了原来的cur.next,因此需要临时指针temp记录原来的cur.next。
var reverseList = function(head) {
if(!head || !head.next){
return head;
}
var pre = null;
var cur = head;
while(cur){
var temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
};
32 回文链表
- 方法1:将链表节点的val放入数组中,然后利用双指针判断是否为回文数组(i指向第一个元素,j指向最后一个元素)。
- 方法2:快慢指针,这里给出该方法的代码。
- 将后半部分反转,前半部分和后半部分链表比较。
- 快指针1次走2步,慢指针1次走1步。
- 快指针走到头,慢指针刚好到中间,此时这个中间点既是反转链表的起点。
- 后半部分链表反转后,利用双指针判断是否为回文链表(left指向前部分的头节点[整个链表的头节点],right指向后半部分的头节点[整个链表最后一个节点])。
var reverseList = function(head) {
if(!head || !head.next){
return head;
}
var pre = null;
var cur = head;
while(cur){
var temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
};
var findMiddle = function(head) {
var fast = head;
var slow = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
var isPalindrome = function(head) {
var mid = findMiddle(head);
var right = reverseList(mid);
var left = head;
while(left != null && right != null){
if(left.val != right.val){
return false;
}
left = left.next;
right = right.next;
}
return true;
};
33 环形链表
- 哈希集合
- 遍历链表节点,将节点放入Set中,若Set中已经存在该节点,则该链表存在环。
var hasCycle = function(head) {
var set = new Set();
while(head != null){
if(set.has(head)){
return true;
}
set.add(head);
head = head.next;
}
return false;
};
34 环形链表Ⅱ
- 方法1:哈希集合,遍历链表节点,将节点放入Set中,若Set中已经存在该节点,则该节点为入口的第一个节点。
var detectCycle = function(head) {
var set = new Set();
while(head != null){
if(!set.has(head)){
set.add(head);
}else{
return head;
}
head = head.next;
}
return null;
};
- 方法2:快慢指针。
- 快指针1次走2步,慢指针1次走1步。快指针绕圈了,快指针追慢指针。
- 假设:从链表头节点到入环的第一个节点的长度为x,入环的第一个节点到快、慢指针相遇点的长度为y,快、慢指针相遇点到入环的第一个节点的长度为z。
- 当快、慢指针相遇时,证明链表有环。
- slow = x + y,fast = x + y + n(y + z)
- 2(x + y) = x + y + n(y + z)
- x + y = n(y + z)
- x = n(y + z) - y = (n - 1)(y + z) + z
- n = 1时,x = z,即当头节点和相遇点一起向前走,二者指向的节点相等时,该节点为入环的第一个节点。
var detectCycle = function(head) {
var fast = head;
var slow = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
var i = head;
var j = fast;
while(i!= j){
i = i.next;
j = j.next;
}
return i;
}
}
return null;
};
35 合并两个有序链表
- 哨兵节点:该节点无意义,从第2个节点开始才保存真正有意义的信息。具有哨兵节点的链表不需要单独处理输入头节点为null的情况。
- 比较两个链表的大小,val较小的节点,先链接到合并链表中。
- 当其中一个链表遍历完之后,结束循环,将另一个链表全部连接到合并链表中。
var mergeTwoLists = function(list1, list2) {
var newNode = new ListNode();
var cur = newNode;
while(list1 != null && list2 != null){
if(list1.val < list2.val){
cur.next = list1;
list1 = list1.next;
}
else{
cur.next = list2;
list2 = list2.next;
}
cur = cur.next;
}
if(list1 != null){
cur.next = list1;
}
if(list2 != null){
cur.next = list2;
}
return newNode.next;
};