leetcode 数组&字符串

54 阅读3分钟

数组

1、两数求和问题

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

示例:

给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]

const twoSum = function(nums, target) {
  const diffs = {}
  const len = nums.length
  for(let i=0;i<len;i++) {
    if(diffs[target-nums[i]]!==undefined) {
      return [diffs[target - nums[i]], i]
    }
    diffs[nums[i]]=i
  }
};

2、合并两个有序数组

给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。

说明: 初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。 你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。

示例:

输入: nums1 = [1,2,3,0,0,0], m = 3 nums2 = [2,5,6], n = 3 输出: [1,2,2,3,5,6]

const merge = function (nums1, m, nums2, n) {
  let i = m - 1, j = n - 1, k = m + n - 1
  while (i >= 0 && j >= 0) {
    if (nums1[i] >= nums2[j]) {
      nums1[k] = nums1[i]
      i--
      k--
    } else {
      nums1[k] = nums2[j]
      j--
      k--
    }
  }

  while (j >= 0) {
    nums1[k] = nums2[j]
    k--
    j--
  }
};

3、三数求和问题

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4], 满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]

const threeSum = function (nums) {
  let res = []
  nums = nums.sort((a, b) => {
    return a - b
  })
  const len = nums.length
  for (let i = 0; i < len - 2; i++) {
    let j = i + 1
    let k = len - 1
    if (i > 0 && nums[i] === nums[i - 1]) {
      continue
    }
    while (j < k) {
      if (nums[i] + nums[j] + nums[k] < 0) {
        j++
        while (j < k && nums[j] === nums[j - 1]) {
          j++
        }
      } else if (nums[i] + nums[j] + nums[k] > 0) {
        k--
        while (j < k && nums[k] === nums[k + 1]) {
          k--
        }
      } else {
        res.push([nums[i], nums[j], nums[k]])
        j++
        k--
        while (j < k && nums[j] === nums[j - 1]) {
          j++
        }
        while (j < k && nums[k] === nums[k + 1]) {
          k--
        }
      }
    }
  }
  return res
};

字符串

1、反转字符串

const res = str.split('').reverse().join('')

2、判断一个字符串是否是回文字符串

function isPalindrome(str) {
  const len = str.length
  for (let i = 0; i < len / 2; i++) {
    if (str[i] !== str[len - i - 1]) {
      return false
    }
  }
  return true
}

根据对称性,当然也可以直接和反转后的字符串进行比较

3、回文字符串的衍生问题

给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。

示例 1:

输入: "aba" 输出: True 示例 2: 输入: "abca" 输出: True 解释: 你可以删除c字符。 注意: 字符串只包含从 a-z 的小写字母。字符串的最大长度是50000。

const validPalindrome = function (s) {
  const len = s.length
  let i = 0, j = len - 1
  while (i < j && s[i] === s[j]) {
    i++
    j--
  }

  if (isPalindrome(i + 1, j)) {
    return true
  }

  if (isPalindrome(i, j - 1)) {
    return true
  }
  
  function isPalindrome(st, ed) {
    while (st < ed) {
      if (s[st] !== s[ed]) {
        return false
      }
      st++
      ed--
    }
    return true
  }

  return false
};

4、正则表达式问题

设计一个支持以下两种操作的数据结构:

void addWord(word) bool search(word) search(word) 可以搜索文字或正则表达式字符串,字符串只包含字母 . 或 a-z 。 . 可以表示任何一个字母。

示例:

addWord("bad") addWord("dad") addWord("mad") search("pad") -> false search("bad") -> true search(".ad") -> true search("b..") -> true

说明: 你可以假设所有单词都是由小写字母 a-z 组成的。

const WordDictionary = function () {
  this.words = {}
};

WordDictionary.prototype.addWord = function (word) {
  if (this.words[word.length]) {
    this.words[word.length].push(word)
  } else {
    this.words[word.length] = [word]
  }

};

WordDictionary.prototype.search = function (word) {
  if (!this.words[word.length]) {
    return false
  }
  const len = word.length
  if (!word.includes('.')) {
    return this.words[len].includes(word)

  }

  const reg = new RegExp(word)

  return this.words[len].some((item) => {
    return reg.test(item)
  })
};

5、字符串与数字之间的转换问题

请你来实现一个 atoi 函数,使其能将字符串转换成整数。

首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。 当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。 该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。 注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。 在任何情况下,若函数不能进行有效的转换时,请返回 0。

说明:

假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−2^31, 2^31 − 1]。如果数值超过这个范围,请返回 INT_MAX (2^31 − 1) 或 INT_MIN (−2^31) 。

示例 1:

输入: "42" 输出: 42

示例 2:

输入: " -42" 输出: -42 解释: 第一个非空白字符为 '-', 它是一个负号。 我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。

示例 3:

输入: "4193 with words" 输出: 4193 解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。

示例 4:

输入: "words and 987" 输出: 0 解释: 第一个非空字符是 'w', 但它不是数字或正、负号。 因此无法执行有效的转换。

示例 5:

输入: "-91283472332" 输出: -2147483648 解释: 数字 "-91283472332" 超过 32 位有符号整数范围。因此返回 INT_MIN (−2^31) 。

const myAtoi = function (str) {
  const reg = /\s*([-\+]?[0-9]*).*/
  const groups = str.match(reg)
  const max = Math.pow(2, 31) - 1
  const min = -max - 1
  let targetNum = 0
  if (groups) {
    targetNum = +groups[1]
    if (isNaN(targetNum)) {
      targetNum = 0
    }
  }
  if (targetNum > max) {
    return max
  } else if (targetNum < min) {
    return min
  }
  return targetNum
};