The List

简介: The List

链表


链表判环(快慢指针)


[141.环形判环]: https://leetcode.cn/problems/linked-list-cycle/


解题思想:


  • 先判断head节点是否为空


  • 再利用快慢指针来判断,如果两个指针能够相等,则有环,否则快指针首选到尾节点后判断为null,则无环


(在javascript中,return null的结果为true,在c++中,return NULL的结果为false)


var hasCycle = function(head) {
    if(head === null) return false;
    let p1 = head; 
    let p2 = head.next;
    while(p2 && p2.next) {
        if(p1 === p2) return true;
        p1 = p1.next;
        p2 = p2.next.next;
    }
    return false;
};


[142.环形链表]: https://leetcode.cn/problems/linked-list-cycle-ii/


解题思想:


  • 如果链表的头节点或者第二个节点为null,则非循环链表


  • 然后进行快慢指针的相遇,如果快指针的q.next为null或者q.next.next为null则非循环链表


  • 如果快慢指针能够相遇,则说明是循环链表


  • 要找到循环的首节点,让慢指针重新从头节点开始走,让快指针恢复成慢指针的速度


  • 当他们相遇的时候就是循环链表的首节点


var detectCycle = function(head) {
      if(head === null || head.next === null) return null;
    let p = head, q = head;
      do {
        if(q.next === null || q.next.next === null) return null;
          p = p.next
        q = q.next.next
      } while(p != q)
    p = head;
      while(p !== q) {
        p = p.next;
          q = q.next;
    }
      return p;
};


[202.快乐数]: https://leetcode.cn/problems/happy-number/


解题思想:


  • 一个数组的每个位置平方和确定,可想象成链表形式,这个节点指向下一个节点


  • 先写出对应求平方和的方法,对一个数取余并平方,然后依此求下一位的平方


  • 然后将1看作链表中的null值即可按照链表判断有无环的方式进行判断是否为快乐数


function getNext(x) {
        let z = 0;
    while(x) {
            z += (x % 10) * (x % 10);
        x = parseInt(x / 10);
        }
      return z;
    }
  var isHappy = function(n) {
        if(n === 1) return true;
      let p = n, q = n;
        do {
          if(getNext(q) === 1 || getNext(getNext(q)) === 1) return true;
            p = getNext(p);
          q = getNext(getNext(q));
        } while(p !== q);
      return false;
    };


链表反转


[206.反转链表]: https://leetcode.cn/problems/reverse-linked-list/


解题思路:


  • 利用三个节点进行迭代反转


  • 如果链表为null,则直接返回即可


  • 利用三个节点反转,pre表示反转头,cur表示未反转头,下个带反转头


      var reverseList = function(head) {
          if(head === null) return head;
          let pre = null, cur = head, p = head.next;
          while(cur) {
              cur.next = pre;
              pre = cur;
              (cur = p) && (p = p.next);
          }
          return pre;
      };


2. 利用递归反转


  • 递归从尾节点进行反转


  • 当当前head为null或者head->next为null时表示为尾节点,返回head


  • 然后递归将head->next节点指向head节点


  • 然后将head节点指向null


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


[返回倒数第K个节点]: https://leetcode.cn/problems/kth-node-from-end-of-list-lcci/


解题思路:


  • 利用前后指针


  • 先让前指针先走k-1步


  • 然后两个指针再一同走,如果前指针走到尾节点,后指针就在倒数第k个节点


    var kthToLast = function(head, k) {
          let p1 = head;
        let p2 = head;
          while(--k) {
            p1 = p1.next;
          }
        while(1) {
              if(p1.next === null) {
                  return p2.val;
              }
              p1 = p1.next;
              p2 = p2.next;
          }
      };


链表删除节点


[19.删除链表的倒数第N个结点]: https://leetcode.cn/problems/remove-nth-node-from-end-of-list/


解题思路:


  • 先创建一个虚拟头节点


  • 利用前后指针找到需要删除的节点的前一个节点


  • 将要删除的前一个节点指向被删除节点的后一个节点


  • 然后返回虚拟头节点的下一个节点


      var removeNthFromEnd = function(head, n) {
            let p = new ListNode(-1), res = p;p1 = p, p2 = p;
          p.next = head;
            while(n--) {
              p1 = p1.next;
            };
          while(1) {
                if(p1.next === null) {
                  p2.next = p2.next.next;
                    return res.next;
              }
                p1 = p1.next;
              p2 = p2.next;
            };
      };


