第1题:两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
var twoSum = function(nums, target) {
// 暴力法
// for (let i = 0; i < nums.length; i++) {
// const index = nums.indexOf(target - nums[i])
// if (index !== -1 && index !== i) {
// return [i, index]
// }
// }
// 先遍历一次数组,用map保存 item-index的关系。
// 再遍历第二次数组,每遍历一项就判断在map中是否存在满足条件的,如果存在则返回
const map = new Map()
for (let i = 0; i < nums.length; i++) {
map.set(nums[i], i)
}
for (let j = 0; j < nums.length; j++) {
const index = map.get(target - nums[j])
// 如果index有值,并且不和j相等,则说明满足条件
if (index && index !== j) {
return [j, index]
}
}
};
第二题:无重复字符的最长子串
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
var lengthOfLongestSubstring = function(s) {
// 定义一个set表,用来记录子串
const set = new Set()
// 定义左右指针
let left = 0
let right = 0
// 定义maxLength用来保存最长子串长度
let maxLength = 0
const length = s.length
for (; left < length; left++) {
// 当右指针小于s的长度,并且set中没有right下标的字符
while (right < length && !set.has(s[right])) {
// 将s[right]保存到set中
set.add(s[right++])
}
// 比较maxLength和right - left
maxLength = Math.max(maxLength, right - left)
// 如果right === length,证明maxLength已经是最大了,不需要继续循环了。
if (right === length) break
// 如果不是,删除s[left]
// 因为如果执行该代码,证明right !== length,那么就意味着上面while循环是因为s[right]已经存在于set中
// 删除最先进入set的s[left],重新获取子串
set.delete(s[left])
}
return maxLength
};
第三题:回文数
给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。例如,121 是回文,而 123 不是。
var isPalindrome = function(x) {
// 先变成字符串
const str = String(x)
// 将字符串变成数组
const arr = str.split('')
// 翻转数组,并将数组切割成字符串判断与str是否相同
return arr.reverse().join('') === str
};
第四题:最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""
。
var longestCommonPrefix = function(strs) {
if (strs.length === 1) return strs[0]
let flag = true
let index = 0
while (flag) {
for (let i = 1; i < strs.length; i++) {
// 当字符相同
if (strs[i][index] === strs[i - 1][index]) {
continue
} else {
// 字符不相同,直接跳出循环
flag = false
break
}
}
if (flag) {
index++
// 防止字符串相同,死循环
if (index >= strs[0].length) {
flag = false
}
}
}
return strs[0].slice(0, index) === undefined ? '' : strs[0].slice(0, index)
};
第五题:有效的括号
给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。
var isValid = function(s) {
const stack = []
for (const i of s) {
if (['[', '{', '('].includes(i)) {
stack.push(i)
continue
}
switch (i) {
case ')':
if (stack[stack.length - 1] === '(') {
stack.pop()
continue
}
break
case ']':
if (stack[stack.length - 1] === '[') {
stack.pop()
continue
}
break
case '}':
if (stack[stack.length - 1] === '{') {
stack.pop()
continue
}
break
}
return false
}
if (arr.length === 0) return true
return false
};
第六题:合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例 1:
var mergeTwoLists = function(l1, l2) {
let p1 = l1
let p2 = l2
let p3 = new ListNode(null, null)
let result = p3
while (p1 && p2) {
if (p1.val <= p2.val) {
p3.next = p1
p3 = p3.next
p1 = p1.next
} else {
p3.next = p2
p3 = p3.next
p2 = p2.next
}
}
while (p1) {
p3.next = p1
p3 = p3.next
p1 = p1.next
}
while (p2) {
p3.next = p2
p3 = p3.next
p2 = p2.next
}
return result.next
};
第七题:删除有序数组中的重复项
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function(nums) {
// 长度为0,直接返回即可
if (nums.length === 0) return 0
// 使用两个指针
let fast = 1, slow = 1
while (fast < nums.length) {
// 因为该数组是有序数组,所以只要相邻两个元素不相等,那么就将fast对应的项赋值给slow
if (nums[fast] !== nums[fast - 1]) {
nums[slow] = nums[fast]
// slow++
slow++
}
// 如果相邻元素相同,直接fast++即可
fast++
}
return slow
};
第八题:最大子数组和
给你一个整数数组 nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
/**
* @param {number[]} nums
* @return {number}
*/
var maxSubArray = function(nums) {
let pre = 0, max = nums[0]
for (let i = 0; i < nums.length; i++) {
pre = Math.max(nums[i], (pre + nums[i]))
max = Math.max(max, pre)
}
return max
};
第九题: 二进制求和
给你两个二进制字符串,返回它们的和(用二进制表示)。
输入为 非空 字符串且只包含数字 1
和 0
。
/**
* @param {string} a
* @param {string} b
* @return {string}
*/
var addBinary = function(a, b) {
let i = a.length - 1
let j = b.length - 1
let result = ''
// 保存进位的值
let over = 0
while (i >= 0 && j >= 0) {
let sum = Number(a[i]) + Number(b[j]) + over
// sum大于1,也就是说需要进位
if (sum > 1) {
over = 1
sum = sum - 2
} else {
// 将over置为0,防止影响后续代码
over = 0
}
result = sum + result
i--
j--
}
while (i >= 0) {
let sum = Number(a[i]) + over
if (sum > 1) {
over = 1
sum = sum - 2
} else {
over = 0
}
result = sum + result
i--
}
while (j >= 0) {
let sum = Number(b[j]) + over
if (sum > 1) {
over = 1
sum = sum - 2
} else {
over = 0
}
// +的时候sum要在result前面
result = sum + result
j--
}
// over要在result前面
return over === 0 ? result : over + result
};
第十题: 爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
/**
* @param {number} n
* @return {number}
*/
var climbStairs = function(n) {
if (n === 1 || n === 2 || n === 3) {
return n
}
const arr = [2, 3]
for (let i = 4; i < n; i++) {
// 将 数组第一位和第二位值进行交换
[arr[0], arr[1]] = [arr[1], arr[0]]
// 修改第一位的值
arr[1] = arr[0] + arr[1]
}
return arr[0] + arr[1]
};
第十一题:删除排序链表中的重复元素
存在一个按升序排列的链表,给你这个链表的头节点 head
,请你删除所有重复的元素,使每个元素 只出现一次 。
返回同样按升序排列的结果链表。
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var deleteDuplicates = function(head) {
if (head === null) return head
let p = head
while (p.next) {
if (p.val === p.next.val) {
p.next = p.next.next
} else {
p = p.next
}
}
return head
};
第十二题:合并两个有序数组
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
/**
* @param {number[]} nums1
* @param {number} m
* @param {number[]} nums2
* @param {number} n
* @return {void} Do not return anything, modify nums1 in-place instead.
*/
var merge = function(nums1, m, nums2, n) {
// 先nums1的最后一个数组下标
let last = m + n - 1
while (n) {
if (m === 0 || nums1[m - 1] < nums2[n - 1]) {
nums1[last--] = nums2[--n]
} else {
nums1[last--] = nums1[--m]
}
}
};