leetcode链表相关题目总结

leetCode 141环形链表:判断一个链表是否存在环

  1. 把每一项都做一个标记_invited,如果存在环,那么就一定会访问到_invited
var hasCycle = function (head) {
  if (!head) return false
  while (head.next) {
    if (head.next._invited) return true
    else {
      head = head.next
      head._invited = true
    }
  }
  return false
};

// 执行用时:72 ms
// 内存消耗:43.7 MB

  1. 设置快慢指针,慢指针走一步,快指针走两步(这里需要注意一点,快慢指针的设置一定要保证他们会相遇,当然也是存在环的时候)
var hasCycle = function (head) {
  let fast = head,
    slow = head;
  while (fast && slow && fast.next) {
    slow = slow.next
    fast = fast.next.next
    if (slow === fast) return true
  }
  return false
};

// 执行用时:68 ms
// 内存消耗:43.9 MB
  1. 使用set集合的自动判重能力
var hasCycle = function(head) {
    let set = new Set()
    set.add(head)
    while(head && head.next){
        head = head.next
        if(set.has(head)) return true
       else set.add(head)
    }
    return false
};

// 执行用时:60 ms
// 内存消耗:44.5 MB

方法2的双指针形式leetCode里面比较流行

leetCode206:反转链表

  1. 使用递归的方式
  var reverseList = function (head) {
    if (!head) return null
    let reverseList;
    let recursion = function (head) {
      if (head.next) return recursion(head.next).next = head
        else return reverseList = head
    }
    let lastIndex = recursion(head)
    lastIndex.next = null
    return reverseList
  };
  1. 使用循环的方式:这是leetCode的官方方法。
    我们举个例子,假如之前是这样的 1 -> 2 -> 3 -> null,那么反转之后就应该是 3 -> 2 -> 1 -> null,这里面解法的过程是这样的:

(1)let next = cur.next;: let next = 2 -> 3 -> null
(2)cur.next = prev;: cur = { value:1, next:null }
(3)prev = cur;: prev = { value:1, next:null }
(4)cur = next: cur = 2 -> 3 -> null

(1)let next = cur.next;: let next = 3 -> null
(2)cur.next = prev;: cur = { value:2, next: { value:1, next:null } } = { value:2, next: prev }
(3)prev = cur;: prev = { value:2, next: { value:1, next:null } }
(4)cur = next: cur = 3 -> null

(1)let next = cur.next;: let next = null
(2)cur.next = prev;: cur = { value:3, next: { value:2, next: { value:1, next:null } } } = { value:3, next: prev }
(3)prev = cur;: prev = { value:3, next: { value:2, next: { value:1, next:null } } } = cur
(4)cur = next: cur = null

cur = null 循环结束,完成反转

  var reverseList = function (head) {
    let prev = null;
    let cur = head;
    while(cur){
        let next = cur.next;
        cur.next = prev;
        prev = cur;
        cur = next
    }
    return prev
  };
  1. 使用递归方式

递归方式1:
循环的这种方式其实还是是从第一层逐渐向内层进行反转,而这种递归的方式是从最里面,逐渐向外面一次反转,这也是leetCode的官方方法。
有人可能会感觉递归里面的第一句是不是有一点冗余,既然head.next == null,那么head一定有值,那么head == null一定不成立,其实不然head == null判断的是一开始刚刚进来的状态也就是reverseList(null)这种情况。
再来看看newHead返回的作用,第一次返回的newHead其实是尾部,也就是反转之后的头部。

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

递归方式2:

这种方式和循环那种方式的解法基本一样,就不赘述了。

  let prev = null;
  let reverseFn = (head) => {
    if (!head) return
    let next = head.next
    head.next = prev
    prev = head
    reverseFn(next)
  }
  reverseFn(head)
  return prev
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值