刷题学框架,刷题学思想.跟着labuladong刷链表。
labuladong链接:labuladong代码小抄
刷题插件链接(来源labuladong公众号):
链接:https://pan.baidu.com/s/1glrZjyFCG4bXual3gzTvvw
提取码:un2k
比较两个链表当前值的大小,选择小的,连接到p的后面。当有一个链表空了的时候,就把另一个链表都连接到p后面。
var mergeTwoLists = function(list1, list2) {
var margin = new ListNode()
var p = margin
while(list1!=null && list2!=null){
if(list1.val < list2.val){
p.next = list1
list1 = list1.next
}
else{
p.next = list2
list2 = list2.next
}
p = p.next
}
if(list1 == null){
p.next = list2
}
else{
p.next = list1
}
return margin.next
};
labuladong中给出的Java代码用的是优先队列,JS中没有这种结构(也可能是我不知道),因此我使用的是先排序,再构造的方法,代码很好理解,如下:
var mergeKLists = function(lists) {
var margin = new ListNode()
var p = margin
var arr = []
for(list of lists){
while(list != null){
arr.push(list.val)
list = list.next
}
}
arr.sort(function(a,b){return a-b})
for(a of arr){
var newa = new ListNode(a)
p.next = newa
p = p.next
}
return margin.next
};
利用的双指针中的快慢指针,其中快指针先走n个结点,然后再快慢指针一起走,当快指针走到最后一个的时候,慢指针正好走到要删除结点的前一个结点,只需要对当前的结点的next=next.next即可,对于n等于链表的长度这种情况,可以直接删除第一个结点,即取head.next即可。
var removeNthFromEnd = function(head, n) {
var rNode = head
var lNode = head
for(var i=0;i<n;i++){
rNode = rNode.next
}
if(!rNode){ //处理n等于链表长度的情况
return head.next
}
while(rNode.next != null){
lNode = lNode.next
rNode = rNode.next
}
lNode.next = lNode.next.next
return head
};
使用双指针的话,可以直接让快指针每次走两个,慢指针每次走一个,这样的话当快指针走到最后一个的时候,慢指针正好在中间。(最好还是自己画图确认,因为有中间有两个数的情况)
var middleNode = function(head) {
var fast = new ListNode()
var slow = new ListNode()
fast = head,slow = head
while(fast != null && fast.next != null ){
fast = fast.next.next
slow = slow.next
}
return slow
};
var hasCycle = function(head) {
var fast = new ListNode()
var slow = new ListNode()
fast = head,slow = head
while(fast != null && fast.next != null){
fast = fast.next.next
slow = slow.next
if(slow == fast) return true
}
return false
};
var detectCycle = function(head) {
var fast = new ListNode()
var slow = new ListNode()
fast = head,slow = head
while(fast != null && fast.next != null){
fast = fast.next.next
slow = slow.next
if(slow == fast){
slow = head
while(slow != fast){
slow = slow.next
fast = fast.next
}
return fast
}
}
return null
};
可以让两个指针都走一遍两个链表,就是当A到头的时候,指针指到B上,当B走到头的时候,指针指到A上,这样两个指针可以同时到达相交点,如果没有相交点,两个指针也能同时到null,返回即可。
var getIntersectionNode = function(headA, headB) {
var nodeA = new ListNode()
var nodeB = new ListNode()
nodeA = headA,nodeB = headB
while(nodeA != nodeB){
if(nodeA == null){
nodeA = headB
}else{
nodeA = nodeA.next
}
if(nodeB == null){
nodeB = headA
}else{
nodeB = nodeB.next
}
}
return nodeA
};
var reverseList = function(head) {
if(head == null || head.next == null){
return head
}
var last = new ListNode()
last = reverseList(head.next)
head.next.next = head
head.next = null
return last
};
给出reverseList的定义,就是反转以head为头结点的链表。
这里涉及到反转前N个结点和反转区间结点的知识,我觉得我解释的没有labuladong解释的好,最好直接看原文吧,下面给出js的实现代码。
var reverseBetween = function(head, left, right) {
successor = new ListNode()
if(left == 1){
return reverseN(head,right)
}
head.next = reverseBetween(head.next,left-1,right-1)
return head
};
var reverseN = function(head,n){
if(n == 1){
successor = head.next
return head
}
var last = new ListNode()
last = reverseN(head.next,n-1)
head.next.next = head
head.next = successor
return last
}
var reverse = function(head,b){
var pre = new ListNode()
var cur = new ListNode()
var nxt = new ListNode()
pre = null
cur = head
nxt = head
while(cur != b){
nxt = cur.next
cur.next = pre
pre = cur
cur = nxt
}
return pre
}
var reverseKGroup = function(head, k) {
if(head == null){
return null
}
var a = new ListNode()
var b = new ListNode()
a = head
b = head
for(var i=0;i<k;i++){
if(b == null){
return head
}
b = b.next
}
var newHead = new ListNode()
newHead = reverse(a,b)
a.next = reverseKGroup(b,k)
return newHead
};
最直接的方案就是把链表反转,然后逐个比较;但这里我们使用双指针的方法,先找到链表终点,再把后半部分反转,与前半部分比较。
var isPalindrome = function(head) {
var slow = new ListNode()
var fast = new ListNode()
slow = head
fast = head
while(fast != null && fast.next!=null){
slow = slow.next
fast = fast.next.next
}
if(fast != null){
slow = slow.next
}
var left = new ListNode()
var right = new ListNode()
left = head
right = reverse(slow)
while(right != null){
if(left.val != right.val){
return false
}
left = left.next
right = right.next
}
return true
};
var reverse = function(head){
var pre = new ListNode()
var cen = new ListNode()
pre = null
cen = head
while(cen != null){
var nxt = new ListNode()
nxt = cen.next
cen.next = pre
pre = cen
cen = nxt
}
return pre
}