# 简单
# 俩数之和
# 题目
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。
示例 :
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
2
3
题目链接:https://leetcode-cn.com/problems/two-sum/
# 解法一(js)
var twoSum = function(nums, target) {
if(nums.length<2) return false;
var arr=[]
for(var i=0;i<nums.length;i++){
for(var j=i+1;j<nums.length;j++){
console.log('i:'+i+',j:'+j);
if(nums[i]+nums[j]==target){
arr.push(i,j)
}
}
}
return arr;
};
2
3
4
5
6
7
8
9
10
11
12
13
# 解法二(js)
var twoSum = function(nums, target){
const map = new Map();
for(let i=0; i<nums.length; i++){
if (map.has(nums[i])){
return [map.get(nums[i]),i];
}else{
map.set(target-nums[i],i);
}
}
}
2
3
4
5
6
7
8
9
10
# 整数反转
# 题目
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
注意:
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−2**31, 2 **31 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
示例 :
输入: -123
输出: -321
2
题目链接:https://leetcode-cn.com/problems/reverse-integer/
# 解答
var reverse = function(x) {
var arr=Math.abs(x).toString().split('');
var num=arr.reverse().join('');
if(x<0){
return num > 2**31 || -num > 2**31-1 ? 0 : -num
}else{
return num > 2**31-1 || -num > 2**31 ? 0 : num
}
};
2
3
4
5
6
7
8
9
# 回文数
# 题目
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
示例 :
输入: 121
输出: true
2
输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
2
3
题目链接:https://leetcode-cn.com/problems/palindrome-number/
# 解法一
var isPalindrome = function(x) {
if(x<0) return false;
var arr=x.toString().split('');
return arr.reverse().join('')==x?true:false;
};
2
3
4
5
6
# 解法二
var isPalindrome = function(x) {
if(x<0) return false;
x=x.toString();
for(var i=0,len=x.length;i<len/2;i++){
if(x[i]!=x[len-i-1]){
return false
}
}
return true;
};
2
3
4
5
6
7
8
9
10
# 最长公共前缀
# 题目
编写一个函数来查找字符串数组中的最长公共前缀,如果不存在公共前缀,返回空字符串 ""。
示例 :
输入: ["flower","flow","flight"]
输出: "fl"
2
输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。
2
3
题目链接:https://leetcode-cn.com/problems/longest-common-prefix/
# 解法一
var longestCommonPrefix = function(strs) {
if (strs === null || strs.length < 1) return "";
if(strs.length<2) return strs[0];
let prevs=strs[0];
for(let i=1;i<strs.length;i++){
let j=0;
for(;j<prevs.length && j< strs[i].length;j++){
if(prevs[j] != strs[i][j])
break;
}
prevs=prevs.substring(0,j);
if(prevs === "") return ""
}
return prevs;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 解法二
var longestCommonPrefix = function(strs) {
var result
if(strs === null || strs.length < 1) return ""
if(strs.length<2) return strs[0]
var reg = /^(\w+)([^,]*),(\1[^,]*,)*\1([^,]*)$/
var m=strs.join(',').match(reg)
result=m?m[1]:''
return result
};
2
3
4
5
6
7
8
9
# 有效的括号
# 题目
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
示例 :
输入: "()[]{}"
输出: true
2
输入: "([)]"
输出: false
2
题目链接:https://leetcode-cn.com/problems/valid-parentheses/
# 解法一
const isValid = function(s){
const stack=[];
for(let i=0;i<s.length;i++){
if(s[i]=='(' || s[i]=='[' || s[i]=='{'){
stack.push(s[i])
}else{
if (stack.length == 0) { // 此时栈空,无法匹配
return false;
}
const top=stack[stack.length-1];
if((top=='(' && s[i]==')')|| (top=='[' && s[i]==']') ||(top=='{' && s[i]=='}')){
stack.pop()
}else{
return false;
}
}
}
console.log(stack);
return stack.length==0;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 解法二
const isValid = function(s){
while(s.length){
var temp=s;
s=s.replace('()','');
s=s.replace('[]','');
s=s.replace('{}','');
if(temp==s) return false;
}
return true;
};
2
3
4
5
6
7
8
9
10
# 删除排序数组中的重复项
# 题目
给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
示例 :
给定数组 nums = [1,1,2],
函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。
你不需要考虑数组中超出新长度后面的元素。
2
3
4
5
题目链接:https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/
# 解法
var removeDuplicates = function(nums) {
for(let i=0;i<nums.length;i++){
console.log(nums.indexOf(nums[i]));
if(nums.indexOf(nums[i])!=i){
nums.splice(i,1)
i=i-1;
}
}
return nums.length;
};
2
3
4
5
6
7
8
9
10
# 移除元素
# 题目
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
示例 :
给定 nums = [3,2,2,3], val = 3,
函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。
你不需要考虑数组中超出新长度后面的元素。
2
3
4
5
题目链接:https://leetcode-cn.com/problems/remove-element/
# 解法
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;
};
2
3
4
5
6
7
8
9
# 实现strStr()
# 题目
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。
示例 :
输入: haystack = "hello", needle = "ll"
输出: 2
2
题目链接:https://leetcode-cn.com/problems/implement-strstr/
# 解法
var strStr = function(haystack, needle) {
return haystack.indexOf(needle);
};
2
3
# 搜索插入位置
# 题目
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
示例 :
输入: [1,3,5,6], 5
输出: 2
2
输入: [1,3,5,6], 2
输出: 1
2
题目链接:https://leetcode-cn.com/problems/search-insert-position/
# 解法
var searchInsert = function(nums, target) {
for (let j = 0; j < nums.length; j++) {
if (nums[j] >= target) {
return j
}
}
return nums.length
};
2
3
4
5
6
7
8
# 最后一个单词的长度
# 题目
给定一个仅包含大小写字母和空格 ' ' 的字符串 s,返回其最后一个单词的长度。如果字符串从左向右滚动显示,那么最后一个单词就是最后出现的单词。如果不存在最后一个单词,请返回 0 。
示例 :
输入: "Hello World"
输出: 5
2
题目链接:https://leetcode-cn.com/problems/length-of-last-word/
# 解法一
var lengthOfLastWord = function(s) {
var str = s.trim().split(" ");//trim()用于删除字符串的头尾空白符。
return str[str.length - 1].length;
};
2
3
4
# 解法二
var lengthOfLastWord = function(s) {
let arr=s.split(" ");
for(let i=0;i<arr.length;i++){
if(arr[i]==""){
arr.splice(i,1)
i--;
}
}
return arr.length<=0 ? 0:arr[arr.length-1].length;
};
2
3
4
5
6
7
8
9
10
# 外观数列
# 题目
给定一个正整数 n ,输出外观数列的第 n 项。「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。
前五项如下:
1. 1
2. 11
3. 21
4. 1211
5. 111221
第一项是数字 1
描述前一项,这个数是 1 即 “ 一 个 1 ”,记作 "11"
描述前一项,这个数是 11 即 “ 二 个 1 ” ,记作 "21"
描述前一项,这个数是 21 即 “ 一 个 2 + 一 个 1 ” ,记作 "1211"
描述前一项,这个数是 1211 即 “ 一 个 1 + 一 个 2 + 二 个 1 ” ,记作 "111221"
2
3
4
5
6
7
8
9
10
11
示例 :
输入:n = 4
输出:"1211"
解释:
countAndSay(1) = "1"
countAndSay(2) = 读 "1" = 一 个 1 = "11"
countAndSay(3) = 读 "11" = 二 个 1 = "21"
countAndSay(4) = 读 "21" = 一 个 2 + 一 个 1 = "12" + "11" = "1211"
2
3
4
5
6
7
题目链接:https://leetcode-cn.com/problems/count-and-say/
# 解法一
var countAndSay = function(n) {
if(n == 1){
return "1";
}
let newStr="",preStr,index=1,
str=countAndSay(n-1);//21
preStr=str[0];
for(let i=1;i<str.length;i++){
if(preStr == str[i]){
index++;
}else{
newStr+=index+preStr;
preStr=str[i];
index=1;
}
}
return newStr+=index+preStr;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 解法二
var countAndSay = function(n) {
let reg=/(\d)\1*/g;
if(n==1) return '1';
return countAndSay(n-1).match(reg).map(item=>item.length+item[0]).join('');
};
2
3
4
5
# 解法三
var countAndSay = function(n) {
let prev = '1'
for(let i = 1; i < n; i++){
prev = prev.replace(/(\d)\1*/g, item =>`${item.length}${item[0]}`)
}
return prev
};
2
3
4
5
6
7
# 最大子序和
# 题目
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和
示例 :
输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
2
3
题目链接:https://leetcode-cn.com/problems/maximum-subarray/
# 解法一
var maxSubArray = function(nums) {
let sum=0,maxAns=nums[0];
for(let item of nums){
if(sum>0){
sum+=item
}else{
sum=item
}
maxAns= Math.max(sum,maxAns)
};
return maxAns
}
2
3
4
5
6
7
8
9
10
11
12
# 解法二
var maxSubArray = function(nums) {
let pre=0,maxAns=nums[0]
nums.forEach(item => {
pre=Math.max(pre+item,item)
maxAns=Math.max(maxAns,pre)
});
return maxAns;
};
2
3
4
5
6
7
8
# 加一
# 题目
给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。你可以假设除了整数 0 之外,这个整数不会以零开头。
示例 :
输入:digits = [1,2,3]
输出:[1,2,4]
解释:输入数组表示数字 123。
2
3
题目链接:https://leetcode-cn.com/problems/plus-one/
# 解法
var plusOne = function(digits) {
let len=digits.length;
for(let i=len-1;i>=0;i--){
digits[i]++;
digits[i]%=10;
if(digits[i]!=0){
return digits;
}
}
digits=[...Array(len+1)].map(_=>0);
// digits=new Array(length+1).fill(0)
digits[0]=1;
return digits;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
# 二进制求和
# 题目
给你两个二进制字符串,返回它们的和(用二进制表示)。输入为 非空 字符串且只包含数字 1 和 0。
示例 :
输入: a = "1010", b = "1011"
输出: "10101"
2
题目链接:https://leetcode-cn.com/problems/add-binary/
# 解法
var addBinary = function(a, b) {
let ca=0,ans='';
for(let i=a.length-1,j=b.length-1;i>=0 || j>=0;i--,j--){
let sum=ca;
sum+= i>=0?parseInt(a[i]):0;
sum+=j>=0?parseInt(b[j]):0;
ans+=sum%2;
ca=Math.floor(sum/2)
}
ans+=ca=='1'?ca:''
return ans.split('').reverse().join('')
};
2
3
4
5
6
7
8
9
10
11
12
# x的平方根
# 题目
计算并返回 x 的平方根,其中 x 是非负整数。由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例 :
输入: 8
输出: 2
说明: 8 的平方根是 2.82842...,
由于返回类型是整数,小数部分将被舍去。
2
3
4
题目链接:https://leetcode-cn.com/problems/sqrtx/
# 解法
var mySqrt = function(x) {
if (x<1) {
return 0;
}
var find = function ( left, right, x) {
if (right - left <= 1) {
return left;
}
mid = Math.floor((left + right) / 2);
if (mid * mid > x) {
right = mid;
} else {
left = mid;
}
return find( left, right, x);
}
return find(1, x, x);
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 合并俩个有序数组
# 题目
给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
示例 :
输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
2
3
4
5
题目链接:https://leetcode-cn.com/problems/merge-sorted-array/
# 解法
var merge = function(nums1, m, nums2, n) {
let count=m+n;
while(m>0 && n>0){
nums1[--count]=nums1[m-1]<nums2[n-1]?nums2[--n]:nums1[--m];
}
if(n>0){
nums1.splice(0,n,...nums2.slice(0,n))
}
return nums1
};
2
3
4
5
6
7
8
9
10
11
# 杨辉三角
# 题目
给定一个非负整数 numRows,生成杨辉三角的前 numRows 行。
示例 :
输入: 5
输出:
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]
2
3
4
5
6
7
8
9
题目链接:https://leetcode-cn.com/problems/pascals-triangle/
# 解法
var generate = function(numRows) {
if(numRows==0) return [];
let j=0,res=[];
while(j<numRows){
let temp=[1];
for(let i=1;i<j;i++){
let row=res[j-1];
temp.push(row[i-1]+row[i])
}
if(j>0) temp.push(1);
res.push(temp);
j++;
}
return res;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 杨辉三角 II
# 题目
给定一个非负索引 k,其中 k ≤ 33,返回杨辉三角的第 k 行。
示例 :
输入: 3
输出: [1,3,3,1]
2
题目链接:https://leetcode-cn.com/problems/pascals-triangle-ii/
# 解法
var getRow = function(rowIndex) {
if(rowIndex<0 && k>33) return [];
let number=rowIndex+1;
let j=0;res=[];
while(j<number){
let temp=[1]
for(let i=1;i<j;i++){
let row=res[j-1];
temp.push(row[i-1]+row[i])
}
if(j>0) temp.push(1)
res.push(temp);
j++;
}
return res[rowIndex];
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 买卖股票的最佳时期
# 题目
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。注意:你不能在买入股票前卖出股票。
示例 :
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
2
3
4
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
2
3
题目链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/
# 解法
var maxProfit = function(prices) {
if (!prices || !prices.length) return 0
let max=0;
for(let i=0;i<prices.length;i++){
for(let j=i+1;j<prices.length;j++){
if(prices[j]>prices[i]){
max=Math.max(max,prices[j]-prices[i])
}
}
}
return max;
};
2
3
4
5
6
7
8
9
10
11
12
13
# 买卖股票的最佳时期 II
# 题目
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 :
输入: [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。
2
3
4
输入: [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。
因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
2
3
4
5
题目链接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/
# 解法
var maxProfit = function(prices) {
if (!prices || !prices.length) return 0
let profit=0;
for(let i=1;i<prices.length;i++){
const diff=prices[i]-prices[i-1] // 今天和昨天的差价
if(diff>0){ / 差价大于0
profit+=diff // 今天卖掉,赚了今天和昨天的差价
}
}
return profit;
};
2
3
4
5
6
7
8
9
10
11
12
# 验证回文串
# 题目
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
示例 :
输入: "A man, a plan, a canal: Panama"
输出: true
2
输入: "race a car"
输出: false
2
题目链接:https://leetcode-cn.com/problems/valid-palindrome/
# 解法
var isPalindrome = function(s) {
let str=s.toLocaleLowerCase().match(/[A-Za-z0-9]+/g); //s = s.replace(/[^a-z0-9]/g,'');
if(!str) return true;
let arr=str.join('').split('');
for(let i=0;i<arr.length;i++){
if(arr[i]!=arr[arr.length-i-1]){
return false
}
}
return true;
};
2
3
4
5
6
7
8
9
10
11
12
13
# 验证回文串II
# 题目
给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。
示例 :
输入: "abca"
输出: True
解释: 你可以删除c字符。
2
3
题目链接:https://leetcode-cn.com/problems/valid-palindrome-ii/
# 解法
var validPalindrome = function(s) {
let len=s.length;
for(let i=0;i<len/2;i++){
if(s[i]!=s[len-i-1]){
let str1=s.substring(0,i)+s.substring(i+1,len)
let str2=s.substring(0,len-i-1)+s.substring(len-i,len)
return str1==str1.split('').reverse().join('') || str2==str2.split('').reverse().join('')
}
}
return true;
};
2
3
4
5
6
7
8
9
10
11
# 快乐数
# 题目
编写一个算法来判断一个数 n 是不是快乐数。「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为 1,那么这个数就是快乐数。如果 n 是快乐数就返回 True ;不是,则返回 False 。
示例 :
输入:19
输出:true
解释:
1**2 + 9**2 = 82
8**2 + 2**2 = 68
6**2 + 8**2 = 100
1**2 + 0**2 + 0**2 = 1
2
3
4
5
6
7
题目链接:https://leetcode-cn.com/problems/happy-number/
# 解法
var isHappy = function(n) {
while(n=n.toString().split('').reduce((p,v)=>p+v*v,0)){
if(n==1){
return true
}else if(n==4){
return false
}
}
};
2
3
4
5
6
7
8
9
# Excel表列名称
# 题目
给定一个正整数,返回它在 Excel 表中相对应的列名称。
例如:
1 -> A
2 -> B
3 -> C
...
26 -> Z
27 -> AA
28 -> AB
...
2
3
4
5
6
7
8
示例:
输入: 28
输出: "AB"
2
题目链接:https://leetcode-cn.com/problems/excel-sheet-column-title/
# 解法
var convertToTitle = function(n) {
const str="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
let result=''
while(n>0){
n--;
result=str[n%26]+result;
n=Math.floor(n/26);
}
return result;
};
2
3
4
5
6
7
8
9
10
11
# Excel表序列号
# 题目
给定一个Excel表格中的列名称,返回其相应的列序号。
例如:
A -> 1
B -> 2
C -> 3
...
Z -> 26
AA -> 27
AB -> 28
...
2
3
4
5
6
7
8
示例:
输入: "AB"
输出: 28
2
示例:
输入: "ZY"
输出: 701
2
题目链接:https://leetcode-cn.com/problems/meeting-rooms/
# 解法
var canAttendMeetings = function(intervals) {
intervals=intervals.sort((a,b)=>a[0]-b[0]);
console.log(intervals);
for(let i=0;i<intervals.length-1;i++){
if(intervals[i][1]>intervals[i+1][0]){
return false;
}
}
return true;
};
2
3
4
5
6
7
8
9
10
11
# 存在重复元素
# 题目
给定一个整数数组,判断是否存在重复元素。如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。
示例:
输入: [1,2,3,1]
输出: true
2
示例:
输入: [1,2,3,4]
输出: false
2
题目链接:https://leetcode-cn.com/problems/contains-duplicate/
# 解法一(new Set)
var containsDuplicate = function(nums) {
const arr=[...new Set(nums)]
if(arr.length!=nums.length) return true;
return false;
};
2
3
4
5
# 解法二(indexOf)
var containsDuplicate = function(nums) {
for(let i=0;i<nums.length;i++){
if(nums.indexOf(nums[i])!=i){
return true;
}
}
return false;
};
2
3
4
5
6
7
8
# 解法三(sort)
var containsDuplicate = function(nums) {
nums.sort((a,b)=>a-b);
for(let i=1;i<nums.length;i++){
if(nums[i]==nums[i-1]) return true;
}
return false;
};
2
3
4
5
6
7
# 解法四(includes)
var containsDuplicate = function(nums) {
let arr=[];
for(let i=0;i<nums.length;i++){
if(arr.includes(nums[i])){
return true;
}else{
arr.push(nums[i])
}
}
return false;
};
2
3
4
5
6
7
8
9
10
11
# 解法五(new Map)
var containsDuplicate = function(nums) {
let map=new Map;
for(let i=0;i<nums.length;i++){
if(map.has(nums[i])){
return true;
}else{
map.set(nums[i],1)
}
}
return false;
};
2
3
4
5
6
7
8
9
10
11
# 解法六(枚举法)
var containsDuplicate = function(nums) {
for(let i=0;i<nums.length-1;i++){
for(let j=i+1;j<nums.length;j++){
if(nums[i]==nums[j])return true;
}
}
return false;
};
2
3
4
5
6
7
8
# 存在重复元素 II
# 题目
给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。
示例:
输入: nums = [1,2,3,1], k = 3
输出: true
2
示例:
输入: nums = [1,2,3,1,2,3], k = 2
输出: false
2
题目链接:https://leetcode-cn.com/problems/contains-duplicate-ii/
# 解法一(枚举法)
var containsNearbyDuplicate = function(nums,k) {
for(var i = 0; i < nums.length - 1; i++){
for(var j = i + 1; j < nums.length; j++){
if (nums[i] === nums[j]){
if(j-i<=k){
return true;
}
}
}
}
return false;
};
2
3
4
5
6
7
8
9
10
11
12
# 解法二(includes)
var containsNearbyDuplicate = function(nums,k) {
let arr=[]
for(let i=0;i<nums.length;i++){
if(arr.includes(nums[i])){
return true;
}else{
arr.push(nums[i]);
if(arr.length>k){
arr.splice(0,1)
}
}
}
return false;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
# 解法三(set)
var containsNearbyDuplicate = function(nums,k) {
let set=new Set();
for(let i=0;i<nums.length;i++){
if(set.has(nums[i])){
return true;
}else{
set.add(nums[i])
if(set.size>k){
set.delete(nums[i-k])
}
}
}
return false;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
# 解法三(some)
var containsNearbyDuplicate = function(nums,k) {
return nums.some((item,index)=>{
var tempArr=nums.slice(index+1,index+k+1);
return tempArr.indexOf(item)!=-1?true:false;
});
};
2
3
4
5
6
# 反转字符串
# 题目
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。
示例:
输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]
2
题目链接:链接:https://leetcode-cn.com/problems/reverse-string
# 解法
var reverseString = function(s) {
let length=s.length
for(let left=0,right=length-1;left<right;left++,right--){
[s[left],s[right]]=[s[right],s[left]]
}
};
2
3
4
5
6
# 反转字符串中的单词
# 题目
给定一个字符串,逐个翻转字符串中的每个单词。
示例:
输入:"the sky is blue"
输出:"blue is sky the"
2
示例:
输入:"a good example"
输出:"example good a"
解释:如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
2
3
题目链接:https://leetcode-cn.com/problems/reverse-words-in-a-string/
# 解法
var reverseWords = function(s) {
let arr=s.split(" ");
for(let i=0;i<arr.length;i++){
if(arr[i]==""){
arr.splice(i,1)
i--;
}
}
return arr.reverse().join(' ');
};
2
3
4
5
6
7
8
9
10
# 反转字符串中的单词 II
# 题目
给定一个字符串,逐个翻转字符串中的每个单词。
示例:
输入: ["t","h","e"," ","s","k","y"," ","i","s"," ","b","l","u","e"]
输出: ["b","l","u","e"," ","i","s"," ","s","k","y"," ","t","h","e"]
2
题目链接:https://leetcode-cn.com/problems/reverse-words-in-a-string-ii/
# 解法
var reverseWords = function(s) {
const length=s.length;
let temp=' ',i=0;
while(i<length){
if(s[i]!=" "){
temp+=s[i];
}else{
s.splice(length,0,...temp)
temp=" ";
}
i++;
}
if(temp.length>1){
s.splice(length,0,...temp)
}
s.splice(0,length+1);//删除原先的数组
return s;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 解法二(先整体反转再挨个反转)
var reverseWords = function(s) {
const length=s.length;
const reverse=function(s,start,end){
while(start<end){
let temp=s[end];
s[end]=s[start];
s[start]=temp;
start++;
end--;
}
}
reverse(s,0,length-1);//整体反转
let start=0,end=0;
while(end<length){
if(s[end]==" "){
reverse(s,start,end-1)//挨个反转
start=end+1;
}
end++;
}
reverse(s,start,end-1)//最后一个单词反转
return s;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 反转字符串中的单词 III
# 题目
给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序。
示例:
输入:"Let's take LeetCode contest"
输出:"s'teL ekat edoCteeL tsetnoc"
2
题目链接:https://leetcode-cn.com/problems/reverse-words-in-a-string-iii/
# 解法
var reverseWords = function(s) {
return s.split(' ').map(x=>x.split('').reverse().join('')).join(' ')
};
2
3
# 最短单词距离
# 题目
给定一个单词列表和两个单词 word1 和 word2,返回列表中这两个单词之间的最短距离。
示例:
输入:words = ["practice", "makes", "perfect", "coding", "makes"], word1 = “coding”, word2 = “practice”
输出: 3
2
示例:
输入:words = ["practice", "makes", "perfect", "coding", "makes"], word1 = "makes", word2 = "coding"
输出: 1
2
题目链接:https://leetcode-cn.com/problems/shortest-word-distance/
# 解法
var shortestDistance = function(words, word1, word2) {
let result=Infinity;
let word1_index=-1,word2_index=-1;
for(let i=0;i<words.length;i++){
if(words[i]==word1){
word1_index=i;
}
if(words[i]==word2){
word2_index=i
}
if(word1_index!=-1 && word2_index!=-1){
result=Math.min(result,Math.abs(word2_index-word1_index))
}
}
return result;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 会议室
# 题目
给定一个会议时间安排的数组 intervals ,每个会议时间都会包括开始和结束的时间 intervals[i] = [starti, endi] ,请你判断一个人是否能够参加这里面的全部会议。
示例:
输入:intervals = [[0,30],[5,10],[15,20]]
输出:false
2
示例:
输入:intervals = [[7,10],[2,4]]
输出:true
2
题目链接:https://leetcode-cn.com/problems/meeting-rooms/
# 解法
var canAttendMeetings = function(intervals) {
intervals=intervals.sort((a,b)=>a[0]-b[0]);
for(let i=0;i<intervals.length-1;i++){
if(intervals[i][1]>intervals[i+1][0]){
return false;
}
}
return true;
};
2
3
4
5
6
7
8
9
10
# 各位相加
# 题目
给定一个非负整数 num,反复将各个位上的数字相加,直到结果为一位数。
示例:
输入: 38
输出: 2
解释: 各位相加的过程为:3 + 8 = 11, 1 + 1 = 2。 由于 2 是一位数,所以返回 2。
2
3
题目链接:https://leetcode-cn.com/problems/add-digits/
# 解法一
var addDigits = function(num) {
if(num<10){
return num;
}
while(num=num.toString().split('').reduce((p,v)=>Number(p)+Number(v),0)){
if(num.toString().length==1){
return num;
}
}
};
2
3
4
5
6
7
8
9
10
# 解法二
var addDigits = function(num) {
if(num<10){
return num;
}
return num%9 ||9;
};
2
3
4
5
6
# 同构字符串
# 题目
给定两个字符串 s 和 t,判断它们是否是同构的。
如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。
每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。
示例:
输入:s = "egg", t = "add"
输出:true
2
示例:
输入:s = "foo", t = "bar"
输出:false
2
题目链接:https://leetcode-cn.com/problems/isomorphic-strings/
# 解法
var isIsomorphic = function(s, t) {
if(s.length!=t.length) return false;
for(let i=0;i<s.length;i++){
if(s.indexOf(s[i])!=t.indexOf(t[i])){
return false;
}
}
return true;
};
2
3
4
5
6
7
8
9
# 丑数
# 题目
编写一个程序判断给定的数是否为丑数。丑数就是只包含质因数 2, 3, 5 的正整数。
示例:
输入: 6
输出: true
解释: 6 = 2 × 3
2
3
示例:
输入: 8
输出: true
解释: 8 = 2 × 2 × 2
2
3
题目链接:https://leetcode-cn.com/problems/ugly-number/
# 解法
var isUgly = function(num) {
if(num<1) return false;
[2,3,5].map(item=>{
while(num%item==0) num=num/item
})
return num==1;
};
2
3
4
5
6
7
# 丢失的数字
# 题目
给定一个包含 [0, n] 中 n 个数的数组 nums ,找出 [0, n] 这个范围内没有出现在数组中的那个数。
示例:
输入:nums = [3,0,1]
输出:2
解释:n = 3,因为有 3 个数字,所以所有的数字都在范围 [0,3] 内。2 是丢失的数字,因为它没有出现在 nums 中。
2
3
示例:
输入:nums = [9,6,4,2,3,5,7,0,1]
输出:8
解释:n = 9,因为有 9 个数字,所以所有的数字都在范围 [0,9] 内。8 是丢失的数字,因为它没有出现在 nums 中。
2
3
题目链接:https://leetcode-cn.com/problems/missing-number/
# 解法
var missingNumber = function(nums) {
let length=nums.length;
let arr=[];
for(let i=0;i<=length;i++){
if(!nums.includes(i)){
arr.push(i)
}
}
return arr;
};
2
3
4
5
6
7
8
9
10
# 重新排列数组
# 题目
给你一个数组 nums ,数组中有 2n 个元素,按 [x1,x2,...,xn,y1,y2,...,yn] 的格式排列。请你将数组按 [x1,y1,x2,y2,...,xn,yn] 格式重新排列,返回重排后的数组。
示例:
输入:nums = [2,5,1,3,4,7], n = 3
输出:[2,3,5,4,1,7]
解释:由于 x1=2, x2=5, x3=1, y1=3, y2=4, y3=7 ,所以答案为 [2,3,5,4,1,7]
2
3
题目链接:https://leetcode-cn.com/problems/shuffle-the-array/
# 解法
var shuffle = function(nums, n) {
let arr=[];
let num1=nums.splice(0,n)
for(let i=0;i<n;i++){
arr.push(num1[i],nums[i])
}
return arr;
};
2
3
4
5
6
7
8
# 宝石与石头
# 题目
给定字符串J 代表石头中宝石的类型,和字符串 S代表你拥有的石头。 S 中每个字符代表了一种你拥有的石头的类型,你想知道你拥有的石头中有多少是宝石。J 中的字母不重复,J 和 S中的所有字符都是字母。字母区分大小写,因此"a"和"A"是不同类型的石头。
示例:
输入: J = "aA", S = "aAAbbbb"
输出: 3
2
题目链接:https://leetcode-cn.com/problems/jewels-and-stones/
# 解法
var numJewelsInStones = function(jewels, stones) {
let index=0
for(let i=0;i<stones.length;i++){
if(jewels.indexOf(stones[i])!=-1){
index++
}
}
return index;
};
2
3
4
5
6
7
8
9
# 统计一致字符串的数目
# 题目
给你一个由不同字符组成的字符串 allowed 和一个字符串数组words。如果一个字符串的每一个字符都在 allowed 中,就称这个字符串是 一致字符串。
示例:
输入:allowed = "ab", words = ["ad","bd","aaab","baa","badab"]
输出:2
解释:字符串 "aaab" 和 "baa" 都是一致字符串,因为它们只包含字符 'a' 和 'b' 。
2
3
4
题目链接:https://leetcode-cn.com/problems/count-the-number-of-consistent-strings/
# 解法
var countConsistentStrings = function(allowed, words) {
let count=0
for(let i=0;i<words.length;i++){
words[i].split('').every(item=>allowed.includes(item))==true?count++:count;
}
return count;
};
2
3
4
5
6
7
# 最长连续递增序列
# 题目
给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。
连续递增的子序列 可以由两个下标 l 和 r(l < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是连续递增子序列。
示例:
输入:nums = [1,3,5,4,7]
输出:3
解释:最长连续递增序列是 [1,3,5], 长度为3。
尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为 5 和 7 在原数组里被 4 隔开。
2
3
4
题目链接:https://leetcode-cn.com/problems/longest-continuous-increasing-subsequence
# 解法
var findLengthOfLCIS = function(nums) {
let max=0,start=0;
for(let i=0;i<nums.length;i++){
if(i>0 && nums[i]<=nums[i-1]){
start=i;
}
max=Math.max(max,i-start+1)
}
return max;
};
2
3
4
5
6
7
8
9
10
# 将数字变成0的操作次数
# 题目
给你一个非负整数 num ,请你返回将它变成 0 所需要的步数。 如果当前数字是偶数,你需要把它除以 2 ;否则,减去 1 。
示例:
输入:num = 14
输出:6
解释:
步骤 1) 14 是偶数,除以 2 得到 7 。
步骤 2) 7 是奇数,减 1 得到 6 。
步骤 3) 6 是偶数,除以 2 得到 3 。
步骤 4) 3 是奇数,减 1 得到 2 。
步骤 5) 2 是偶数,除以 2 得到 1 。
步骤 6) 1 是奇数,减 1 得到 0 。
2
3
4
5
6
7
8
9
题目链接:https://leetcode-cn.com/problems/number-of-steps-to-reduce-a-number-to-zero/
# 解法
var numberOfSteps = function(num) {
let index=0;
while(num!=0){
if(num%2==0){
num=num/2;
index++;
}else{
num=num-1;
index++;
}
}
return index;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
# 所有奇数长度子数组的和
# 题目
给你一个正整数数组 arr ,请你计算所有可能的奇数长度子数组的和。子数组 定义为原数组中的一个连续子序列。请你返回 arr 中 所有奇数长度子数组的和 。
示例:
输入:arr = [1,4,2,5,3]
输出:58
解释:所有奇数长度子数组和它们的和为:
[1] = 1
[4] = 4
[2] = 2
[5] = 5
[3] = 3
[1,4,2] = 7
[4,2,5] = 11
[2,5,3] = 10
[1,4,2,5,3] = 15
我们将所有值求和得到 1 + 4 + 2 + 5 + 3 + 7 + 11 + 10 + 15 = 58
2
3
4
5
6
7
8
9
10
11
12
13
题目链接:https://leetcode-cn.com/problems/sum-of-all-odd-length-subarrays/
# 解法
var sumOddLengthSubarrays = function(arr) {
let sum=0;
for(let i=0;i<arr.length;i++){
for(let j=i;j<arr.length;j++){
if((j-i+1)%2!=0){
for(let k=i;k<=j;k++){
sum+=arr[k]
}
}
}
}
return sum;
};
2
3
4
5
6
7
8
9
10
11
12
13
# 转换成小写字母
# 题目
实现函数 ToLowerCase(),该函数接收一个字符串参数 str,并将该字符串中的大写字母转换成小写字母,之后返回新的字符串。
示例:
输入: "Hello"
输出: "hello"
2
题目链接:https://leetcode-cn.com/problems/to-lower-case/
# 解法
var toLowerCase = function(str) {
let s=''
str.split('').forEach(element => {
if(element.charCodeAt()<=90 && element.charCodeAt()>=65){
s+=String.fromCharCode(element.charCodeAt()+32)
}else{
s+=element;
}
});
return s;
// return str.replace(/[A-Z]/g,c=>String.fromCharCode(c.charCodeAt()+32)) 解法二
};
2
3
4
5
6
7
8
9
10
11
12
13
14
# 解码字母到整数映射
# 题目
给你一个字符串 s,它由数字('0' - '9')和 '#' 组成。我们希望按下述规则将 s 映射为一些小写英文字符:
字符('a' - 'i')
分别用('1' - '9')
表示。
字符('j' - 'z')
分别用('10#' - '26#')
表示。
返回映射之后形成的新字符串。
题目数据保证映射始终唯一。
示例:
输入:s = "10#11#12"
输出:"jkab"
解释:"j" -> "10#" , "k" -> "11#" , "a" -> "1" , "b" -> "2".
2
3
4
题目链接:https://leetcode-cn.com/problems/decrypt-string-from-alphabet-to-integer-mapping/
# 解法
var freqAlphabets = function(s) {
let str=''
for(let i=0,j;i<s.length;i++){
j=i+2;
if(s[j]=='#'){
let value=+(s[j-2]+s[j-1])+96
str+=String.fromCharCode(value)
i=j;
}else{
str+=String.fromCharCode(+s[i]+96)
}
}
return str;
//return s.replace(/(\d{2}(?=#)\#)|(\d{1})/g,item=> String.fromCharCode(parseInt(item)+96)) 第二种解法
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 自除数
# 题目
自除数 是指可以被它包含的每一位数除尽的数。
例如,128 是一个自除数,因为 128 % 1 == 0,128 % 2 == 0,128 % 8 == 0。
还有,自除数不允许包含 0 。
给定上边界和下边界数字,输出一个列表,列表的元素是边界(含边界)内所有的自除数。
示例:
输入:
上边界left = 1, 下边界right = 22
输出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 15, 22]
2
3
4
题目链接:https://leetcode-cn.com/problems/self-dividing-numbers/
# 解法
var selfDividingNumbers = function(left, right) {
let res=[]
for(let i=left;i<=right;i++){
if(i.toString().split('').every(item=>i%parseInt(item)==0))res.push(i)
}
return res;
};
2
3
4
5
6
7
# 查找常用字符
# 题目
给定仅有小写字母组成的字符串数组 A,返回列表中的每个字符串中都显示的全部字符(包括重复字符)组成的列表。例如,如果一个字符在每个字符串中出现 3 次,但不是 4 次,则需要在最终答案中包含该字符 3 次。
示例:
输入:["bella","label","roller"]
输出:["e","l","l"]
2
3
题目链接:https://leetcode-cn.com/problems/find-common-characters/
# 解法
var commonChars = function(A) {
let arr=[],word=A[0]
for(let c of word){
if(A.every(item=>item.includes(c))){
A=A.map(m=>m.replace(c,''))
arr.push(c)
}
}
return arr;
};
2
3
4
5
6
7
8
9
10
# 无法吃午餐的学生数量
# 题目
学校的自助午餐提供圆形和方形的三明治,分别用数字 0 和 1 表示。所有学生站在一个队列里,每个学生要么喜欢圆形的要么喜欢方形的。 餐厅里三明治的数量与学生的数量相同。所有三明治都放在一个 栈 里,每一轮:
如果队列最前面的学生 喜欢 栈顶的三明治,那么会 拿走它 并离开队列。 否则,这名学生会 放弃这个三明治 并回到队列的尾部。 这个过程会一直持续到队列里所有学生都不喜欢栈顶的三明治为止。
给你两个整数数组 students 和 sandwiches ,其中 sandwiches[i] 是栈里面第 i 个三明治的类型(i = 0 是栈的顶部), students[j] 是初始队列里第 j 名学生对三明治的喜好(j = 0 是队列的最开始位置)。请你返回无法吃午餐的学生数量。
示例:
输入:students = [1,1,0,0], sandwiches = [0,1,0,1]
输出:0
解释:
- 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [1,0,0,1]。
- 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [0,0,1,1]。
- 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [0,1,1],三明治栈为 sandwiches = [1,0,1]。
- 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [1,1,0]。
- 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [1,0],三明治栈为 sandwiches = [0,1]。
- 最前面的学生放弃最顶上的三明治,并回到队列的末尾,学生队列变为 students = [0,1]。
- 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [1],三明治栈为 sandwiches = [1]。
- 最前面的学生拿走最顶上的三明治,剩余学生队列为 students = [],三明治栈为 sandwiches = []。
所以所有学生都有三明治吃。
2
3
4
5
6
7
8
9
10
11
12
13
14
题目链接:https://leetcode-cn.com/problems/number-of-students-unable-to-eat-lunch/
# 解法
var countStudents = function(students, sandwiches) {
while(students.some(item=>item==sandwiches[0])){ //关键在于some函数
if(students[0] === sandwiches[0]){
students.shift()
sandwiches.shift()
}else{
// 拿出第一个学生塞到队列最后
let first = students.shift()
students.push(first)
}
}
return students.length;
};
2
3
4
5
6
7
8
9
10
11
12
13
# 独一无二的出现次数
# 题目
给你一个整数数组 arr,请你帮忙统计数组中每个数的出现次数。如果每个数的出现次数都是独一无二的,就返回 true;否则返回 false。
示例:
输入:arr = [1,2,2,1,1,3]
输出:true
解释:在该数组中,1 出现了 3 次,2 出现了 2 次,3 只出现了 1 次。没有两个数的出现次数相同。
2
3
4
题目链接:https://leetcode-cn.com/problems/unique-number-of-occurrences/
# 解法一
var uniqueOccurrences = function(arr) {
let obj = {};
for(let item of arr){
obj[item]?obj[item]++:obj[item]=1;
}
let res=Object.keys(obj).map(key=>obj[key]);
return res.length==[...new Set(res)].length;
};
2
3
4
5
6
7
8
# 解法二
var uniqueOccurrences = function(arr) {
let map=new Map();
for(let item of arr){
if(map.has(item)){
map.set(item,map.get(item)+1)
}else{
map.set(item,1)
}
}
let set=new Set();
for(let [key, value] of map){
set.add(value)
}
return map.size==set.size;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 独一无二的出现次数
# 题目
给定长度为 2n 的整数数组 nums ,你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), ..., (an, bn) ,使得从 1 到 n 的 min(ai, bi) 总和最大。
示例:
输入:nums = [1,4,3,2]
输出:4
解释:所有可能的分法(忽略元素顺序)为:
1. (1, 4), (2, 3) -> min(1, 4) + min(2, 3) = 1 + 2 = 3
2. (1, 3), (2, 4) -> min(1, 3) + min(2, 4) = 1 + 2 = 3
3. (1, 2), (3, 4) -> min(1, 2) + min(3, 4) = 1 + 3 = 4
所以最大总和为 4
2
3
4
5
6
7
题目链接:https://leetcode-cn.com/problems/array-partition-i/
# 解法
var arrayPairSum = function(nums) {
return nums=nums.sort((a,b)=>a-b).reduce((p,v,index)=>index%2!=0?p:p+v,0)
};
2
3
# 计算力扣银行的钱
# 题目
Hercy 想要为购买第一辆车存钱。他 每天 都往力扣银行里存钱。
最开始,他在周一的时候存入 1 块钱。从周二到周日,他每天都比前一天多存入 1 块钱。在接下来每一个周一,他都会比 前一个周一 多存入 1 块钱。
给你 n ,请你返回在第 n 天结束的时候他在力扣银行总共存了多少块钱。
示例:
输入:n = 10
输出:37
解释:第 10 天后,总额为 (1 + 2 + 3 + 4 + 5 + 6 + 7) + (2 + 3 + 4) = 37 。注意到第二个星期一,Hercy 存入 2 块钱。
2
3
题目链接:https://leetcode-cn.com/problems/calculate-money-in-leetcode-bank/
# 解法
var totalMoney = function(n) {
let money=0;
let sum=0;
for(let i=0;i<n;i++){
money=i%7+Math.floor(i/7)+1;
sum+=money
}
return sum;
};
2
3
4
5
6
7
8
9
# 卡车上的最大单元数
# 题目
请你将一些箱子装在 一辆卡车 上。给你一个二维数组 boxTypes ,其中 boxTypes[i] = [numberOfBoxesi, numberOfUnitsPerBoxi] :
numberOfBoxesi 是类型 i 的箱子的数量。 numberOfUnitsPerBoxi 是类型 i 每个箱子可以装载的单元数量。 整数 truckSize 表示卡车上可以装载 箱子 的 最大数量 。只要箱子数量不超过 truckSize ,你就可以选择任意箱子装到卡车上。
返回卡车可以装载 单元 的 最大 总数。
示例:
输入:boxTypes = [[1,3],[2,2],[3,1]], truckSize = 4
输出:8
解释:箱子的情况如下:
- 1 个第一类的箱子,里面含 3 个单元。
- 2 个第二类的箱子,每个里面含 2 个单元。
- 3 个第三类的箱子,每个里面含 1 个单元。
可以选择第一类和第二类的所有箱子,以及第三类的一个箱子。
单元总数 = (1 * 3) + (2 * 2) + (1 * 1) = 8
2
3
4
5
6
7
8
题目链接:https://leetcode-cn.com/problems/maximum-units-on-a-truck/
# 解法
var maximumUnits = function(boxTypes, truckSize) {
boxTypes.sort((a,b)=>b[1]-a[1])
let sum=0
for(let i=0;i<boxTypes.length;i++){
if(truckSize>=boxTypes[i][0]){
sum+=boxTypes[i][0]*boxTypes[i][1]
truckSize-=boxTypes[i][0]
}else{
sum+=truckSize*boxTypes[i][1];
break;
}
}
return sum;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
# 判断是否互为字符重排
# 题目
给定两个字符串 s1 和 s2,请编写一个程序,确定其中一个字符串的字符重新排列后,能否变成另一个字符串。
示例:
输入: s1 = "abc", s2 = "bca"
输出: true
2
题目链接:https://leetcode-cn.com/problems/check-permutation-lcci/
# 解法
var CheckPermutation = function(s1, s2) {
s1=s1.split('').sort((a,b)=>{
return a.localeCompare(b)
});
s2=s2.split('').sort((a,b)=>{
return a.localeCompare(b)
});
if(s1.length!=s2.length) return false;
for(let index in s1){
if(s2[index]!=s1[index]){
return false
}
}
return true
//return [...s1].sort().join('')==[...s2].sort().join('') 第二种
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 商品折扣后的最终价格
# 题目
给你一个数组 prices ,其中 prices[i] 是商店里第 i 件商品的价格。
商店里正在进行促销活动,如果你要买第 i 件商品,那么你可以得到与 prices[j] 相等的折扣,其中 j 是满足 j > i 且 prices[j] <= prices[i] 的 最小下标 ,如果没有满足条件的 j ,你将没有任何折扣。
请你返回一个数组,数组中第 i 个元素是折扣后你购买商品 i 最终需要支付的价格。
示例:
输入:prices = [8,4,6,2,3]
输出:[4,2,4,2,3]
解释:
商品 0 的价格为 price[0]=8 ,你将得到 prices[1]=4 的折扣,所以最终价格为 8 - 4 = 4 。
商品 1 的价格为 price[1]=4 ,你将得到 prices[3]=2 的折扣,所以最终价格为 4 - 2 = 2 。
商品 2 的价格为 price[2]=6 ,你将得到 prices[3]=2 的折扣,所以最终价格为 6 - 2 = 4 。
商品 3 和 4 都没有折扣
2
3
4
5
6
7
题目链接:https://leetcode-cn.com/problems/final-prices-with-a-special-discount-in-a-shop/
# 解法
var finalPrices = function(prices) {
for(let i=0;i<prices.length;i++){
for(let j=i+1;j<prices.length;j++){
if(prices[i]>=prices[j]){
prices[i]-=prices[j]
break;
}
}
}
return prices;
};
2
3
4
5
6
7
8
9
10
11
# 合并排序的数组
# 题目
给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法,将 B 合并入 A 并排序。初始化 A 和 B 的元素数量分别为 m 和 n。
示例:
输入:
A = [1,2,3,0,0,0], m = 3
B = [2,5,6], n = 3
输出: [1,2,2,3,5,6]
2
3
4
5
题目链接:https://leetcode-cn.com/problems/sorted-merge-lcci/
# 解法
var merge = function(A, m, B, n) {
let index1=m-1,index2=n-1,length=m+n-1
while(index2>=0 && index1>=0){
if(A[index1]<=B[index2]){
A[length]=B[index2]
length--;
index2--
}else{
A[length]=A[index1]
length--
index1--
}
}
while(index1>=0){
A[length--]=A[index1--]
}
while(index2>=0){
A[length--]=B[index2--]
}
return A
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 俩个数组的交集
# 题目
给定两个数组,编写一个函数来计算它们的交集。
示例:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
2
题目链接:https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/
# 解法
var intersect = function(nums1, nums2) {
let arr=[]
for(let i=0;i<nums1.length;i++){
for(let j=0;j<nums2.length;j++){
if(nums1[i]==nums2[j]){
arr.push(nums1[i])
nums1.splice(i,1)
nums2.splice(j,1)
i--;
j--;
}
}
}
return arr;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const intersect = (nums1, nums2) => {
const map = {};
const res = [];
for (const num1 of nums1) { // 记录nums1各个数字的出现次数
if (map[num1]) {
map[num1]++;
} else {
map[num1] = 1;
}
}
for (const num2 of nums2) { // 遍历nums2,看看有没有数字在nums1出现过
const val = map[num2];
if (val > 0) { // 有出现过
res.push(num2); // 推入res数组
map[num2]--; // 匹配掉一个,就减一个
}
}
return res;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 有效的字母异位同
# 题目
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
示例:
输入: s = "anagram", t = "nagaram"
输出: true
2
题目链接:https://leetcode-cn.com/problems/valid-anagram/
# 解法
var isAnagram = function(s, t) {
if(s.length!=t.length){
return false;
}
let arr=new Array(26).fill(0)
for(let i=0;i<s.length;i++){
arr[s.codePointAt(i)-'a'.codePointAt(0)]++
}
for(let j=0;j<t.length;j++){
arr[t.codePointAt(j)-'a'.codePointAt(0)]--
if(arr[t.codePointAt(j)-'a'.codePointAt(0)]<0){
return false
}
}
return true;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 解法
var isAnagram = function(s, t) {
return s.split('').sort().join('')==t.split('').sort().join('');
};
2
3
# 爬楼梯
# 题目
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
示例:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
2
3
4
5
题目链接:https://leetcode-cn.com/problems/climbing-stairs/
# 解法
var climbStairs = function(n) {
let p = 0, q = 0, r = 1;
for (let i = 1; i <= n; ++i) {
p = q;
q = r;
r = p + q;
}
return r;
};
2
3
4
5
6
7
8
9
10
# 子数组最大平均数I
# 题目
给定 n 个整数,找出平均数最大且长度为 k 的连续子数组,并输出该最大平均数。
示例:
输入:[1,12,-5,-6,50,3], k = 4
输出:12.75
解释:最大平均数 (12-5-6+50)/4 = 51/4 = 12.75
2
3
题目链接:https://leetcode-cn.com/problems/maximum-average-subarray-i/
# 解法
var findMaxAverage = function(nums, k) {
let sum=0,max=-Infinity;
for(let i=0;i<=nums.length-k;i++){
for(let j=i;j<k+i;j++){
sum+=nums[j]
}
max=Math.max(max,sum)
sum=0;
}
return max/k;
};
2
3
4
5
6
7
8
9
10
11
# 和为s的连续正数序列
# 题目
输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
示例:
输入:target = 9
输出:[[2,3,4],[4,5]]
2
题目链接:https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/
# 解法一
var findContinuousSequence = function(target) {
let index=Math.floor(target/2)+1
let arr=[],res=[]
let sum=0
for(let i=1;i<=index;i++){
sum+=i;
res.push(i);
while(sum>target){
sum-=res[0];
res.shift();
}
if(sum==target){
arr.push([...res])
}
}
return arr;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 解法二
var findContinuousSequence = function(target) {
let max = Math.floor(target / 2) + 1;
let arr=[],res=[]
let sum=0
for(let i=1;i<=max;i++){
for(let j=i;j<=max;j++){
sum+=j;
res.push(j)
if(sum==target){
arr.push(res)
sum=0;
res=[]
break;
}else if(sum>target){
sum=0;
res=[]
break;
}
}
}
return arr;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 圆圈中最后剩下的数字
# 题目
0,1,···,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字(删除后从下一个数字开始计数)。求出这个圆圈里剩下的最后一个数字。例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
示例:
输入: n = 5, m = 3
输出: 3
2
题目链接:https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/
# 解法
var lastRemaining = function(n, m) {
let arr=[]
for(let i=0;i<n;i++){
arr.push(i)
}
let head=0
while(arr.length>1){
head=(head+m-1)%arr.length;
arr.splice(head,1)
}
return arr[0]
};
2
3
4
5
6
7
8
9
10
11
12
# 字符串压缩
# 题目
字符串压缩。利用字符重复出现的次数,编写一种方法,实现基本的字符串压缩功能。比如,字符串aabcccccaaa会变为a2b1c5a3。若“压缩”后的字符串没有变短,则返回原先的字符串。你可以假设字符串中只包含大小写英文字母(a至z)。
示例:
输入:"aabcccccaaa"
输出:"a2b1c5a3"
2
题目链接:https://leetcode-cn.com/problems/compress-string-lcci/
# 解法一
var compressString = function(S) {
let index=1
let str=''
for(let i=1;i<S.length+1;i++){
if(S[i]==S[i-1]){
index++
}else{
str+=S[i-1]+index
index=1
}
}
return str.length<S.length?str:S;
};
2
3
4
5
6
7
8
9
10
11
12
13
# 解法二
var compressString = function(S) {
let reg=/(\w)\1*/g
s=S.replace(reg,item=>`${item[0]}${item.length}`)
return s.length<S.length?s:S;
};
2
3
4
5
# 整理字符串
# 题目
给你一个由大小写英文字母组成的字符串 s 。
一个整理好的字符串中,两个相邻字符 s[i] 和 s[i+1],其中 0<= i <= s.length-2 ,要满足如下条件:
若 s[i] 是小写字符,则 s[i+1] 不可以是相同的大写字符。 若 s[i] 是大写字符,则 s[i+1] 不可以是相同的小写字符。 请你将字符串整理好,每次你都可以从字符串中选出满足上述条件的 两个相邻 字符并删除,直到字符串整理好为止。
请返回整理好的 字符串 。题目保证在给出的约束条件下,测试样例对应的答案是唯一的。
注意:空字符串也属于整理好的字符串,尽管其中没有任何字符。
示例:
输入:s = "leEeetcode"
输出:"leetcode"
解释:无论你第一次选的是 i = 1 还是 i = 2,都会使 "leEeetcode" 缩减为 "leetcode" 。
2
3
4
题目链接:https://leetcode-cn.com/problems/make-the-string-great/
# 解法一
var makeGood = function(s) {
let arr=s.split('')
const make=(arr)=>{
let stop=true;
for(let i=1;i<arr.length;i++){
if(arr[i].toUpperCase()==arr[i-1].toUpperCase() && arr[i]!=arr[i-1]){
arr.splice(i-1,2)
i--;
stop=false;
break;
}
}
if(stop) return arr;
return make(arr);
}
return make(arr).join('')
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 解法二
var makeGood = function(s) {
let i=0;
let arr=[];
while(i<s.length){
if(arr.length>0 && arr[arr.length-1].toLowerCase()==s[i].toLowerCase() && arr[arr.length-1]!=s[i]){
arr.pop()
}else{
arr.push(s[i])
}
i+=1
}
return arr.join('');
};
2
3
4
5
6
7
8
9
10
11
12
13
14
# 旋转字符串
# 题目
给定两个字符串, A 和 B。A 的旋转操作就是将 A 最左边的字符移动到最右边。 例如, 若 A = 'abcde',在移动一次之后结果就是'bcdea' 。如果在若干次旋转操作之后,A 能变成B,那么返回True。
示例:
示例 1:
输入: A = 'abcde', B = 'cdeab'
输出: true
示例 2:
输入: A = 'abcde', B = 'abced'
输出: false
2
3
4
5
6
7
题目链接:https://leetcode-cn.com/problems/rotate-string/
# 解法一
var rotateString = function(A, B) {
return A.length==B.length&&(A+A).includes(B);
};
2
3
# 解法二
var rotateString = function(A, B) {
if(A.length!=B.length ) return false;
if (A.length === 0) return true
for(let i=0;i<A.length;i++){
A = A.substring(1) + A.substr(0, 1)
if(A==B){
return true
}
}
return false;
};
2
3
4
5
6
7
8
9
10
11
# 亲密字符串
# 题目
给定两个由小写字母构成的字符串 A 和 B ,只要我们可以通过交换 A 中的两个字母得到与 B 相等的结果,就返回 true ;否则返回 false 。交换字母的定义是取两个下标 i 和 j (下标从 0 开始),只要 i!=j 就交换 A[i] 和 A[j] 处的字符。例如,在 "abcd" 中交换下标 0 和下标 2 的元素可以生成 "cbad" 。
示例:
输入: A = "ab", B = "ba"
输出: true
解释: 你可以交换 A[0] = 'a' 和 A[1] = 'b' 生成 "ba",此时 A 和 B 相等。
2
3
题目链接:https://leetcode-cn.com/problems/buddy-strings/
# 解法
var buddyStrings = function(A, B) {
if(A.length!=B.length) return false;
if(A===B) return A.length>(new Set(B)).size
let a='',b=''
for(let i=0;i<A.length;i++){
if(A[i]!=B[i]){
a=A[i]+a
b+=B[i]
}
}
return a.length==2 && a==b
};
2
3
4
5
6
7
8
9
10
11
12
# 分割平衡字符串
# 题目
在一个「平衡字符串」中,'L' 和 'R' 字符的数量是相同的。给出一个平衡字符串 s,请你将它分割成尽可能多的平衡字符串。返回可以通过分割得到的平衡字符串的最大数量。
示例:
输入:s = "RLRRLLRLRL"
输出:4
解释:s 可以分割为 "RL", "RRLL", "RL", "RL", 每个子字符串中都包含相同数量的 'L' 和 'R'。
2
3
题目链接:https://leetcode-cn.com/problems/split-a-string-in-balanced-strings/
# 解法
var balancedStringSplit = function(s) {
let num=0,res=0;
for(let i=0;i<s.length;i++){
if(s[i]=='R'){
num++
}else{
num--
}
if(num==0) res++;
}
return res;
};
2
3
4
5
6
7
8
9
10
11
12
# 压缩字符串
# 题目
给定一组字符,使用原地算法将其压缩。压缩后的长度必须始终小于或等于原数组长度。数组的每个元素应该是长度为1 的字符(不是 int 整数类型)。在完成原地修改输入数组后,返回数组的新长度。
示例:
输入:
["a","a","b","b","c","c","c"]
输出:
返回 6 ,输入数组的前 6 个字符应该是:["a","2","b","2","c","3"]
说明:
"aa" 被 "a2" 替代。"bb" 被 "b2" 替代。"ccc" 被 "c3" 替代。
2
3
4
5
6
题目链接:https://leetcode-cn.com/problems/string-compression/
# 解法
var compress = function(chars) {
let str='123445'
console.log(...str);
let count=1;
for(let i=0;i<chars.length;i++){
if(chars[i]==chars[i+1]){
count++;
}else if(count !== 1){
chars.splice(i - count + 2, count - 1, ...String(count));
i = i - count + 2;
count = 1;
}
}
return chars;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 分糖果 II
# 题目
排排坐,分糖果。
我们买了一些糖果 candies,打算把它们分给排好队的 n = num_people 个小朋友。
给第一个小朋友 1 颗糖果,第二个小朋友 2 颗,依此类推,直到给最后一个小朋友 n 颗糖果。
然后,我们再回到队伍的起点,给第一个小朋友 n + 1 颗糖果,第二个小朋友 n + 2 颗,依此类推,直到给最后一个小朋友 2 * n 颗糖果。
重复上述过程(每次都比上一次多给出一颗糖果,当到达队伍终点后再次从队伍起点开始),直到我们分完所有的糖果。注意,就算我们手中的剩下糖果数不够(不比前一次发出的糖果多),这些糖果也会全部发给当前的小朋友。
返回一个长度为 num_people、元素之和为 candies 的数组,以表示糖果的最终分发情况(即 ans[i] 表示第 i 个小朋友分到的糖果数)。
示例:
输入:candies = 7, num_people = 4
输出:[1,2,3,1]
解释:
第一次,ans[0] += 1,数组变为 [1,0,0,0]。
第二次,ans[1] += 2,数组变为 [1,2,0,0]。
第三次,ans[2] += 3,数组变为 [1,2,3,0]。
第四次,ans[3] += 1(因为此时只剩下 1 颗糖果),最终数组变为 [1,2,3,1]。
2
3
4
5
6
7
8
题目链接:https://leetcode-cn.com/problems/distribute-candies-to-people/
# 解法一
var distributeCandies = function(candies, num_people) {
let arr=new Array(num_people).fill(0)
let num=0;
while(num<candies){
arr[num%num_people]+=(++num)
candies-=num
}
arr[num%num_people]+=candies
return arr;
};
2
3
4
5
6
7
8
9
10
# 解法二
var distributeCandies = function(candies, num_people) {
let index=1;
let arr=new Array(num_people).fill(0);
let sum=0;
while(sum<candies){
for(let i=0;i<num_people;i++){
arr[i]+=index;
sum+=index;
if(sum>=candies){
let len=candies-(sum-index);
if(len==0) break;
arr[i]=arr[i]-index+len;
break;
}
index++;
}
}
return arr;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 分饼干
# 题目
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
示例:
输入: g = [1,2,3], s = [1,1]
输出: 1
解释:
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。
2
3
4
5
6
题目链接:https://leetcode-cn.com/problems/assign-cookies/
# 解法
var findContentChildren = function(g, s) {
g.sort((a,b)=>a-b);
s.sort((a,b)=>a-b);
let child=0,cookie=0;
while(child<g.length && cookie<s.length){
if(g[child]<=s[cookie]){
child++
}
cookie++
}
return child
};
2
3
4
5
6
7
8
9
10
11
12
# 最小差值I
# 题目
给你一个整数数组 A,请你给数组中的每个元素 A[i] 都加上一个任意数字 x (-K <= x <= K),从而得到一个新数组 B 。返回数组 B 的最大值和最小值之间可能存在的最小差值。
示例:
输入:A = [1,3,6], K = 3
输出:0
解释:B = [3,3,3] 或 B = [4,4,4]
2
3
题目链接:https://leetcode-cn.com/problems/smallest-range-i/
# 解法
var smallestRangeI = function(A, K) {
let min=Math.min(...A)
let max=Math.max(...A)
return Math.max(0,max-min-2*K)
};
2
3
4
5
# 删除相邻字符串
# 题目
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。在 S 上反复执行重复项删除操作,直到无法继续删除。在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例:
输入:"abbaca"
输出:"ca"
解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。
2
3
4
题目链接:https://leetcode-cn.com/problems/remove-all-adjacent-duplicates-in-string/
# 解法一
var removeDuplicates = function(S) {
let i=0;
S=S.split('')
while(i<S.length){
if(S[i]==S[i+1]){
S.splice(i,2)
i=0;
}else{
i++;
}
}
return S.join('')
};
2
3
4
5
6
7
8
9
10
11
12
13
# 解法二
var removeDuplicates = function(S) {
let stack=[]
let i=0;
while(i<S.length){
if(S[i]==stack[stack.length-1]){
stack.pop()
}else{
stack.push(S[i])
}
i++;
}
return stack.join('')
}
2
3
4
5
6
7
8
9
10
11
12
13
# 反转字符串II
# 题目
给定一个字符串 s 和一个整数 k,你需要对从字符串开头算起的每隔 2k 个字符的前 k 个字符进行反转。如果剩余字符少于 k 个,则将剩余字符全部反转。如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。
示例:
输入: s = "abcdefg", k = 2
输出: "bacdfeg"
2
题目链接:https://leetcode-cn.com/problems/reverse-string-ii/
# 解法
var reverseStr = function(s, k) {
let str='',n=0;
for(let i=0;i<s.length;i=i+k){
let t=s.slice(i,i+k)
if(n%2==0){
t=t.split('').reverse().join('')
}
n++;
str+=t
}
return str
};
2
3
4
5
6
7
8
9
10
11
12
# 赎金信
# 题目
给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串 ransom 能不能由第二个字符串 magazines 里面的字符构成。如果可以构成,返回 true ;否则返回 false。
示例:
canConstruct("a", "b") -> false
canConstruct("aa", "ab") -> false
canConstruct("aa", "aab") -> true
2
3
题目链接:https://leetcode-cn.com/problems/ransom-note/
# 解法
var canConstruct = function(ransomNote, magazine) {
for(let i=0;i<ransomNote.length;i++){
if(magazine.indexOf(ransomNote[i])==-1) return false;
magazine=magazine.replace(ransomNote[i],'')
}
return true;
};
2
3
4
5
6
7
# 矩形中的幸运数
# 题目
给你一个 m * n 的矩阵,矩阵中的数字 各不相同 。请你按 任意 顺序返回矩阵中的所有幸运数。
幸运数是指矩阵中满足同时下列两个条件的元素:
- 在同一行的所有元素中最小
- 在同一列的所有元素中最大
示例:
输入:matrix = [[3,7,8],[9,11,13],[15,16,17]]
输出:[15]
解释:15 是唯一的幸运数,因为它是其所在行中的最小值,也是所在列中的最大值。
2
3
题目链接:https://leetcode-cn.com/problems/lucky-numbers-in-a-matrix/
# 解法
var luckyNumbers = function(matrix) {
let m=matrix.length,n=matrix[0].length;
let set=new Set()
for(let i=0;i<m;i++){
let min=matrix[i][0]
let k=0;
for(let j=1;j<n;j++){
if(matrix[i][j]<min){
min=matrix[i][j]
k=j;
}
}
let x=0;
for(;x<m;x++){
if(matrix[x][k]>min) break;
}
if(x==m) set.add(min)
}
return [...set]
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 判断字符串的俩半是否相似
# 题目
给你一个偶数长度的字符串 s 。将其拆分成长度相同的两半,前一半为 a ,后一半为 b 。
两个字符串 相似 的前提是它们都含有相同数目的元音('a','e','i','o','u','A','E','I','O','U')。注意,s 可能同时含有大写和小写字母。
如果 a 和 b 相似,返回 true ;否则,返回 false 。
示例:
输入:s = "book"
输出:true
解释:a = "bo" 且 b = "ok" 。a 中有 1 个元音,b 也有 1 个元音。所以,a 和 b 相似。
2
3
题目链接:https://leetcode-cn.com/problems/determine-if-string-halves-are-alike
# 解法
var halvesAreAlike = function(s) {
let set=new Set(['a','e','i','o','u'])
s=s.toLowerCase()
let len=s.length;
let index1=0,index2=0
for(let i=0;i<len;i++){
i<len/2?(set.has(s[i])?index1++:0):(set.has(s[i])?index2++:0)
}
return index1==index2
};
2
3
4
5
6
7
8
9
10
# 最小绝对值
# 题目
给你个整数数组 arr,其中每个元素都 不相同。请你找到所有具有最小绝对差的元素对,并且按升序的顺序返回。
示例:
输入:arr = [4,2,1,3]
输出:[[1,2],[2,3],[3,4]]
2
题目链接:https://leetcode-cn.com/problems/minimum-absolute-difference/
# 解法
var minimumAbsDifference = function(arr) {
arr=arr.sort((a,b)=>a-b)
let min=arr[1]-arr[0];
let res=[]
for(let i=1;i<arr.length;i++){
let temp=arr[i]-arr[i-1]
let a=[arr[i-1],arr[i]]
if(temp<min){
res=[a]
min=temp
}else if (temp==min){
res.push(a)
}
}
return res;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 重复的字符字串
# 题目
给定一个非空的字符串,判断它是否可以由它的一个子串重复多次构成。给定的字符串只含有小写英文字母,并且长度不超过10000。
示例:
输入: "abab"
输出: True
解释: 可由子字符串 "ab" 重复两次构成。
2
3
题目链接:https://leetcode-cn.com/problems/repeated-substring-pattern/
# 解法一
var repeatedSubstringPattern = function(s) {
let s1=(s+s).slice(1,-1)
return s1.indexOf(s)!=-1
};
2
3
4
# 解法二
var repeatedSubstringPattern = function(s) {
return /^([a-z]+)\1+$/.test(s)
};
2
3
# 区域和检索 - 数组不可变
# 题目
给定一个整数数组 nums,求出数组从索引 i 到 j(i ≤ j)范围内元素的总和,包含 i、j 两点。
实现 NumArray 类:
- NumArray(int[] nums) 使用数组 nums 初始化对象
- int sumRange(int i, int j) 返回数组 nums 从索引 i 到 j(i ≤ j)范围内元素的总和,包含 i、j 两点(也就是 sum(nums[i], nums[i + 1], ... , nums[j])) 示例:
输入:
["NumArray", "sumRange", "sumRange", "sumRange"]
[[[-2, 0, 3, -5, 2, -1]], [0, 2], [2, 5], [0, 5]]
输出:
[null, 1, -1, -3]
解释:
NumArray numArray = new NumArray([-2, 0, 3, -5, 2, -1]);
numArray.sumRange(0, 2); // return 1 ((-2) + 0 + 3)
numArray.sumRange(2, 5); // return -1 (3 + (-5) + 2 + (-1))
numArray.sumRange(0, 5); // return -3 ((-2) + 0 + 3 + (-5) + 2 + (-1))
2
3
4
5
6
7
8
9
10
11
题目链接:https://leetcode-cn.com/problems/range-sum-query-immutable
# 解法一
/**
* @param {number[]} nums
*/
var NumArray = function(nums) {
const preSum = new Array(nums.length + 1);
preSum[0] = 0;
for (let i = 0; i < nums.length; i++) {
preSum[i + 1] = preSum[i] + nums[i];
}
this.preSum = preSum;
};
/**
* @param {number} i
* @param {number} j
* @return {number}
*/
NumArray.prototype.sumRange = function(i, j) {
return this.preSum[j+1]- this.preSum[i]
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 气球的最大数量
# 题目
给你一个字符串 text,你需要使用 text 中的字母来拼凑尽可能多的单词 "balloon"(气球)。字符串 text 中的每个字母最多只能被使用一次。请你返回最多可以拼凑出多少个单词 "balloon"。
示例:
输入:text = "nlaebolko"
输出:1
2
题目链接:https://leetcode-cn.com/problems/maximum-number-of-balloons/
# 解法一
var maxNumberOfBalloons = function(text) {
var obj={
'a':0,
'b':0,
'l':0,
'o':0,
'n':0
}
let map=new Map(Object.entries(obj))
for(let i=0;i<text.length;i++){
if(text[i]=='b'){
map.set('b',map.get('b')+1)
}else if(text[i]=='a'){
map.set('a',map.get('a')+1)
}else if(text[i]=='l'){
map.set('l',map.get('l')+0.5)
}else if(text[i]=='o'){
map.set('o',map.get('o')+0.5)
}else if(text[i]=='n'){
map.set('n',map.get('n')+1)
}
}
return Math.floor(Math.min(...map.values()))
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 气球的最大数量
# 题目
某种外星语也使用英文小写字母,但可能顺序 order 不同。字母表的顺序(order)是一些小写字母的排列。给定一组用外星语书写的单词 words,以及其字母表的顺序 order,只有当给定的单词在这种外星语中按字典序排列时,返回 true;否则,返回 false。
示例:
输入:words = ["hello","leetcode"], order = "hlabcdefgijkmnopqrstuvwxyz"
输出:true
解释:在该语言的字母表中,'h' 位于 'l' 之前,所以单词序列是按字典序排列的。
2
3
题目链接:https://leetcode-cn.com/problems/verifying-an-alien-dictionary/
# 解法
var isAlienSorted = function(words, order) {
for(let i=0;i<words.length-1;i++){
let word1=words[i]
let word2=words[i+1]
let continueCompare = true;
for(let j=0;j<Math.min(word1.length,word2.length) && continueCompare;j++){
if(word1[j]!=word2[j]){
if(order.indexOf(word1[j])>order.indexOf(word2[j])){
return false;
}else{
continueCompare=false;
}
}
}
if (word1.length> word2.length&& continueCompare) return false;
}
return true;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 早餐组合
# 题目
小扣在秋日市集选择了一家早餐摊位,一维整型数组 staple 中记录了每种主食的价格,一维整型数组 drinks 中记录了每种饮料的价格。小扣的计划选择一份主食和一款饮料,且花费不超过 x 元。请返回小扣共有多少种购买方案。注意:答案需要以 1e9 + 7 (1000000007) 为底取模,如:计算初始结果为:1000000008,请返回 1
示例:
输入:staple = [10,20,5], drinks = [5,5,2], x = 15
输出:6
2
题目链接:https://leetcode-cn.com/problems/2vYnGI/
# 解法(双指针)
var breakfastNumber = function(staple, drinks, x) {
let index=0
staple=staple.sort((a,b)=>a-b)
drinks=drinks.sort((a,b)=>a-b)
let len1=staple.length,len2=drinks.length
let i=0;j=len2-1;
while(i<len1 && j>=0){
if(staple[i]+drinks[j]<=x){
index+=j+1; //如果此时j符合,那么之前的全都符合
i++;
}else{
j--;
}
}
return index%1000000007;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 单词规律
# 题目
给定一种规律 pattern 和一个字符串 str ,判断 str 是否遵循相同的规律。这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 str 中的每个非空单词之间存在着双向连接的对应规律。
示例:
输入: pattern = "abba", str = "dog cat cat dog"
输出: true
2
题目链接:https://leetcode-cn.com/problems/word-pattern/
# 解法(双指针)
var wordPattern = function(pattern, s) {
s=s.split(' ')
if(pattern.length!=s.length) return false;
for(let i=0;i<s.length;i++){
if(pattern.indexOf(pattern[i])!=s.indexOf(s[i])){
return false;
}
}
return true;
};
2
3
4
5
6
7
8
9
10
# 反转字符串中的元音字母
# 题目
编写一个函数,以字符串作为输入,反转该字符串中的元音字母。
示例:
输入:"hello"
输出:"holle"
2
题目链接:https://leetcode-cn.com/problems/reverse-vowels-of-a-string/
# 解法(双指针)
var reverseVowels = function(s) {
let set = new Set(['a','e','i','o','u','A','E','I','O','U']);
let arr = s.split('');
let i =0;
let j = arr.length-1;
while(i<j){
if(set.has(arr[i])){ // 左边是否有元音字母
if(set.has(arr[j])){ // 如果左边有元音字母,右边也有,那么交换
[arr[i],arr[j]] = [arr[j],arr[i]];
i++;
}
j--;
}else{
i++;
}
}
return arr.join('')
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 拆炸弹
# 题目
你有一个炸弹需要拆除,时间紧迫!你的情报员会给你一个长度为 n 的 循环 数组 code 以及一个密钥 k 。
为了获得正确的密码,你需要替换掉每一个数字。所有数字会 同时 被替换。
- 如果 k > 0 ,将第 i 个数字用 接下来 k 个数字之和替换。
- 如果 k < 0 ,将第 i 个数字用 之前 k 个数字之和替换。
- 如果 k == 0 ,将第 i 个数字用 0 替换。 由于 code 是循环的, code[n-1] 下一个元素是 code[0] ,且 code[0] 前一个元素是 code[n-1] 。
给你 循环 数组 code 和整数密钥 k ,请你返回解密后的结果来拆除炸弹!
示例:
输入:code = [5,7,1,4], k = 3
输出:[12,10,16,13]
解释:每个数字都被接下来 3 个数字之和替换。解密后的密码为 [7+1+4, 1+4+5, 4+5+7, 5+7+1]。注意到数组是循环连接的
2
3
题目链接:https://leetcode-cn.com/problems/defuse-the-bomb
# 解法
var decrypt = function(code, k) {
let res=[]
let len=code.length;
if(k==0) res=new Array(len).fill(0)
if(k>0){
for(let i=0;i<len;i++){
let sum=0,index=i
for(let j=0;j<k;j++){
sum+=code[(++index)%len]
}
res.push(sum)
}
}
if(k<0){
for(let i=0;i<len;i++){
let sum=0,index=i
for(let j=0;j<-k;j++){
sum+=code[(--index+len)%len]
}
res.push(sum)
}
}
return res;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 删除回文子序列
# 题目
给你一个字符串 s,它仅由字母 'a' 和 'b' 组成。每一次删除操作都可以从 s 中删除一个回文 子序列。返回删除给定字符串中所有字符(字符串为空)的最小删除次数。
「子序列」定义:如果一个字符串可以通过删除原字符串某些字符而不改变原字符顺序得到,那么这个字符串就是原字符串的一个子序列。
「回文」定义:如果一个字符串向后和向前读是一致的,那么这个字符串就是一个回文。
示例:
输入:s = "abb"
输出:2
解释:"abb" -> "bb" -> "".
先删除回文子序列 "a",然后再删除 "bb"。
2
3
4
题目链接:https://leetcode-cn.com/problems/remove-palindromic-subsequences/
# 解法(双指针)
var removePalindromeSub = function(s) {
if (s.length === 0) return 0;
for (let left = 0, right = s.length - 1; left < right; ++left, --right) {
if (s[left] !== s[right]) return 2;
}
return 1;
};
2
3
4
5
6
7
# 柠檬水找零
# 题目
在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。注意,一开始你手头没有任何零钱。如果你能给每位顾客正确找零,返回 true ,否则返回 false 。
示例:
输入:[5,5,5,10,20]
输出:true
解释:
前 3 位顾客那里,我们按顺序收取 3 张 5 美元的钞票。
第 4 位顾客那里,我们收取一张 10 美元的钞票,并返还 5 美元。
第 5 位顾客那里,我们找还一张 10 美元的钞票和一张 5 美元的钞票。
由于所有客户都得到了正确的找零,所以我们输出 true。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/lemonade-change
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2
3
4
5
6
7
8
9
10
11
题目链接:https://leetcode-cn.com/problems/lemonade-change
# 解法(双指针)
var lemonadeChange = function(bills) {
let sum=0;
let five=0,ten=0;
for(let i=0;i<bills.length;i++){
if(bills[i]==5) five++;
if(bills[i]==10){
five--;
ten++;
if(five<0) return false;
}
if(bills[i]==20){
if(ten>0){
ten--;
five--;
}else{
five=five-3;
}
if(five<0 || ten<0) return false;
}
}
return true;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 最长回文串
# 题目
给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。在构造过程中,请注意区分大小写。比如 "Aa" 不能当做一个回文字符串。
示例:
输入:
"abccccdd"
输出:
7
解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。
2
3
4
5
6
7
8
题目链接:https://leetcode-cn.com/problems/longest-palindrome/
# 解法(双指针)
var longestPalindrome = function(s) {
let map=new Map();
let count=0;
for(let item of s){
if(map.has(item)){
map.delete(item)
count+=2;
}else{
map.set(item,1)
}
}
return count<s.length?count+1:count;
};
2
3
4
5
6
7
8
9
10
11
12
13
# 使用最小花费爬楼梯
# 题目
数组的每个下标作为一个阶梯,第 i 个阶梯对应着一个非负数的体力花费值 cost[i](下标从 0 开始)。每当你爬上一个阶梯你都要花费对应的体力值,一旦支付了相应的体力值,你就可以选择向上爬一个阶梯或者爬两个阶梯。请你找出达到楼层顶部的最低花费。在开始时,你可以选择从下标为 0 或 1 的元素作为初始阶梯。
示例:
输入:cost = [10, 15, 20]
输出:15
解释:最低花费是从 cost[1] 开始,然后走两步即可到阶梯顶,一共花费 15 。
2
3
题目链接:https://leetcode-cn.com/problems/min-cost-climbing-stairs/
# 解法(双指针)
var minCostClimbingStairs = function(cost) {
let len=cost.length;
for(let i=2;i<len;i++){
cost[i]+=Math.min(cost[i-1],cost[i-2])
}
return Math.min(cost[len-1],cost[len-2]);
};
2
3
4
5
6
7
# K 次取反后最大化的数组和
# 题目
给定一个整数数组 A,我们只能用以下方法修改该数组:我们选择某个索引 i 并将 A[i] 替换为 -A[i],然后总共重复这个过程 K 次。(我们可以多次选择同一个索引 i。)以这种方式修改数组后,返回数组可能的最大和。
示例:
输入:A = [4,2,3], K = 1
输出:5
解释:选择索引 (1,) ,然后 A 变为 [4,-2,3]。
2
3
题目链接:https://leetcode-cn.com/problems/maximize-sum-of-array-after-k-negations/
# 解法(双指针)
var largestSumAfterKNegations = function(A, K) {
A=A.sort((a,b)=>a-b)
for(let i=0;i<A.length;i++){
if(A[i]<0 && K>0){
A[i]=-A[i]
K--;
}
}
A=A.sort((a,b)=>a-b)
if(K>0){
if(K%2!=0){
A[0]=-A[0]
}
}
return A.reduce((p,v)=>p+v)
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 是否所有 1 都至少相隔 k 个元素
# 题目
给你一个由若干 0 和 1 组成的数组 nums 以及整数 k。如果所有 1 都至少相隔 k 个元素,则返回 True ;否则,返回 False 。
示例:
输入:nums = [1,0,0,0,1,0,0,1], k = 2
输出:true
解释:每个 1 都至少相隔 2 个元素。
2
3
题目链接:https://leetcode-cn.com/problems/check-if-all-1s-are-at-least-length-k-places-away/
# 解法(双指针)
var kLengthApart = function(nums, k) {
let prev=-1
for(let i=0;i<nums.length;++i){
if(nums[i]==1){
if(prev!=-1 && i-prev-1<k){
return false;
}
prev=i
}
}
return true;
};
2
3
4
5
6
7
8
9
10
11
12
# 最短补全词
# 题目
给定一个字符串牌照 licensePlate 和一个字符串数组 words ,请你找出并返回 words 中的 最短补全词 。
如果单词列表(words)中的一个单词包含牌照(licensePlate)中所有的字母,那么我们称之为 补全词 。在所有完整词中,最短的单词我们称之为 最短补全词 。
单词在匹配牌照中的字母时要:
- 忽略牌照中的数字和空格。
- 不区分大小写,比如牌照中的 "P" 依然可以匹配单词中的 "p" 字母。
- 如果某个字母在牌照中出现不止一次,那么该字母在补全词中的出现次数应当一致或者更多。
例如:licensePlate = "aBc 12c",那么它由字母 'a'、'b' (忽略大写)和两个 'c' 。可能的 补全词 是 "abccdef"、"caaacab" 以及 "cbca" 。
题目数据保证一定存在一个最短补全词。当有多个单词都符合最短补全词的匹配条件时取单词列表中最靠前的一个。
示例:
输入:licensePlate = "1s3 PSt", words = ["step", "steps", "stripe", "stepple"]
输出:"steps"
说明:最短补全词应该包括 "s"、"p"、"s" 以及 "t"。在匹配过程中我们忽略牌照中的大小写。
"step" 包含 "t"、"p",但只包含一个 "s",所以它不符合条件。
"steps" 包含 "t"、"p" 和两个 "s"。
"stripe" 缺一个 "s"。
"stepple" 缺一个 "s"。
因此,"steps" 是唯一一个包含所有字母的单词,也是本样例的答案。
2
3
4
5
6
7
8
9
题目链接:https://leetcode-cn.com/problems/shortest-completing-word
# 解法(双指针)
var shortestCompletingWord = function(licensePlate, words) {
licensePlate=licensePlate.replace(/\s|\d/g,'').toLowerCase()
let arr=[]
for(let item of licensePlate){
arr.push(item.charCodeAt()-97)
}
return words.filter(word=>{
let map=new Array(26).fill(0)
for(let i=0;i<word.length;i++){
map[word[i].charCodeAt()-97]++
}
for(let item of arr){
if(--map[item]<0){
return false;
}
}
return true;
}).sort((a, b) => a.length - b.length)[0]
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 仅仅反转字母
# 题目
给定一个字符串 S,返回 “反转后的” 字符串,其中不是字母的字符都保留在原地,而所有字母的位置发生反转。
示例:
输入:"Test1ng-Leet=code-Q!"
输出:"Qedo1ct-eeLg=ntse-T!"
2
题目链接:https://leetcode-cn.com/problems/reverse-only-letters/
# 解法
var reverseOnlyLetters = function(S) {
const arr =S.replace(/[^a-z]/ig,'').split('').reverse();
console.log(arr);
return S.split('').map(s=>{
return /[a-z]/i.test(s)?arr.shift():s
}).join('')
};
2
3
4
5
6
7
8
# 三个数的最大乘积
# 题目
给你一个整型数组 nums ,在数组中找出由三个数组成的最大乘积,并输出这个乘积。
示例:
输入:nums = [1,2,3]
输出:6
2
题目链接:https://leetcode-cn.com/problems/maximum-product-of-three-numbers/
# 解法
var maximumProduct = function(nums) {
nums=nums.sort((a,b)=>a-b)
let len=nums.length;
return Math.max(nums[len-1]*nums[len-2]*nums[len-3],nums[len-1]*nums[1]*nums[0]);
};
2
3
4
5
# 比较含退格的字符串
# 题目
给定 S 和 T 两个字符串,当它们分别被输入到空白的文本编辑器后,判断二者是否相等,并返回结果。 # 代表退格字符。
示例:
输入:S = "ab#c", T = "ad#c"
输出:true
解释:S 和 T 都会变成 “ac”。
2
3
题目链接:https://leetcode-cn.com/problems/backspace-string-compare/
# 解法
var backspaceCompare = function(S, T) {
var c = (s, a = []) => {
for(var i = 0; i < s.length; i++)
s[i] === '#' ? a.pop() : a.push(s[i])
return a.join('')
}
return c(S) === c(T)
};
2
3
4
5
6
7
8
# 两个列表的最小索引总和
# 题目
假设Andy和Doris想在晚餐时选择一家餐厅,并且他们都有一个表示最喜爱餐厅的列表,每个餐厅的名字用字符串表示。你需要帮助他们用最少的索引和找出他们共同喜爱的餐厅。 如果答案不止一个,则输出所有答案并且不考虑顺序。 你可以假设总是存在一个答案。
示例:
输入:
["Shogun", "Tapioca Express", "Burger King", "KFC"]
["Piatti", "The Grill at Torrey Pines", "Hungry Hunter Steakhouse", "Shogun"]
输出: ["Shogun"]
解释: 他们唯一共同喜爱的餐厅是“Shogun”。
2
3
4
5
题目链接:https://leetcode-cn.com/problems/minimum-index-sum-of-two-lists
# 解法
var findRestaurant = function(list1, list2) {
let map=new Map()
let res=[]
list1.forEach(item=>{
if(list2.includes(item)){
map.set(item,list2.indexOf(item)+list1.indexOf(item))
}
})
let min=Math.min.apply(Math,[...map.values()])
for (let [key, val] of map) {
if (val === min) {
res.push(key)
}
}
return res;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 字符串相加
# 题目
给定两个字符串形式的非负整数 num1 和num2 ,计算它们的和。
题目链接:https://leetcode-cn.com/problems/add-strings/
# 解法
var addStrings = function(num1, num2) {
let i=num1.length-1,j=num2.length-1,add=0;
let res=[]
while(i>=0 || j>=0 || add!=0){
const x = i >= 0 ? num1.charAt(i) - '0' : 0;
const y = j >= 0 ? num2.charAt(j) - '0' : 0;
let result=x + y + add;
res.push(result%10)
add= Math.floor(result / 10);
i-=1
j-=1;
}
return res.reverse().join('')
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 找到小镇的法官
# 题目
在一个小镇里,按从 1 到 N 标记了 N 个人。传言称,这些人中有一个是小镇上的秘密法官。
如果小镇的法官真的存在,那么:
小镇的法官不相信任何人。
- 每个人(除了小镇法官外)都信任小镇的法官。
- 只有一个人同时满足属性 1 和属性 2 。
- 给定数组 trust,该数组由信任对 trust[i] = [a, b] 组成,表示标记为 a 的人信任标记为 b 的人。
如果小镇存在秘密法官并且可以确定他的身份,请返回该法官的标记。否则,返回 -1。
示例:
输入:N = 4, trust = [[1,3],[1,4],[2,3],[2,4],[4,3]]
输出:3
2
题目链接:https://leetcode-cn.com/problems/find-the-town-judge
# 解法
let findJudge = function(N, trust) {
let graph = Array(N+1).fill(0)
// 出度加一
// 入度减一
trust.forEach(([a, b]) => {
graph[a]--
graph[b]++
})
return graph.findIndex((node, index) => {
// 剔除0
return index != 0 && node === N-1
})
};
2
3
4
5
6
7
8
9
10
11
12
13
# 最长和谐子序列
# 题目
和谐数组是指一个数组里元素的最大值和最小值之间的差别 正好是 1 。现在,给你一个整数数组 nums ,请你在所有可能的子序列中找到最长的和谐子序列的长度。数组的子序列是一个由数组派生出来的序列,它可以通过删除一些元素或不删除元素、且不改变其余元素的顺序而得到。
示例:
输入:nums = [1,3,2,2,5,2,3,7]
输出:5
解释:最长的和谐子序列是 [3,2,2,2,3]
2
3
题目链接:https://leetcode-cn.com/problems/longest-harmonious-subsequence/
# 解法
var findLHS = function(nums) {
let max=0;
for(let i=0;i<nums.length;i++){
let count=0
flag=false;
for(let j=0;j<nums.length;j++){
if(nums[j]==nums[i]){
count++
}else if(nums[j]==nums[i]+1){
count++
flag=true;
}
if(flag) max=Math.max(max,count);
}
}
return max;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 仅执行一次字符串交换能否使两个字符串相等
# 题目
给你长度相等的两个字符串 s1 和 s2 。一次 字符串交换 操作的步骤如下:选出某个字符串中的两个下标(不必不同),并交换这两个下标所对应的字符。如果对 其中一个字符串 执行 最多一次字符串交换 就可以使两个字符串相等,返回 true ;否则,返回 false 。
示例:
输入:s1 = "bank", s2 = "kanb"
输出:true
解释:例如,交换 s2 中的第一个和最后一个字符可以得到 "bank"
2
3
题目链接:https://leetcode-cn.com/problems/check-if-one-string-swap-can-make-strings-equal
# 解法
var areAlmostEqual = function(s1, s2) {
if(s1==s2) return true;
for(let i=0;i<s2.length;i++){
for(let j=i+1;j<s2.length;j++){
let s22=s2.split('')
let temp=s22[i]
s22[i]=s22[j]
s22[j]=temp
if(s1==s22.join('')) return true;
}
}
return false;
};
2
3
4
5
6
7
8
9
10
11
12
13
# 判断子序列
# 题目
给定字符串 s 和 t ,判断 s 是否为 t 的子序列。字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串。(例如,"ace"是"abcde"的一个子序列,而"aec"不是)。。
示例:
输入:s = "abc", t = "ahbgdc"
输出:true
2
题目链接:https://leetcode-cn.com/problems/is-subsequence
# 解法一
var isSubsequence = function(s, t) {
if(s.length==0) return true;
let subIndex=0,index=0;
while(index<t.length){
if(s[subIndex]==t[index]){
subIndex++;
if(subIndex>s.length-1){
return true;
}
}
index++;
}
return false;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 解法二
var isSubsequence = function(s, t) {
if(s.length==0) return true;
let num=0
for(let i=0;i<s.length;i++){
if(t.indexOf(s[i],num)!=-1){
if(num>t.indexOf(s[i],num)){
return false;
}
num=t.indexOf(s[i],num)+1
}else{
return false;
}
}
return true;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 重新排列单词间的空格
# 题目
给你一个字符串 text ,该字符串由若干被空格包围的单词组成。每个单词由一个或者多个小写英文字母组成,并且两个单词之间至少存在一个空格。题目测试用例保证 text 至少包含一个单词 。
请你重新排列空格,使每对相邻单词之间的空格数目都 相等 ,并尽可能 最大化 该数目。如果不能重新平均分配所有空格,请 将多余的空格放置在字符串末尾 ,这也意味着返回的字符串应当与原 text 字符串的长度相等。
返回 重新排列空格后的字符串 。
示例:
输入:text = " practice makes perfect"
输出:"practice makes perfect "
解释:总共有 7 个空格和 3 个单词。7 / (3-1) = 3 个空格加上 1 个多余的空格。多余的空格需要放在字符串的末尾。
2
3
题目链接:https://leetcode-cn.com/problems/rearrange-spaces-between-words/
# 解法
var reorderSpaces = function(text) {
if (!text.includes(' ')) return text;
let len = text.match(/ /g).length;
let str = text.match(/\w+/g)
if (str.length === 1) return str[0] + ' '.repeat(len);
let c = len / (str.length - 1) | 0, e = len % (str.length - 1);
return str.join(' '.repeat(c)) + ' '.repeat(e);
};
2
3
4
5
6
7
8
# 矩阵对角线元素的和
# 题目
给你一个正方形矩阵 mat,请你返回矩阵对角线元素的和。请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。
示例:
输入:mat = [[1,2,3],
[4,5,6],
[7,8,9]]
输出:25
解释:对角线的和为:1 + 5 + 9 + 3 + 7 = 25
请注意,元素 mat[1][1] = 5 只会被计算一次。
2
3
4
5
6
7
题目链接:https://leetcode-cn.com/problems/matrix-diagonal-sum
# 解法
var diagonalSum = function(mat) {
let len=mat.length,sum=0
for(let i=0;i<len;i++){
for(let j=0;j<mat[0].length;j++){
if(i==j || i+j==len-1){
sum+=mat[i][j]
}
}
}
return sum;
};
2
3
4
5
6
7
8
9
10
11
# 上升下降字符串
# 题目
给你一个字符串 s ,请你根据下面的算法重新构造字符串:
- 从 s 中选出 最小 的字符,将它 接在 结果字符串的后面。
- 从 s 剩余字符中选出 最小 的字符,且该字符比上一个添加的字符大,将它 接在 结果字符串后面。
- 重复步骤 2 ,直到你没法从 s 中选择字符。
- 从 s 中选出 最大 的字符,将它 接在 结果字符串的后面。
- 从 s 剩余字符中选出 最大 的字符,且该字符比上一个添加的字符小,将它 接在 结果字符串后面。
- 重复步骤 5 ,直到你没法从 s 中选择字符。
- 重复步骤 1 到 6 ,直到 s 中所有字符都已经被选过。
在任何一步中,如果最小或者最大字符不止一个 ,你可以选择其中任意一个,并将其添加到结果字符串。
请你返回将 s 中字符重新排序后的 结果字符串 。
示例:
输入:s = "aaaabbbbcccc"
输出:"abccbaabccba"
解释:第一轮的步骤 1,2,3 后,结果字符串为 result = "abc"
第一轮的步骤 4,5,6 后,结果字符串为 result = "abccba"
第一轮结束,现在 s = "aabbcc" ,我们再次回到步骤 1
第二轮的步骤 1,2,3 后,结果字符串为 result = "abccbaabc"
第二轮的步骤 4,5,6 后,结果字符串为 result = "abccbaabccba"
2
3
4
5
6
7
8
题目链接:https://leetcode-cn.com/problems/increasing-decreasing-string
# 解法
var sortString = function(s) {
let arr=new Array(26).fill(0);
let str=''
for(let item of s){
arr[item.charCodeAt()-'a'.charCodeAt()]++
}
while(str.length<s.length){
for(let i=0;i<arr.length;i++){
if(arr[i]){
str+=String.fromCharCode(i+'a'.charCodeAt())
arr[i]--
}
}
for(let i=arr.length-1;i>=0;i--){
if(arr[i]){
str+=String.fromCharCode(i+'a'.charCodeAt())
arr[i]--
}
}
}
return str;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 字符的最短距离
# 题目
给你一个字符串 s 和一个字符 c ,且 c 是 s 中出现过的字符。返回一个整数数组 answer ,其中 answer.length == s.length 且 answer[i] 是 s 中从下标 i 到离它 最近 的字符 c 的 距离 。两个下标 i 和 j 之间的 距离 为 abs(i - j) ,其中 abs 是绝对值函数。
示例:
输入:s = "loveleetcode", c = "e"
输出:[3,2,1,0,1,0,0,1,2,2,1,0]
解释:字符 'e' 出现在下标 3、5、6 和 11 处(下标从 0 开始计数)。
距下标 0 最近的 'e' 出现在下标 3 ,所以距离为 abs(0 - 3) = 3 。
距下标 1 最近的 'e' 出现在下标 3 ,所以距离为 abs(1 - 3) = 3 。
对于下标 4 ,出现在下标 3 和下标 5 处的 'e' 都离它最近,但距离是一样的 abs(4 - 3) == abs(4 - 5) = 1 。
距下标 8 最近的 'e' 出现在下标 6 ,所以距离为 abs(8 - 6) = 2 。
2
3
4
5
6
7
题目链接:https://leetcode-cn.com/problems/shortest-distance-to-a-character/
# 解法一
var shortestToChar = function(S, C) {
var arr = [];
for (var i = 0; i < S.length; i++)
{
for (var j = 0; j < S.length; j++)
{
if (S[i + j] == C || S[i - j] == C) break;
}
arr[i] = j;
}
return arr;
};
2
3
4
5
6
7
8
9
10
11
12
13
# 解法二
var shortestToChar = function(s, c) {
let set=new Set();
for(let i=0;i<s.length;i++){
if(s[i]==c){
let index=s.indexOf(c,i)
set.add(index)
}
}
let arr=[...set]
let res=[]
for(let i=0;i<s.length;i++){
let min=Infinity;
for(let j=0;j<arr.length;j++){
min=Math.min(min,Math.abs(arr[j]-i))
}
res.push(min)
}
return res;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 下一个更大元素 I
# 题目
给你两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。
示例:
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
对于 num1 中的数字 4 ,你无法在第二个数组中找到下一个更大的数字,因此输出 -1 。
对于 num1 中的数字 1 ,第二个数组中数字1右边的下一个较大数字是 3 。
对于 num1 中的数字 2 ,第二个数组中没有下一个更大的数字,因此输出 -1 。
2
3
4
5
6
题目链接:https://leetcode-cn.com/problems/next-greater-element-i
# 解法
var nextGreaterElement = function(nums1, nums2) {
let arr=[]
for(let i=0;i<nums1.length;i++){
let index=nums2.indexOf(nums1[i])
let id=nums2.findIndex((item,idx)=>item>nums1[i]&& idx>index)
id>-1?arr.push(nums2[id]):arr.push(id)
}
return arr;
};
2
3
4
5
6
7
8
9
# 将数组分成和相等的三个部分
# 题目
给你一个整数数组 A,只有可以将其划分为三个和相等的非空部分时才返回 true,否则返回 false。形式上,如果可以找出索引 i+1 < j 且满足 A[0] + A[1] + ... + A[i] == A[i+1] + A[i+2] + ... + A[j-1] == A[j] + A[j-1] + ... + A[A.length - 1] 就可以将数组三等分。
示例:
输入:[0,2,1,-6,6,-7,9,1,2,0,1]
输出:true
解释:0 + 2 + 1 = -6 + 6 - 7 + 9 + 1 = 2 + 0 + 1
2
3
题目链接:https://leetcode-cn.com/problems/partition-array-into-three-parts-with-equal-sum
# 解法
var canThreePartsEqualSum = function(arr) {
let sum=arr.reduce((p,v)=>p+v)
if(sum%3!=0) return false;
let num=3,total=0;
for(let item of arr){
total+=item
if(total==sum/3){
total=0
num--
}
}
return num<=0
};
2
3
4
5
6
7
8
9
10
11
12
13
# 非递减数列
# 题目
给你一个长度为 n 的整数数组,请你判断在 最多 改变 1 个元素的情况下,该数组能否变成一个非递减数列。我们是这样定义一个非递减数列的: 对于数组中任意的 i (0 <= i <= n-2),总满足 nums[i] <= nums[i + 1]。
示例:
输入: nums = [4,2,3]
输出: true
解释: 你可以通过把第一个4变成1来使得它成为一个非递减数列。
2
3
题目链接:https://leetcode-cn.com/problems/non-decreasing-array/
# 解法
var checkPossibility = function(nums) {
function isSort(num){
for(let i=1;i<num.length;i++){
if(num[i]<num[i-1]){
return false;
}
}
return true;
}
for(let i=0;i<nums.length-1;i++){
let x=nums[i],y=nums[i+1]
if(x>y){
nums[i]=y
if(isSort(nums)){
return true;
}
nums[i]=x
nums[i+1]=x
return isSort(nums)
}
}
return true
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 千位分隔数
给你一个整数 n,请你每隔三位添加点(即 "." 符号)作为千位分隔符,并将结果以字符串格式返回。
示例:
输入:n = 123456789
输出:"123.456.789"
2
题目链接:https://leetcode-cn.com/problems/thousand-separator/
# 解法
var thousandSeparator = function(n) {
n=n.toString().split('')
for(let i=n.length-3;i>0;i=i-3){
n.splice(i,0,'.')
}
return n.join('');
};
2
3
4
5
6
7
# 长按键入
你的朋友正在使用键盘输入他的名字 name。偶尔,在键入字符 c 时,按键可能会被长按,而字符可能被输入 1 次或多次。你将会检查键盘输入的字符 typed。如果它对应的可能是你的朋友的名字(其中一些字符可能被长按),那么就返回 True。
示例:
输入:name = "alex", typed = "aaleex"
输出:true
解释:'alex' 中的 'a' 和 'e' 被长按。
2
3
题目链接:https://leetcode-cn.com/problems/long-pressed-name/
# 解法
var isLongPressedName = function(name, typed) {
if(name==typed) return true
let count=0
let str=''
while(count<name.length){
str+=name[count]+'+'
count++
}
console.log(str);
let reg=new RegExp('^'+str+'$','i')
return reg.test(typed)
};
2
3
4
5
6
7
8
9
10
11
12
# 卡牌分组
给定一副牌,每张牌上都写着一个整数。
此时,你需要选定一个数字 X,使我们可以将整副牌按下述规则分成 1 组或更多组:
- 每组都有 X 张牌。
- 组内所有的牌上都写着相同的整数。
仅当你可选的 X >= 2 时返回 true。
示例:
输入:[1,2,3,4,4,3,2,1]
输出:true
解释:可行的分组是 [1,1],[2,2],[3,3],[4,4]
2
3
题目链接:https://leetcode-cn.com/problems/x-of-a-kind-in-a-deck-of-cards/
# 解法
var hasGroupsSizeX = function(deck) {
let gcd = (a, b) => (b === 0 ? a : gcd(b, a % b)) //重点
let map=new Map()
for(let item of deck){
map.set(item,(map.get(item)||0)+1)
}
let arr = [...map.values()]
let res = arr[0]
return arr.every(i =>{
return (res = gcd(res, i)) > 1
})
};
2
3
4
5
6
7
8
9
10
11
12
13
14
# 括号的最大嵌套深度
如果字符串满足以下条件之一,则可以称之为 有效括号字符串(valid parentheses string,可以简写为 VPS):
字符串是一个空字符串 "",或者是一个不为 "(" 或 ")" 的单字符。
字符串可以写为 AB(A 与 B 字符串连接),其中 A 和 B 都是 有效括号字符串 。
字符串可以写为 (A),其中 A 是一个 有效括号字符串 。 类似地,可以定义任何有效括号字符串 S 的 嵌套深度 depth(S):
depth("") = 0
depth(C) = 0,其中 C 是单个字符的字符串,且该字符不是 "(" 或者 ")"
depth(A + B) = max(depth(A), depth(B)),其中 A 和 B 都是 有效括号字符串
depth("(" + A + ")") = 1 + depth(A),其中 A 是一个 有效括号字符串 例如:""、"()()"、"()(()())" 都是 有效括号字符串(嵌套深度分别为 0、1、2),而 ")(" 、"(()" 都不是 有效括号字符串 。
给你一个 有效括号字符串 s,返回该字符串的 s 嵌套深度 。
示例:
输入:s = "(1+(2*3)+((8)/4))+1"
输出:3
解释:数字 8 在嵌套的 3 层括号中。
2
3
题目链接:https://leetcode-cn.com/problems/maximum-nesting-depth-of-the-parentheses/
# 解法
var maxDepth = function(s) {
let i=0;
let L=0,n=0;
while(i<s.length){
if(s[i]=='('){
L++
}
if(s[i]==')'){
L--
}
n=n>L?n:L
i++;
}
return n;
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 旋转数字
我们称一个数 X 为好数, 如果它的每位数字逐个地被旋转 180 度后,我们仍可以得到一个有效的,且和 X 不同的数。要求每位数字都要被旋转。如果一个数的每位数字被旋转以后仍然还是一个数字, 则这个数是有效的。0, 1, 和 8 被旋转后仍然是它们自己;2 和 5 可以互相旋转成对方(在这种情况下,它们以不同的方向旋转,换句话说,2 和 5 互为镜像);6 和 9 同理,除了这些以外其他的数字旋转以后都不再是有效的数字。现在我们有一个正整数 N, 计算从 1 到 N 中有多少个数 X 是好数?
示例:
输入: 10
输出: 4
解释:
在[1, 10]中有四个好数: 2, 5, 6, 9。
注意 1 和 10 不是好数, 因为他们在旋转之后不变。
2
3
4
5
题目链接:https://leetcode-cn.com/problems/rotated-digits/
# 解法
let rotatedDigits = N => {
let r = /^(?![018]+$)[0125689]+$/
let num = 0
for (let i = 1; i <= N; i++) {
if (r.test(i)) {
num += 1
}
}
return num
}
2
3
4
5
6
7
8
9
10
# 解法二
var rotatedDigits = function(N) {
let goodNum = '2569';
let count = 0;
for(let i = 1; i <= N; i++) {
let str = i.toString();
if (str.indexOf('3') >= 0 || str.indexOf('4') >= 0 || str.indexOf('7') >= 0) {
continue
}
for (let j = 0; j < str.length; j++) {
if (goodNum.indexOf(str[[j]]) !== -1) {
count++
break
}
}
}
return count
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 字符串的最大公因子
对于字符串 S 和 T,只有在 S = T + ... + T(T 自身连接 1 次或多次)时,我们才认定 “T 能除尽 S”。返回最长字符串 X,要求满足 X 能除尽 str1 且 X 能除尽 str2。
示例:
输入:str1 = "ABCABC", str2 = "ABC"
输出:"ABC"
2
题目链接:https://leetcode-cn.com/problems/greatest-common-divisor-of-strings/
# 解法
var gcdOfStrings = function(str1, str2) {
if (str1 + str2 !== str2 + str1) return ''
const gcd = (a, b) => (0 === b ? a : gcd(b, a % b))
return str1.substring(0, gcd(str1.length, str2.length))
};
2
3
4
5