每日算法(第二十八期)

先来回顾一下上期的问题及答案:

「合并两个有序链表」(Merge Two Sorted Lists)。

题目描述:

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

示例:

输入:l1 = 1->2->4l2 = 1->3->4输出:1->1->2->3->4->4

提示:

  • 使用递归或迭代的方式都可以解决该问题。

  • 递归解法:

    • 如果 l1 为空,则返回 l2

    • 如果 l2 为空,则返回 l1

    • 比较 l1l2 的头节点的值,将较小值作为新链表的头节点。

    • 然后递归调用函数,将较小值的链表的下一个节点与另一个链表合并。

  • 迭代解法:

    • 创建一个新的链表 dummy 作为合并后的链表的哑节点,使用一个指针 current 指向 dummy

    • 比较 l1l2 的头节点的值,将较小值接在 current 的后面,并将指针向后移动。

    • 继续比较两个链表中的节点,直到其中一个链表为空。

    • 将剩余的非空链表接在 current 的后面。

    • 返回 dummy 的下一个节点作为合并后的链表的头节点。

以下是对应的 TypeScript 解答:

class ListNode {
  val: number;
  next: ListNode | null;
  constructor(val?: number, next?: ListNode | null) {
    this.val = val === undefined ? 0 : val;
    this.next = next === undefined ? null : next;
  }
}

function mergeTwoLists(l1: ListNode | null, l2: ListNode | null): ListNode | null {
  const dummy: ListNode = new ListNode();
  let current: ListNode | null = dummy;

  while (l1 && l2) {
    if (l1.val < l2.val) {
      current.next = l1;
      l1 = l1.next;
    } else {
      current.next = l2;
      l2 = l2.next;
    }
    current = current.next;
  }

  current.next = l1 || l2;

  return dummy.next;
}

解题思路:

  • 创建一个哑节点(dummy node)作为合并后的链表的头部,并使用一个指针 current 指向哑节点。

  • 比较两个链表的头节点的值,将较小值接在 current 的后面,并将指针 current 和较小值的链表的指针向后移动。

  • 继续比较两个链表中的节点,直到其中一个链表为空。

  • 将剩余的非空链表接在 current 的后面。

  • 返回哑节点的下一个

节点作为合并后的链表的头节点。

时间复杂度分析:

  • 需要遍历两个链表中的所有节点,时间复杂度为 O(N+M),其中 N 和 M 分别是两个链表的长度。

空间复杂度分析:

  • 只使用了常数级别的额外空间。

  • 空间复杂度为 O(1)。

2023年6月22日

「删除有序数组中的重复项」(Remove Duplicates from Sorted Array)。

题目描述:

给你一个有序数组 nums,请你原地删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

说明:

为了方便起见,可以忽略数组中超出新长度后面的元素。

示例:

输入:nums = [1,1,2]输出:2, nums = [1,2]解释:函数应该返回新的长度 2,并且原数组 nums 的前两个元素被修改为 1, 2。不需要考虑数组中超出新长度后面的元素。

提示:

  • 数组已经按升序排列。

  • 使用双指针的方式可以解决该问题。

  • 定义两个指针 ij,初始时都指向数组的第一个元素。

  • 比较 nums[i]nums[j] 的值:

    • 如果它们相等,则移动指针 j,继续寻找下一个不同的元素。

    • 如果它们不相等,则将 nums[j] 的值赋给 nums[i+1],并同时移动指针 ij,继续寻找下一个不同的元素。

  • 重复上述步骤,直到指针 j 达到数组的末尾。

  • 最后,返回 i+1 作为新数组的长度。

上面问题的答案会在第二天的公众号推文中公布,大家可以关注公众号:程序员每日三问,第一时间获得推送内容。

学习不打烊,充电加油只为遇到更好的自己,每天早上9点纯手工发布面试题(死磕自己,愉悦大家) 希望大家在这浮夸的程序员圈里保持冷静,每天坚持花20分钟来学习与思考,在千变万化,类库层出不穷的今天,不要等到找工作时才狂刷题,提倡每日学习。

你可能感兴趣的:(算法,链表,数据结构)