算法系列---链表

129 阅读2分钟

考点系列必须会的三点:

1.遍历

2.删除

3.插入

考点解法:

快慢指针法

双指针法

递归方法

set方法

虚拟指针法

考点系列一:反转系列:

1.反转链表

2.局部反转链表

3.K个一组翻转链表

解法:

核心点:

整个链表的反转的源码背过最好,

 var cur = head;    
 var pre = null;   
 while(cur){        
  var temp = cur.next;       
   cur.next= pre;        
  pre = cur;        
  cur = temp;   
 }    
return pre;

之后的2,或是3无非就是链表的删除与拼接而已。

删除过程的模板如下,例如局部范围的删除:

 var newNode = new ListNode();   
newNode.next = head;   
var preLeftNode = newNode;   
i=1;  
while(preLeftNode&&i<left){       
 preLeftNode = preLeftNode.next;      
 i++;   
}   
var rightNode = preLeftNode.next   
var k=1;   
while(rightNode&&(k<right-left+1)){       
  rightNode = rightNode.next;       
  k++;   
}  
 var leftNode = preLeftNode.next;   
var temp =rightNode.next;   
preLeftNode.next = null;   
rightNode.next = null;   
preLeftNode.next = reverse(leftNode)    
leftNode.next =  temp   
return newNode.next;

删除left-right之间范围的节点,因为存在删除的边界节点所以要用创建虚拟节点的方法进行解决。

其次删除过程中要保存前节点以及right节点之后的节点。替换的时候采用穿针引线的方法。

其次k的选值都要采用i=1一般i=0的时候处理的是链表的长度。

考点系列二:环形系列

1.环形链表

2.环形链表的起始位置

解法:标准的快慢指针法&hashMap法

set集合大法

 var setMap = new Set();    
var temp = head;
   while(temp){        
     if(setMap.has(temp)){  
          return temp;   
     }       
 setMap.add(temp);       
 temp = temp.next;   
 }    
return null;

快慢指针法

 if(head==null||head.next==null){       
   return null;   
 }   
 var slow = head;    
var fast = head;    
while(fast&&fast.next){       
  fast = fast.next.next;        
 slow = slow.next;        
if(fast==slow){           
  break;       
  }    
}
    
if(fast!=slow){     
   return null;  
  }     
fast = head;     
while(slow!=fast){         
fast = fast.next;         
slow = slow.next;     
}    
return slow;

考点系列三:排序系列&合并链表

1.给链表排序

2.有序链表的合并

3.给链表进行插入排序

3.合并两个链表

4.合并K个升序链表

合并两个链表

解法:虚拟指针法

var mergeInBetween = function(list1, a, b, list2) {    
var newHead= new ListNode();   
 newHead.next = list1;    
var temp = newHead;    
var i=0;   
 while(temp.next&&i<a){    
    temp = temp.next;        
  i++;    
}    
var k=0;   
var obj = temp;   
 while(obj&&k<(b-a+1)){       
 obj = obj.next;        
k++;    
}
var left = temp;    
var right = obj.next;    
temp.next = null;    
obj.next = null;   
 var aa = list2;    
while(aa.next){        
 aa = aa.next;    
}    
left.next = list2;    
if(aa){         
 aa.next = right;   
 }      
 return newHead.next
};

合并K个升序链表

var mergeKLists = function(lists) {
    if(!lists.length){
        return null;
    }
    var i=1;
    var temp = lists[0];
    while(i<lists.length){
        temp = mergLinkTwo(temp,lists[i])
        i++;
    }
    return temp;
};


var mergLinkTwo = function(left,right){
   var dumpy = new ListNode();
    var p = dumpy;
    while(left&&right){
        if(left.val<=right.val){
            p.next = left;
            left = left.next;
        } else {
            p.next = right;
            right = right.next;
        }
        p = p.next;
    }
    if(left){
        p.next = left;
    }
    if(right){
        p.next = right;
    }
    return dumpy.next;
}

考点系列四:链表相交系列

1.链表相交系列

解法:双指针法

var lenA = getLength(headA);    
var lenB = getLength(headB);    
while(lenA!=lenB){       
 if(lenA>lenB){         
   headA = headA.next;    
  lenA--        
} else {         
   headB = headB.next;     
   lenB--     
   }   
 }    
while(headA){       
 if(headA==headB){      
      return headB;       
 }        
headB = headB.next;        
headA = headA.next;    
}    
return null
};
var getLength = function(head){   
 var i=0;    
while(head){       
 head = head.next;       
 i++;    
}    
return i;

考点系列五:删除元素

1.移除重复节点

2.删除排序链表中的重复元素只保留一个

3.删除排序链表中的重复元素一个都不保留

4.删除链表的节点

5.删除链表的倒数第 N 个结点

考点系列六:分割链表

1.分割链表

2.分隔链表

核心思想:双指针解法

var partition = function(head, x) {
    var temp = head;    
var minNode = new ListNode(0);    
var maxNode = new ListNode(0);    
var minHead = minNode;    
var maxHead = maxNode;    
while(temp){        
if(temp.val >= x){          
maxNode.next = temp;         
maxNode = maxNode.next;       
 } else {           
minNode.next = temp;           
minNode = minNode.next;        
}        
temp = temp.next;    
}    
maxNode.next = null;    
minNode.next = maxHead.next;      
 return minHead.next
};

分隔列表:核心在于中间断接再连的过程

var splitListToParts = function(root, k) {   
 var length = getLen(root);    
var list =[];    
if(k>length){
for (i=0;i<k;i++){        
if(root){            
list[i] = root;            
var temp = root.next;            
root.next = null;            
root = temp;         
} else {             
list[i] = null;        
 }      
}    
} else {       
 var count = Math.floor(length/k)        
var reminder = length%k;       
for(var i=0;i<k;i++){          
list[i] = root;          
for(var j=0;j<count+(reminder>0?1:0);j++){             
root = root.next;         
 }          
var temp = root.next;          
root.next = null;          
root = temp;        
}    }    
return list;  
};
var getLen = function(head){    
var i=0;   
var temp = head;
while(temp){        
temp = temp.next        
i++    
}   
return i;
}

考点系列七:回文链表相关

1.判断链表是否是回文链表

解法核心思想:快慢指针。

var isPalindrome = function(head) {   
 var fast = head;    
var slow = head;   
 while(fast&&slow&&fast.next){        
fast = fast.next.next;        
slow = slow.next;    
}    
if(fast){        
slow = slow.next;    
}    
var slow = trase(slow);    
var pre = head;    
while(slow){        
if(pre.val!=slow.val){            
return false        }        
pre = pre.next;        
slow = slow.next;   
 }    
return true;};
var trase = function(head){    
var cur = head;    
var pre= null;    
while(cur){     
 var   temp = cur.next;        
 cur.next= pre;        
 pre = cur;        
 cur = temp;    
}    
return pre;
}

考点八:任意链表节点交换

1.交换链表中的节点

2.两两交换链表中的节点

解法核心:递归

var swapPairs = function(head) {    
if(head==null||head.next==null){        
return head;    
}   
 var newHead = head.next;    
head.next = swapPairs(head.next.next);    
newHead.next = head;    
return newHead;
};

考点系列九:两数相加

1.两数相加