链表

快慢指针

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

单独设置一个进位carry:

class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
      ListNode head=null, tail=null;
      int carry=0;
      while(l1 !=null || l2 !=null){
          int n1 =l1!=null? l1.val:0;
          int n2=l2!=null? l2.val:0;
          int sum = n1+n2+carry;
          if(head == null){
              head = tail = new ListNode(sum%10);
          }else{
              tail.next= new ListNode(sum%10);
              tail = tail.next;
          }
          carry =sum/10;
        //更新链表
          if (l1 != null) {
                l1 = l1.next;
            }
            if (l2 != null) {
                l2 = l2.next;
            }
      }
      //处理最后一个进位
      if(carry > 0){
          tail.next = new ListNode(carry);
      }
      return head;
    }
    
}

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

解法1,递归:

解法2,迭代:

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。

构造这个链表的 深拷贝。 深拷贝应该正好由 n全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点

解法1. 节点拆分

该链表中每一个节点拆分为两个相连的节点,例如对于链表 A→B→C,我们可以将其拆分为 A→A′→B→B′→C→C′

解法2. 递归

给你单链表的头指针 head 和两个整数 leftright ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表

解法一,切断链表,然后反转,然后再接上

解法2.穿针引线

递归反转

迭代反转两个具体的节点

反转前n个节点

反转m-n之间的节点

给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

解法1,穿针引线,每次反转k个节点

解法2,构造reverseBetween方法来反转

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

解法,用快慢指针找到倒数N的位置,first比second多走N个节点。

给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字。返回 已排序的链表

解法:用set保存链表的值,判断set中是否有这个值。

给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。

解法1.闭合为环,然后再断开。

解法2。用栈。再pop出K的节点。找到要断开的位置。

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你应当 保留 两个分区中每个节点的初始相对位置。

解法,用大小两个链表,分别存储。

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。

实现 LRUCache 类:

  • LRUCache(int capacity)正整数 作为容量 capacity 初始化 LRU 缓存

  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1

  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 getput 必须以 O(1) 的平均时间复杂度运行。

解法:双向链表,每次添加或者get的时候对链表进行移动操作,用双向链表是为了方便定位和删除节点。

解法2.直接继承java中的LinkedHashMap

最后更新于

这有帮助吗?