数据结构之 链表

1. 链表 + 快慢指针:环型链表

给定一个链表,判断链表中是否有环,存在环返回true,否则返回false.

用O(1)的内存解决问题。

1. 解题思路

image-20210602134948403
image-20210602135133923

image-20210602135326453

2. 数据结构及算法思维选择
解法一:二次到达解法

数据结构: 数组

算法思维: 遍历

解法二: 追击问题解法

数据结构: 两个辅助变量

算法思维:遍历、快慢指针

3. 基本解法和编码
  1. 定义数组记录已经访问的结点
  2. 遍历链表的每个节点,并与数组中已经存放的节点依次比较:
    • 相同方法结束,返回true
    • 不同则存入最新位置,继续遍历下个节点
  3. 若next指针为null,则方法结束,返回false

细节问题:

  • 遍历链表,通过head = head.next进行迭代

  • 当且仅当此节点与容器某个节点相同返回true,其他情况返回false

const hasCycle = function(head) {
  const res = [];
  while (head) {
    if (res.includes(head)) {
      return true;
    }
    res.push(head);
    head = head.next;
  }
  return false;
};

时间复杂度:O(n^2)

4. 思考更优解
  • 证明某个节点是否第二次到达,是否可以将已遍历节点进行标记
  • 追击问题模拟实现

image-20210603085144878

5. 编码实现
var hasCycle = function(head) {
    if(head === null || head.next === null){
        return false;
    }
    let slow = head;
    let fast = head.next;
    while(fast !== null && fast.next !== null){
        if( slow === fast){
            return true;
        }
        fast = fast.next.next;
        slow = slow.next;
    }
    return false;
};
6. 变形延伸
  • 分别使用head和head.next作为链表的慢、块指针
  • 标记值法:对节点的val属性进行标记,赋一个超出合法范围的值
  • 反转指针法

延伸扩展:

  • 龟兔赛跑,追击问题
  • 地球,火星与太阳连成一线

2. 环型链表2

var detectCycle = function(head) {
    if (head === null) {
        return null;
    }
    let slow = head, fast = head;
    while (fast !== null) {
        slow = slow.next;
        if (fast.next !== null) {
            fast = fast.next.next;
        } else {
            return null;
        }
        // 相遇
        if (fast === slow) {
            let ptr = head;
            while (ptr !== slow) {
                ptr = ptr.next;
                slow = slow.next;
            }
            return ptr;
        }
    }
    return null;
}

3. 反转链表

var reverseList = function(head) {
    let pre = null;
    let current = head;
    while(current){
        let next = current.next;
        // 1. 当前节点下一个指向前一个节点
        current.next = pre;
        // 2. pre赋給current
        pre = current;
        // 3. cur赋給next
        current = next;
    }
    return pre;

};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值