文章目录
leetcode每周七题-初衷
- 之前的每日一题系列,由于时间问题,直接贴的安大的微信群每日一题,大佬已经坚持到140多天了。
- 为了向大佬学习,推出每日七道面试题。对于力扣大家应该挺熟悉的,毕竟想进BAT一线大厂,leetcode题必刷,接下来我带着大家一起学习吧(全程使用 javascript解题,不是最优解,只是提供一个思路)。
为什么要刷leetcode?游戏它不香?
- 虽然刷题一直饱受诟病,不过不可否认刷题确实能锻炼我们的编程能力。
- 虽然leetcode题目深度普遍偏低(知乎大佬说的),如果是为了面试,刷Leetcode还是很重要的。一是提高对简单题的熟悉程度,有一些听起来很轻松的题目,写过一次和没写过的临场表现可能会有很大的差距;二是可以见识一些大家都知道的奇技淫巧,有一些大公司就是喜欢考这种看似很巧妙,牵扯到知识的广度还是挺宽的。
2020/11/1(140. 单词拆分 II)
题目
- 给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,在字符串中增加空格来构建一个句子,使得句子中所有的单词都在词典中。返回所有这些可能的句子。
- 说明:
- 分隔时可以重复使用字典中的单词。
- 你可以假设字典中没有重复的单词。
示例
- 示例 1:
输入:
s = "catsanddog"
wordDict = ["cat", "cats", "and", "sand", "dog"]
输出:
[
"cats and dog",
"cat sand dog"
]
- 示例2
输入:
s = "pineapplepenapple"
wordDict = ["apple", "pen", "applepen", "pine", "pineapple"]
输出:
[
"pine apple pen apple",
"pineapple pen apple",
"pine applepen apple"
]
解释: 注意你可以重复使用字典中的单词。
- 示例3
输入:
s = "catsandog"
wordDict = ["cats", "dog", "sand", "and", "cat"]
输出:
[]
代码模版
/**
* @param {string} s
* @param {string[]} wordDict
* @return {string[]}
*/
var wordBreak = function(s, wordDict) {
};
题解
/**
* @param {string} s
* @param {string[]} wordDict
* @return {string[]}
*/
var wordBreak = function (s, wordDict) {
const sIndex = s.length;
const newWordDict = new Set(wordDict);//set 数据结构有has方法
let hash = new Map();//存储循环过的从start截取i对应的数据
function drt(start) {
if (hash.has(start)) {//hash里有start,直接取对应的数据
return hash.get(start);
}
if (start > sIndex - 1) {//start 最大值就是字符串最后一个索引 sIndex - 1
return [[]];
}
let res = [];
for (var i = start + 1; i <= sIndex; i++) {
let str = s.slice(start, i);
if (newWordDict.has(str)) {
const items = drt(i);//循环把剩余字符串在newWordDict进行匹配,返回数组res [[string],]
for (let item of items) {
res.push([str].concat(item));
}
}
hash.set(start, res);//存储从start开始截取,对应的res数据
}
return res;
}
return drt(0).map((item) => item.join(" "));// [[string,string],[string,string]] 变成 ["string string","string string"]
};
2020/11/2(349. 两个数组的交集)
题目
- 给定两个数组,编写一个函数来计算它们的交集。
示例
- 示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
- 示例2
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
代码模版
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var intersection = function (nums1, nums2) {
};
题解
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var intersection = function (nums1, nums2) {
let ary1 = new Set(nums1);//利用set去重,有has方法
let ary2 = new Set(nums2);//set数据结构类数组,需要转成数组可以调数组上的方法
return Array.from(ary2).filter((item) => ary1.has(item));//Array.from(ary2) 类数组转数组
};
2020/11/3(941. 有效的山脉数组)
题目
-
给定一个整数数组 A,如果它是有效的山脉数组就返回 true,否则返回 false。
-
让我们回顾一下,如果 A 满足下述条件,那么它是一个山脉数组:
A.length >= 3
在 0 < i < A.length - 1 条件下,存在 i 使得:
A[0] < A[1] < … A[i-1] < A[i]
A[i] > A[i+1] > … > A[A.length - 1]
示例
- 示例 1:
输入:[2,1]
输出:false
- 示例2
输入:[3,5,5]
输出:false
- 示例3
输入:[0,3,2,1]
输出:true
代码模版
/**
* @param {number[]} A
* @return {boolean}
*/
var validMountainArray = function (A) {
};
题解
/**
* @param {number[]} A
* @return {boolean}
*/
var validMountainArray = function (A) {
if (A.length < 3) return false;
let max = Math.max(...A);//找到最高点
let index = A.indexOf(max);//拿到最高点的索引
let i = 0;
let isBoolean = true;
let goUp = false;
let goDown = false;
while (i < A.length - 1) {
if (i < index && A[i] < A[i + 1]) {//最高点之前是上升趋势
i++;
goUp = true;
} else if (i >= index && A[i] > A[i + 1]) {//最高点之后是下降趋势
i++;
goDown = true;
} else {//不满足上面就失败,break中止循环
isBoolean = false;
break;
}
}
return goUp && goDown && isBoolean;
};
2020/11/4(57. 插入区间)
题目
- 给出一个无重叠的 ,按照区间起始端点排序的区间列表。
- 在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间)。
示例
- 示例 1:
输入:intervals = [[1,3],[6,9]], newInterval = [2,5]
输出:[[1,5],[6,9]]
- 示例2
输入:intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
输出:[[1,2],[3,10],[12,16]]
解释:这是因为新的区间 [4,8] 与 [3,5],[6,7],[8,10] 重叠。
代码模版
/**
* @param {number[][]} intervals
* @param {number[]} newInterval
* @return {number[][]}
*/
var insert = function (intervals, newInterval) {
};
题解
/**
* @param {number[][]} intervals
* @param {number[]} newInterval
* @return {number[][]}
*/
var insert = function (intervals, newInterval) {
let res = [];
intervals.push(newInterval);//合并到一个数组
intervals.sort((a, b) => a[0] - b[0]);//按照数组中每一项(也是数组)的第一个值,从小到大进行排序
res.push(intervals[0]);//把第一个先放到res中,从第二个值开始循环(索引为1)
for (var i = 1; i < intervals.length; i++) {
if (res[res.length - 1][1] < intervals[i][0]) {//当res数组中最后一个的第二个值,小于 intervals[i]中的第一个值,说明没有区间不重叠
res.push(intervals[i]);
} else if (res[res.length - 1][1] < intervals[i][1]) {//当res数组中最后一个的第二个值,大于或等于 intervals[i]中的第一个值,小于i intervals[i]中的第二个值,说明有区间重叠,直接把 intervals[i]中的第二个值给es数组中最后一个的第二个值
res[res.length - 1][1] = intervals[i][1];
}
}
return res;
};
2020/11/5(127. 单词接龙)
题目
- 给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord 的最短转换序列的长度。转换需遵循如下规则:
- 每次转换只能改变一个字母。
- 转换过程中的中间单词必须是字典中的单词。
- 说明:
- 如果不存在这样的转换序列,返回 0。
- 所有单词具有相同的长度。
- 所有单词只由小写字母组成。
- 字典中不存在重复的单词。
- 你可以假设 beginWord 和 endWord 是非空的,且二者不相同。
示例
- 示例 1:
输入:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]
输出: 5
解释: 一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog",
返回它的长度 5。
- 示例2
输入:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
输出: 0
解释: endWord "cog" 不在字典中,所以无法进行转换。
代码模版
/**
* @param {string} beginWord
* @param {string} endWord
* @param {string[]} wordList
* @return {number}
*/
var ladderLength = function (beginWord, endWord, wordList) {
};
题解
/**
* @param {string} beginWord
* @param {string} endWord
* @param {string[]} wordList
* @return {number}
*/
var ladderLength = function (beginWord, endWord, wordList) {
if (beginWord === endWord) return 1
let newSetWordList = new Set(wordList);
let que = [];
que.push([beginWord, 1])//第一次默认值,beginWord,默认长度1
while (que.length) {
for (var i = 0; i < que.length; i++) {
let [newBeginWord, level] = que.shift()
if (newBeginWord === endWord) {//相等时,返回长度
return level
}
for (var w = 0; w < newBeginWord.length; w++) {//循环需要转换的字符串
for (var j = 97; j <= 122; j++) {// 26个小写字母(ascii码 http://ascii.911cha.com/)
let newStr = newBeginWord.slice(0, w) + String.fromCharCode(j) + newBeginWord.slice(w + 1)//hit -》 xit hxt hix x代表26个小写字母
if (newSetWordList.has(newStr)) {
que.push([newStr, level + 1]) //把转换后的newStr放到数组中,长度+1
newSetWordList.delete(newStr)//匹配到删除
}
}
}
}
}
return 0;
};
2020/11/6(1356. 根据数字二进制下 1 的数目排序)
题目
-
给你一个整数数组 arr 。请你将数组中的元素按照其二进制表示中数字 1 的数目升序排序。
-
如果存在多个数字二进制中 1 的数目相同,则必须将它们按照数值大小升序排列。
-
请你返回排序后的数组。
示例
- 示例 1:
输入:arr = [0,1,2,3,4,5,6,7,8]
输出:[0,1,2,4,8,3,5,6,7]
解释:[0] 是唯一一个有 0 个 1 的数。
[1,2,4,8] 都有 1 个 1 。
[3,5,6] 有 2 个 1 。
[7] 有 3 个 1 。
按照 1 的个数排序得到的结果数组为 [0,1,2,4,8,3,5,6,7]
- 示例2
输入:arr = [1024,512,256,128,64,32,16,8,4,2,1]
输出:[1,2,4,8,16,32,64,128,256,512,1024]
解释:数组中所有整数二进制下都只有 1 个 1 ,所以你需要按照数值大小将它们排序。
- 示例3
输入:arr = [10000,10000]
输出:[10000,10000]
- 示例4
输入:arr = [2,3,5,7,11,13,17,19]
输出:[2,3,5,17,7,11,13,19]
- 示例5
输入:arr = [10,100,1000,10000]
输出:[10,100,10000,1000]
- 提示:
1 <= arr.length <= 500
0 <= arr[i] <= 10^4
代码模版
/**
* @param {number[]} arr
* @return {number[]}
*/
var sortByBits = function (arr) {
};
题解
/**
* @param {number[]} arr
* @return {number[]}
*/
var sortByBits = function (arr) {
return arr.sort((a, b) => {
let aIndex = a.toString(2).match(/1/g)?.length || 0;//a.toString(2) 把数组转换成二进制的字符串,.match(/1/g)?.length || 0 匹配到1的数量没有就是0
let bIndex = b.toString(2).match(/1/g)?.length || 0;
if (aIndex < bIndex || (aIndex <= bIndex && a < b)) {//aIndex < bIndex 按照1的数量从小到大,aIndex <= bIndex && a < b 如果1的数量相同 从小到大排序
return -1;
}
});
};
- 也可以 把match换成replace
/**
* @param {number[]} arr
* @return {number[]}
*/
var sortByBits = function (arr) {
return arr.sort((a, b) => {
let aIndex = a.toString(2).replace(/0/g, "").length;
let bIndex = b.toString(2).replace(/0/g, "").length;
if (aIndex < bIndex || (aIndex <= bIndex && a < b)) {
return -1;
}
});
};
- 还可以存到newArr 中
/**
* @param {number[]} arr
* @return {number[]}
*/
var sortByBits = function (arr) {
let newArr = [];
for (var i = 0, id = 0; i < arr.length; i++ , id = 0) {
newArr.push({
item: arr[i],
number:
arr[i].toString(2).replace(/0/g, '').length,
});
}
return newArr
.sort((a, b) => {
if (a.number < b.number || (a.number === b.number && a.item < b.item)) {
return -1;
}
})
.map((item) => item.item);
};
2020/11/7(327. 区间和的个数)
题目
给定一个整数数组 nums,返回区间和在 [lower, upper] 之间的个数,包含 lower 和 upper。
区间和 S(i, j) 表示在 nums 中,位置从 i 到 j 的元素之和,包含 i 和 j (i ≤ j)。
扫描二维码关注公众号,回复:
12475708 查看本文章
说明:
最直观的算法复杂度是 O(n2) ,请在此基础上优化你的算法。
示例
- 示例 1:
输入: nums = [-2,5,-1], lower = -2, upper = 2,
输出: 3
解释: 3个区间分别是: [0,0], [2,2], [0,2],它们表示的和分别为: -2, -1, 2。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-of-range-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
代码模版
/**
* @param {number[]} nums
* @param {number} lower
* @param {number} upper
* @return {number}
*/
var countRangeSum = function (nums, lower, upper) {
};
题解
/**
* @param {number[]} nums
* @param {number} lower
* @param {number} upper
* @return {number}
*/
var countRangeSum = function (nums, lower, upper) {
let n = 0;
for (var i = 0; i < nums.length; i++) {//循环nums.length次
let item=0;
for (var j = i; j < nums.length; j++) {//从i项开始循环
item += nums[j];
if(item >=lower&&item<=upper){
n++
}
}
}
return n
};