JS算法之链表中倒数第k个节点及反转链表

714 阅读2分钟

这是我参与8月更文挑战的第24天,活动详情查看:8月更文挑战

链表中倒数第k个节点

剑指Offer 22.链表中倒数第k个节点

难度:简单

输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。

例如,一个链表有6个节点,从头节点开始,它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个节点是值为4的节点。

示例:

 给定一个链表: 1->2->3->4->5, 和 k = 2.
 返回链表 4->5.

题解

法一 快慢指针法

设置p、q两个指针,让p先走k步,然后p、q一起走,直到p为null。

 /**
  * Definition for singly-linked list.
  * function ListNode(val) {
  *     this.val = val;
  *     this.next = null;
  * }
  */
 /**
  * @param {ListNode} head
  * @param {number} k
  * @return {ListNode}
  */
 var getKthFromEnd = function(head, k) {
   let p = head,q = head;
   let i = 0;
   while(p){
     if(i >= k){
       q = q.next;
     }
     p = p.next;
     i++;
   }
   return i < k ? null : q;
 };

法二 使用栈

 var getKthFromEnd = function(head,k){
   var stack = []
   var ans = []
   while(head){ // 所有节点入栈
     stack.push(head);
     head = head.next;
   }
   while(k > 0){
     ans = stack.pop();
     k--;
   }
   return ans;
 }

反转链表

剑指Offer 24.反转链表

难度:简单

定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

示例:

 输入: 1->2->3->4->5->NULL
 输出: 5->4->3->2->1->NULL

限制: 0 <= 节点个数 <= 5000

题解

法一 迭代法

在遍历链表时,将当前节点的next指针改为指向前一个节点。由于节点没有引用其前一个节点,因此必须事先存储其前一个节点。在更改引用前,还需要存储后一个节点。最后返回新的头引用。

 /**
  * Definition for singly-linked list.
  * function ListNode(val) {
  *     this.val = val;
  *     this.next = null;
  * }
  */
 /**
  * @param {ListNode} head
  * @return {ListNode}
  */
 var reverseList = function(head){
   let prev = null;
   let curr = head;
   while(curr){
     const next = curr.next;
     curr.next = prev;
     prev = curr;
     curr = next;
   }
   return prev;
 }

时间复杂度:O(n),空间复杂度O(1)

法二 递归法

假设链表为:

n1→…→nk−1→nk→nk+1→…→nm→∅

若从节点nk+1到nm已经被反转,而我们正处于nk。

n1→…→nk−1→nk→nk+1←…←n~m

我们希望nk+1的下一个节点指向nk。

所以,nk.next.next = nk。

需要注意的是n1的下一个节点必须指向∅。如果忽略这一点,链表中可能会产生环。

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

时间复杂度:O(n),n是链表的长度。需要对链表的每个节点进行反转操作。

空间复杂度:O(n),n是链表长度,空间复杂度取决于递归调用的栈空间,最多为n层。


坚持每日一练!前端小萌新一枚,希望能点个哇~