zoukankan      html  css  js  c++  java
  • Linked List 链表

    1. 链表,常见的有单链表,双向链表,循环链表

    2. 双向链表是常见的空间换时间的策略

    3. 淘汰缓存的做法一般有几个,一般用链表结构,常见的策略有三种:先进先出策略 FIFO(First In,First Out)、最少使用策略 LFU(Least Frequently Used)、最近最少使用策略 LRU(Least Recently Used)。

    链表定义
    function ListNode(val) {
      this.val = val;
      this.next = null;
    }
     
    4. 常见的链表操作:
    链表反转
    链表中环的检测
    两个有序链表合并
    删除链表倒数第n个节点
    求链表的中间节点
     
    5. 合并多个链表
    function ListNode(val) {
      this.val = val;
      this.next = null;
    }
    
    // way1 先找出最小,同时构造
    var mergeKLists = function (lists) {
      if (lists == null || lists.length <= 1) {
        return lists;
      }
    
      let res = null;
      let tail = null;
    
      while (true) {
        let isAllNull = true;
        let curMin = Infinity;
        let curMinIndex = 0;
        for (let i = 0; i < lists.length; i++) {
          if (lists[i] && curMin > lists[i].val) {
            curMin = lists[i].val;
            curMinIndex = i;
          }
    
          if (lists[i]) {
            isAllNull = false;
          }
        }
    
        if (lists[curMinIndex]) {
          lists[curMinIndex] = lists[curMinIndex].next;
        }
    
        if (isAllNull) {
          break;
        }
    
        if (!res) {
          res = {};
          res.val = curMin;
          res.next = null;
        } else {
          let node = new ListNode(curMin);
          if (res.next === null) {
            res.next = node;
          } else {
            tail.next = node;
          }
          tail = node;
        }
      }
    
      return res;
    };
    
    var node1 = new ListNode(1);
    var node3 = new ListNode(3);
    node1.next = node3;
    
    var node2 = new ListNode(2);
    var node4 = new ListNode(4);
    var node5 = new ListNode(5);
    node2.next = node4;
    node4.next = node5;
    
    console.log(mergeKLists([node1, node2]));
    
    //way2 先合并,排序,最后生成
    var mergeKLists = function (lists) {
      if (!lists || lists.length == 0) return null;
      let arr = [];
      debugger;
      let res = new ListNode(0);
      lists.forEach(list => {
        let cur = list;
        while (cur) {
          arr.push(cur.val);
          cur = cur.next;
        }
      });
      let cur = res;
      arr
        .sort((a, b) => a - b)
        .forEach(val => {
          let node = new ListNode(val);
          cur.next = node;
          cur = cur.next;
        });
      return res.next;
    };

    6. 检测链表是否有环?

    a. 散列表记录

    var hasCycle = function(head) {
        let vistedSet = new Set();
        while(head != null){
            if(vistedSet.has(head.val)){
                return true;
            }else{
                vistedSet.add(head.val);
                head = head.next;
            }
        }
    
        return false;
    };

    b. 快指针一次走2步,慢指针一次走一步,如果慢能在某个时刻追到快指针,就说明有环,如果快指针走到了null,说明没有环。

    var hasCycle = (head) => {
      let fastP = head;
      let slowP = head;
      while (fastP) {                         // 快指针指向真实节点
        if (fastP.next == null) return false; // 如果下一个为null,说明没有环
        slowP = slowP.next;                   // 慢的走一步
        fastP = fastP.next.next;              // 快的走两步
        if (slowP == fastP) return true;      // 快慢指针相遇,有环
      }
      return false;                           // fastP指向null了,也始终不相遇
    }
  • 相关阅读:
    js变量的作用域问题
    HTML网页公用头部与尾部的一些方法
    拖动对象ondrag
    子div设置float后导致父div无法自动撑开的问题
    js像素运算问题
    js自动轮播图片的两种循环方法(原创)
    display:none显示和隐藏
    Linux shell脚本基础学习详细介绍(完整版)一
    java技术思维导图(转载)
    VIM编辑命令的技巧
  • 原文地址:https://www.cnblogs.com/roy1/p/13531193.html
Copyright © 2011-2022 走看看