我的刷题笔记二-leetcode

216 阅读1分钟

21. 合并两个有序链表

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

merge_ex1.jpg

输入: l1 = [1,2,4], l2 = [1,3,4]
输出: [1,1,2,3,4,4]
输入: l1 = [], l2 = []
输出: []
输入: l1 = [], l2 = [0]
输出: [0]
// 归并
 function ListNode(val, next) {
    this.val = (val===undefined ? 0 : val)
   this.next = (next===undefined ? null : next)
 }
 
/**
 * @param {ListNode} list1
 * @param {ListNode} list2
 * @return {ListNode}
 */
var mergeTwoLists = function(list1, list2) {
  let dummy = new ListNode(0);
  let current = dummy;
  while(list1 && list2) {
      if(list1.val <= list2.val) {
          current.next = list1;
          list1 = list1.next;
          current = current.next;
      } else {
          current.next = list2;
          list2 = list2.next;
          current = current.next;
      }
  }
  if(!list1) current.next = list2;
  if(!list2) current.next = list1;
  return dummy.next
};
  function ListNode(val, next) {
     this.val = (val===undefined ? 0 : val)
     this.next = (next===undefined ? null : next)
 }
/**
 * @param {ListNode} list1
 * @param {ListNode} list2
 * @return {ListNode}
 */
var mergeTwoLists = function(list1, list2) {
  // 递归
  // 终止条件 !list1,!list2 分别返回list2,list1
  if(!list1) return list2;
  if(!list2) return list1;

  if(list1.val <= list2.val) {
      list1.next = mergeTwoLists(list1.next,list2)
      return list1
  } else {
      list2.next = mergeTwoLists(list2.next,list1)
      return list2
  }
};

22. 括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

输入: n = 3
输出: ["((()))","(()())","(())()","()(())","()()()"]
输入: n = 1
输出: ["()"]

leetcode22.png

/**
 * @param {number} n
 * @return {string[]}
 */
var generateParenthesis = function(n) {
  let res = [];
  function dfs(leftBracket,rightBracket,str) {
    // 当左括号和右括号的都添加完,全部匹配为0时,说明要结束
      if(leftBracket === 0 && rightBracket === 0) {
          res.push(str)
      }
    // 添加左括号
      if(leftBracket > 0) {
          dfs(leftBracket - 1, rightBracket, str+'(')
      }
      // leftBracket < rightBracket,添加右括号
      if(leftBracket < rightBracket ) {
          dfs(leftBracket, rightBracket - 1, str+')')
      }
  }
  dfs(n,n,'') // 初始
  return res;
};

23. 合并K个升序链表

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
  1->4->5,
  1->3->4,
  2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
输入: lists = []
输出: []
输入: lists = [[]]
输出: []
  function ListNode(val, next) {
     this.val = (val===undefined ? 0 : val)
     this.next = (next===undefined ? null : next)
 }
 
/**
 * @param {ListNode[]} lists
 * @return {ListNode}
 */
var mergeKLists = function(lists) {
  let arr = [];  // 将值全部push到数组,然后循坏形成链表
  for(let i = 0 ; i< lists.length; i ++) {
      while(lists[i]) {
          arr.push(lists[i].val);
          lists[i] = lists[i].next;
      }
  };
  arr.sort((a,b) => a - b);  // 升序
  let dunmy  = new ListNode(0);
  let current = dunmy;
  for(let j = 0; j< arr.length; j++) {
      let node = new ListNode(arr[j]);
      current.next = node;
      current = current.next;
  }
  return dunmy.next
};

24. 两两交换链表中的节点

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

swap_ex1.jpg

输入: head = [1,2,3,4]
输出: [2,1,4,3]
输入: head = []
输出: []
  function ListNode(val, next) {
      this.val = (val===undefined ? 0 : val)
      this.next = (next===undefined ? null : next)
  }
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
var swapPairs = function(head) {
  // 思路  通过索引进行比较,且存一个临时节点交换两个节点
  let current = head;
  let index = 0; // 索引
  let temp = new ListNode(null);
  while(current) {
    if(index % 2 === 0) {  // 两两交换的死一个节点
        temp.val = current.val;
        if(current.next) { // 存在链表长度为奇数,最后一个节点指向null
            current.val = current.next.val;
        }
    } else {
        current.val = temp.val;
    }
      index ++;
      current = current.next;
  }
  return head;
};

