算法题汇总

135 阅读2分钟

1,两数相加

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

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

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

image.png

1,首先实现一个链表节点类,如下:

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 arrToList(arr: number[]) {
  const head = new ListNode();
  let temp = head;
  arr.forEach((item) => {
    temp.next = new ListNode(item);
    temp = temp.next;
  });
  return head.next;
}

链表相加函数:

function addTwoNumbers(
  l1: ListNode | null,
  l2: ListNode | null
): ListNode | null {
  const newListNode = new ListNode();

  let cur = newListNode;
  let forward = 0;

  while (l1 || l2 || forward) {
    const firstNum = l1 ? l1.val : 0;
    const secondNum = l2 ? l2.val : 0;
    const sum = firstNum + secondNum + forward;
    const remainder = sum % 10;
    forward = sum >= 10 ? 1 : 0;
    cur.next = new ListNode(remainder);
    cur = cur.next;
    l1 = l1 ? l1.next : null;
    l2 = l2 ? l2.next : null;
  }
  return newListNode.next;
}

具体调试代码链接请看:stackblitz.com/edit/typesc…

2,三数相加为0

题目描述如下题目

image.png

用到的方法是排序+双指针,首先将数组由小到大进行排序,然后针对a进行遍历,b和c作为双指针进行移动,左指针向右移动,右指针向左移动,注意边界条件即可,代码如下:

  const set = new Set<number[]>();
  const len = nums.length;
  // 排序
  nums.sort((a, b) => a - b);

  for (let i = 0; i < len; i++) {
     // 遍历,如果a都大于0了。那么直接返回
    if (nums[i] > 0) break;
    // 过滤掉重复的数据
    if (i > 0 && nums[i] === nums[i - 1]) continue;
    let left = i + 1;
    let right = len - 1;
    while (left < right) {
      // 指针进行移动
      if (nums[i] + nums[left] + nums[right] === 0) {
        set.add([nums[i], nums[left], nums[right]]);
        // 指针左右移动
        left++;
        right--;
        // 去除重复的数据
        while (left < right && nums[left] === nums[left - 1]) left++;
        while (left < right && nums[right] === nums[right + 1]) right--;
      } else if (nums[i] + nums[left] + nums[right] < 0) {
        left++;
      } else {
        right--;
      }
    }
  }
  return Array.from(set);
}

3,最接近的三数之和

题目描述如下:

image.png

此题与上述第二题,三数之和非常类似,也可以用上述描述的双指针方法来做,代码如下:

function threeSumClosest(nums: number[], target: number): number {
  const len = nums.length;
  nums.sort((a, b) => a - b);
  // 存储最好的结果
  let current = 100000;
  for (let i = 0; i < len; i++) {
    // 去除重复的数据
    if (i > 0 && nums[i] === nums[i - 1]) continue;
    let left = i + 1;
    let right = len - 1;
    // 双指针移动
    while (left < right) {
      const sum = nums[left] + nums[right] + nums[i];
      if (sum === target) {
        // 如果等于目标值了,直接返回
        return sum;
      }
      if (Math.abs(current - target) > Math.abs(sum - target)) {
        // 判断是否比原有的值更接近目标值
        current = sum;
      }

      if (sum - target > 0) {
        right = right - 1;
        // 右指针移动,同时去除重复的数据
        while (left < right && nums[right] === nums[right + 1]) right--;
      } else {
        left = left + 1;
        // 左指针移动,同时去除重复数据
        while (left < right && nums[left - 1] === nums[left]) left++;
      }
    }
  }
  return current;
}