链表:数组相关

2021-06-29 每日一题 LeetCode

# 0002. 两数相加 (opens new window)

题目

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

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

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

示例 1:

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
1
2
3

示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]
1
2

示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
1
2

提示:

  • 每个链表中的节点数在范围 [1, 100]
  • 0 <= Node.val <= 9
  • 题目数据保证列表表示的数字不含前导零

解析

按位模拟加法,注意循环条件不要忘记 || sum

代码

    # 0021. 合并两个有序链表 (opens new window)

    题目

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

    示例 1:

    输入:l1 = [1,2,4], l2 = [1,3,4]
    输出:[1,1,2,3,4,4]
    
    1
    2

    示例 2:

    输入:l1 = [], l2 = []
    输出:[]
    
    1
    2

    示例 3:

    输入:l1 = [], l2 = [0]
    输出:[0]
    
    1
    2

    提示:

    • 两个链表的节点数目范围是 [0, 50]
    • -100 <= Node.val <= 100
    • l1l2 均按 非递减顺序 排列

    解析

    同时遍历两个链表,从中选取较小的元素添加到结果链表,直至两个链表都遍历完成。

    代码

      # 0147. 对链表进行插入排序 (opens new window)

      题目

      给定单个链表的头 head ,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。

      解析

      定义一个虚拟头结点,用于存储已排序列表,遍历原始链表,每遇到一个结点,就将其插入到已排序链表中,最后返回虚拟头结点的下一个结点即可。

      代码

      /**
       * Definition for singly-linked list.
       * struct ListNode {
       *     int val;
       *     ListNode *next;
       *     ListNode() : val(0), next(nullptr) {}
       *     ListNode(int x) : val(x), next(nullptr) {}
       *     ListNode(int x, ListNode *next) : val(x), next(next) {}
       * };
       */
      class Solution {
      public:
          ListNode* insertionSortList(ListNode* head) {
              ListNode *dummy = new ListNode(0), *cur = head;
              while (cur) {
                  ListNode *prev = dummy, *next = cur->next;
                  while (prev->next && prev->next->val <= cur->val) {
                      prev = prev->next;
                  }
                  cur->next = prev->next;
                  prev->next = cur;
                  cur = next;
              }
              return dummy->next;
          }
      };
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26

      # 0148. 排序链表 (opens new window)

      题目

      给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

      进阶:你可以在 O(nlogn) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?

      解析

      由于题目要求时间复杂度为 O(nlogn),空间复杂度为 O(1),所以需要采用自底向上的归并排序。

      代码

      /**
       * Definition for singly-linked list.
       * struct ListNode {
       *     int val;
       *     ListNode *next;
       *     ListNode() : val(0), next(nullptr) {}
       *     ListNode(int x) : val(x), next(nullptr) {}
       *     ListNode(int x, ListNode *next) : val(x), next(next) {}
       * };
       */
      class Solution {
      public:
          ListNode* sortList(ListNode* head) {
              int n = 0;
              for (ListNode* cur = head; cur; cur = cur->next) n++;
      
              for (int i = 1; i < n; i *= 2) {
                  ListNode *dummy = new ListNode(0), *cur = dummy;
      
                  int cnt = ceil(1.0 * n / (2 * i));
                  while (cnt--) {
                      ListNode *p = head, *q = head;
                      for (int j = 0; j < i && q; j++) q = q->next;
                      
                      ListNode *next = q;
                      for (int j = 0; j < i && next; j++) next = next->next;
      
                      int l = 0, r = 0;
                      while (l < i && r < i && p && q) {
                          if (p->val <= q->val) cur = cur->next = p, p = p->next, l++;
                          else cur = cur->next = q, q = q->next, r++;
                      }
                      while (l < i && p) cur = cur->next = p, p = p->next, l++;
                      while (r < i && q) cur = cur->next = q, q = q->next, r++;
      
                      head = next;
                  }
                  cur->next = nullptr;
                  head = dummy->next;
              }
              return head;
          }
      };
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43

      # 0160. 相交链表 (opens new window)

      题目

      给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

      解析

      走到尽头见不到你,于是走过你来时的路,等到相遇时才发现,你也走过我来时的路。—— LeetCode 评论区

      代码

      /**
       * Definition for singly-linked list.
       * struct ListNode {
       *     int val;
       *     ListNode *next;
       *     ListNode(int x) : val(x), next(NULL) {}
       * };
       */
      class Solution {
      public:
          ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
              ListNode* pA = headA;
              ListNode* pB = headB;
              while (pA != pB) {
                  pA = pA ? pA->next : headB;
                  pB = pB ? pB->next : headA;
              }
              return pA;
          }
      };
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20

      # 0369. 给单链表加一 (opens new window)

      题目

      用一个 非空 单链表来表示一个非负整数,然后将这个整数加一。

      你可以假设这个整数除了 0 本身,没有任何前导的 0。

      这个整数的各个数位按照 高位在链表头部、低位在链表尾部 的顺序排列。

      解析

      找出最靠右的不是 9 的数字,将该数字加 1。然后将该数字之后所有的 9 改成 0。

      注意

      最后返回头结点时需要判断 dummy 结点是否被赋值,即:999 + 1 = 1000 会导致链表长度改变。

      代码

      /**
       * Definition for singly-linked list.
       * struct ListNode {
       *     int val;
       *     ListNode *next;
       *     ListNode() : val(0), next(nullptr) {}
       *     ListNode(int x) : val(x), next(nullptr) {}
       *     ListNode(int x, ListNode *next) : val(x), next(next) {}
       * };
       */
      class Solution {
      public:
          ListNode* plusOne(ListNode* head) {
              ListNode* dummy = new ListNode(0);
              dummy->next = head;
      
              ListNode* lastNotNine = dummy;
              ListNode* cur = dummy;
              while (cur) {
                  if (cur->val != 9) {
                      lastNotNine = cur;
                  }
                  cur = cur->next;
              }
      
              ++lastNotNine->val;
              cur = lastNotNine->next;
              while (cur) {
                  cur->val = 0;
                  cur = cur->next;
              }
      
              return dummy->val ? dummy : head;
          }
      };
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      Last Updated: 2023-01-28 4:31:25