LeetCode - 中等
3. 无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
/**
* @param {string} s
* @return {number}
*/
const lengthOfLongestSubstring = s => {
let map = Object.create(null);
const len = s.length;
let max = 0;
let lastRepeater = -1;
for (let i = 0; i < len; i++) {
const word = s[i];
if (word in map && lastRepeater < map[word]) {
lastRepeater = map[word];
}
if (i - lastRepeater > max) {
max = i - lastRepeater;
}
map[word] = i;
}
return max;
};
5. 最长回文子串
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
/**
* @param {string} s
* @return {string}
*/
const longestPalindrome = s => {
let longestPalindrome = s[0] || '';
for (let i = 0; i < s.length; i++) {
let dist = 1;
// Check odd-length palindromes
while (s[i + dist] !== undefined && s[i + dist] === s[i - dist]) {
dist++;
}
if (dist > 1) {
dist--;
if (i + dist - (i - dist) + 1 > longestPalindrome.length) {
longestPalindrome = s.substring(i - dist, i + dist + 1);
}
}
dist = 0;
// Check even-length palindromes
while (s[i - dist] !== undefined && s[i - dist] === s[i + 1 + dist]) {
dist++;
}
if (dist > 0) {
dist--;
if (i + 1 + dist - (i - dist) + 1 > longestPalindrome.length) {
longestPalindrome = s.substring(i - dist, i + dist + 2);
}
}
}
return longestPalindrome;
};
8. 字符串转换整数 (atoi)
请你来实现一个 atoi 函数,使其能将字符串转换成整数。
- 假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,qing 返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。
/**
* @param {string} str
* @return {number}
*/
const myAtoi = str => {
const MIN = -2147483648;
const MAX = 2147483647;
let flag = 1;
let first = 1;
let sum = 0;
str = str.trim();
for (let i = 0; i < str.length; i++) {
if (str[i] === '+' && first) {
first = 0;
} else if (str[i] === '-' && first) {
flag = -1;
first = 0;
} else if (str[i] <= '9' && str[i] >= '0') {
first = 0;
sum = sum * 10 + Number(str[i]);
} else {
break;
}
}
sum *= flag;
if (sum > MAX) sum = MAX;
if (sum < MIN) sum = MIN;
return sum;
};
11. 盛最多水的容器
给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
- 你不能倾斜容器,且 n 的值至少为 2。
/**
* @param {number[]} height
* @return {number}
*/
const maxArea = height => {
const len = height.length;
let ans = 0;
for (let i = 0; i < len; i++) {
for (let j = i + 1; j < len; j++) {
ans = Math.max(ans, Math.min(height[i], height[j]) * (j - i));
}
}
return ans;
};
15. 三数之和
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
- 答案中不可以包含重复的三元组。
/**
* @param {number[]} nums
* @return {number[][]}
*/
const threeSum = nums => {
const { length } = nums;
nums.sort((a, b) => a - b);
const result = [];
for (let i = 0; i < length; i += 1) {
const first = nums[i];
if (first > 0) break;
if (i > 0 && first === nums[i - 1]) continue;
const target = 0 - nums[i];
let l = i + 1;
let r = length - 1;
while (l < r) {
const second = nums[l];
const third = nums[r];
if (second + third === target) {
result.push([first, second, third]);
while (l < r && second === nums[l + 1]) l += 1;
while (l < r && third === nums[r - 1]) r -= 1;
l += 1;
r -= 1;
} else if (second + third < target) {
l += 1;
} else {
r -= 1;
}
}
}
return result;
};
43. 字符串相乘
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
/**
* @param {string} num1
* @param {string} num2
* @return {string}
*/
const multiply = (num1, num2) => {
const add = (a, b) => {
let flag = 0;
let la = a.length - 1;
let lb = b.length - 1;
let ans = '';
let t = 0;
while (la >= 0 && lb >= 0) {
t = Number(a[la]) + Number(b[lb]) + flag;
flag = Math.floor(t / 10);
t %= 10;
ans = t + ans;
la--;
lb--;
}
while (la >= 0) {
t = Number(a[la]) + flag;
flag = Math.floor(t / 10);
t %= 10;
ans = t + ans;
la--;
}
while (lb >= 0) {
t = Number(b[lb]) + flag;
flag = Math.floor(t / 10);
t %= 10;
ans = t + ans;
lb--;
}
if (flag > 0) ans = flag + ans;
return ans;
};
const mult = (a, b, n) => {
let ans = '';
let flag = 0;
let t = 0;
let nb = Number(b);
for (let i = a.length - 1; i >= 0; i--) {
t = Number(a[i]) * nb + flag;
flag = Math.floor(t / 10);
t %= 10;
ans = t + ans;
}
if (flag > 0) ans = flag + ans;
while (n--) {
ans += '0';
}
return ans;
};
let pre = '0';
let ans = '';
let len = num1.length;
for (let i = len - 1; i >= 0; i--) {
ans = add(mult(num2, num1[i], len - i - 1), pre);
pre = ans;
}
for (i = 0; i < ans.length; i++) {
if (ans[i] !== '0') break;
}
ans = ans.slice(i);
return ans.length <= 0 ? '0' : ans;
};
46. 全排列
给定一个没有重复数字的序列,返回其所有可能的全排列。
/**
* 全排列
* @param {number[]} nums
* @return {number[][]}
*/
const permute = nums => {
let result = [];
for (let i = 0; i < nums.length; i++) {
let arr = permute(nums.slice(0, i).concat(nums.slice(i + 1, nums.length)));
arr.forEach(a => {
result.push([nums[i], ...a]);
});
if (arr.length === 0) {
result.push([nums[i]]);
}
}
return result;
};
47. 全排列 II
给定一个可包含重复数字的序列,返回所有不重复的全排列。
/**
* @param {number[]} nums
* @return {number[][]}
*/
const permuteUnique = nums => {
const len = nums.length;
let ans = [];
const solve = k => {
if (k === len) {
ans.push(nums.join(''));
return;
}
let t;
for (let i = k; i < len; i++) {
t = nums[i];
nums[i] = nums[k];
nums[k] = t;
solve(k + 1);
t = nums[i];
nums[i] = nums[k];
nums[k] = t;
}
};
solve(0);
let final = [];
for (let i = 0; i < ans.length; i++) {
if (final.indexOf(ans[i]) === -1) final.push(ans[i]);
}
final = final.map(item => {
let it = [];
let flag = 1;
for (let j = 0; j < item.length; j++) {
if (item[j] === '-') {
flag = -1;
} else {
it.push(Number(item[j]) * flag);
flag = 1;
}
}
return it;
});
return final;
};
64. 最小路径和
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
- 每次只能向下或者向右移动一步。
/**
* @param {number[][]} grid
* @return {number}
*/
const minPathSum = grid => {
let xLen = grid[0].length;
let yLen = grid.length;
let minSums = grid;
for (let i = 1; i < xLen; i++) {
minSums[0][i] = minSums[0][i - 1] + grid[0][i];
}
for (let j = 1; j < yLen; j++) {
minSums[j][0] = minSums[j - 1][0] + grid[j][0];
}
for (let i = 1; i < grid[0].length; i++) {
for (let j = 1; j < yLen; j++) {
const item = grid[j][i];
minSums[j][i] = Math.min(
minSums[j][i - 1] + item,
minSums[j - 1][i] + item
);
}
}
return minSums[yLen - 1][xLen - 1];
};
165. 比较版本号
比较两个版本号 version1 和 version2。
- 如果 version1 > version2 返回 1,如果 version1 < version2 返回 -1, 除此之外返回 0。
/**
* @param {string} version1
* @param {string} version2
* @return {number}
*/
const compareVersion = (version1, version2) => {
if (!version1) {
return -1;
}
if (!version2) {
return 1;
}
const verArr1 = version1.split('.');
const verArr2 = version2.split('.');
const len = Math.max(verArr1.length, verArr2.length);
for (let i = 0; i < len; i++) {
let ver1 = verArr1[i] || 0;
let ver2 = verArr2[i] || 0;
ver1 -= 0;
ver2 -= 0;
if (ver1 > ver2) {
return 1;
} else if (ver1 < ver2) {
return -1;
}
}
return 0;
};