25. K 个一组翻转链表 -未理解

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

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

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

1.jpg

输入: head = [1,2,3,4,5], k = 2
输出: [2,1,4,3,5]

2.jpg

输入: head = [1,2,3,4,5], k = 3
输出: [3,2,1,4,5]
  function ListNode(val, next) {
      this.val = (val===undefined ? 0 : val)
    this.next = (next===undefined ? null : next)
  }
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
var reverseKGroup = function(head, k) {

    if(k === 1) return head; // 只有一个节点
    function reverse(head,k) {
        if(head === null || head.next === null) return head;

        let pre = head;
        let next = head.next;
        let count = k;

        while(count && next) {
            count --;
            next.pre = pre; // 指向前一个节点
            pre = pre.next;  // 指针向后走
            next = next.next;
        }

        if( count ) return head;  // count不为0,说明不够k个一组翻转

        const nextHead = next;
        const vhead = new ListNode(0);
        next = pre;
        pre = head;
        vhead.next = next;
        
        while(next !== pre) {
            next.next = next.pre;
            next = next.pre;
        }
        next.next = reverse(nextHead,k)
        return vhead.next
    }

    return reverse(head,k - 1);

};

26. 删除有序数组中的重复项

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。

将最终结果插入 nums 的前 k 个位置后返回 k 。

输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
/**
 * @param {number[]} nums
 * @return {number}
 */
var removeDuplicates = function(nums) {
  for(let i = 0;i< nums.length;i++) {
      if(nums[i] === nums[i + 1]) {
          nums.splice(i, 1);
          i--
      }
  }
  return nums.length
};
var removeDuplicates = function(nums) {
   let k = 0;
   for(let i = 0;i<nums.length;i++) {
       if(nums[i] !== nums[k]) {
           k++;
           nums[k] = nums[i]; // 原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 
       }
   }
   return k + 1;
};

27. 移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案
输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]
解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。
var removeElement = function(nums, val) {
   for(let i = 0;i< nums.length;i++) {
      if(nums[i] === val) {
          nums.splice(i, 1);
          i--
      }
  }
  return nums.length
};
/**
 * @param {number[]} nums
 * @param {number} val
 * @return {number}
 */
var removeElement = function(nums, val) {
   let k = 0;
   for(let i = 0;i<nums.length;i++) {
       if(nums[i] !== val) {
           nums[k] = nums[i]; 
            k++;
       }
   }
   return k;
};

28. 找出字符串中第一个匹配项的下标

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回  -1 。

输入:haystack = "sadbutsad", needle = "sad"
输出:0
解释:"sad" 在下标 0 和 6 处匹配。
第一个匹配项的下标是 0 ,所以返回 0 。
输入:haystack = "leetcode", needle = "leeto"
输出:-1
解释:"leeto" 没有在 "leetcode" 中出现,所以返回 -1
/**
 * @param {string} haystack
 * @param {string} needle
 * @return {number}
 */
var strStr = function(haystack, needle) {
  return haystack.indexOf(needle);
};

29. 两数相除

给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。

返回被除数 dividend 除以除数 divisor 得到的商。

整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2

输入: dividend = 10, divisor = 3
输出: 3
解释: 10/3 = truncate(3.33333..) = truncate(3) = 3
输入: dividend = 7, divisor = -3
输出: -2
解释: 7/-3 = truncate(-2.33333..) = -2
提示:

被除数和除数均为 32 位有符号整数。
除数不为 0。
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231,  231 − 1]。本题中,如果除法结果溢出,则返回 231 − 1
/**
 * @param {number} dividend
 * @param {number} divisor
 * @return {number}
 */
var divide = function(dividend, divisor) {
   if(divide === 0) return;
   const res = parseInt(dividend / divisor);
   if(res > Math.pow(2, 31) - 1)  return Math.pow(2, 31) -1;
   if(res < - Math.pow(2, 31))  return -Math.pow(2, 31);
   return res
};