[82.删除排序链表中重复元素]: https://leetcode.cn/problems/remove-duplicates-from-sorted-list-ii/submissions/


解题思路:


  • 创建虚拟头节点


  • 循环判断当前结点的下一个结点和下下个结点不为空,进入循环判断


  • 如果当前结点的下一个结点值等于下下个结点值,将这个值临时存储


  • 当下一个结点存在,并且这个结点等于临时存储的值时,将当前结点指向下下个结点,即删除重复元素


  • 最后返回虚拟头节点的下一个结点


        var deleteDuplicates = function(head) {
              if(head === null) return head;
            let p = new ListNode(0, head), cur = p;
              while(cur.next && cur.next.next) {
                if(cur.next.val === cur.next.next.val) {
                      let temp = cur.next.val;
                      while(cur.next && cur.next.val === temp) {
                          cur.next = cur.next.next;
                      }
                  } else {
                      cur = cur.next;
                  }
              }
              return p.next;
          };


[83.删除排序链表中的重复元素]: https://leetcode.cn/problems/remove-duplicates-from-sorted-list/


解题思路:


  • 声明头节点,并判断当前结点的下一个结点是否存在


  • 再判断当前结点值是否等于下一结点值,如果相等,就将当前结点指向下下个结点,即删除重复结点


  • 最后返回头结点


            var deleteDuplicates = function(head) {
                let p = head;
                if(head === null) return null;
                while(p.next) {
                    if(p.val === p.next.val) {
                        p.next = p.next.next;
                    } else {
                        p = p.next;
                    }
                }
                return head;
            };


  虚拟头节点:链表头地址可能发生改变
相关文章
|
24天前
|
存储 编译器 容器
list从0到1的突破
list从0到1的突破
13 0
|
3月前
|
存储 C++ 容器
【C++】list的认识与使用
【C++】list的认识与使用
|
4月前
|
存储 Java C++
【c++】list详细讲解
【c++】list详细讲解
57 5
|
4月前
|
算法 搜索推荐 C++
【C++】list的使用(下)
`C++` 中 `std::list` 的 `merge()`、`sort()` 和 `reverse()` 操作: - `merge(x)` 和 `merge(x, comp)`: 合并两个已排序的`list`,将`x`的元素按顺序插入当前`list`,`x`清空。比较可自定义。 - `sort()` 和 `sort(comp)`: 对`list`元素排序,保持等价元素相对顺序。内置排序基于稳定排序算法,速度较慢。 -reverse(): 反转`list`中元素的顺序。 这些操作不涉及元素构造/销毁,直接移动元素。注意,`sort()`不适合`std::list`,因链表结构不利于快速排序
|
4月前
|
编译器 C++ 容器
【C++】list的使用(上)
迭代器在STL中统一了访问接口,如`list`的`begin()`和`end()`。示例展示了如何使用正向和反向迭代器遍历`list`。注意`list`的迭代器不支持加减操作,只能用`++`和`--`。容器的`empty()`和`size()`用于检查状态和获取元素数。`front()`和`back()`访问首尾元素,`assign()`重载函数用于替换内容,`push_*/pop_*`管理两端元素,`insert()`插入元素,`erase()`删除元素,`resize()`调整大小,`clear()`清空容器。这些接口与`vector`和`string`类似,方便使用。
|
6月前
|
人工智能
B - Dima and To-do List
B - Dima and To-do List
33 0
|
12月前
|
存储 C++ 容器
C++ list
C++ list
|
JSON 前端开发 Java
一个 List.of 引发的“血案”
本文作者将分享一个使用List.of后掉进的坑以及爬坑的全过程,希望大家能引以为戒同时引起这样的意识:在使用新技术前先搞清楚其实现的原理。
|
缓存 编译器 C++
list的实现
list的实现
【C++】list的介绍和使用(下)
【C++】list的介绍和使用(下)
【C++】list的介绍和使用(下)