每日算法 每天写一两个算法题,免得一准备面试的时候重头再来,机制如我……^ ^ 算法真的是多写多练,没有捷径
Day1:
日期:210327
1.数组
1:数组往右移位k次
#思路:1.非原地排序,另存一个数组
var rotate = function(nums, k) {
let newArr=[]
newArr.length=5
const len=nums.length
for (let i=0;i<len;i++){
newArr[(i+k)%len]=nums[i]
}
return newArr
};
rotate([1,2,3,4,5,6,7],3)
#思路:1.最后一个放到第一位,剩下的往后移动一位,循环k次
var rotate = function(nums, k) {
if(nums.length<=k){
k=k%nums.length
}
for(let i=0;i<k;i++){
let last=nums[nums.length-1]
for(let j=nums.length-2;j>=0;j--){
nums[j+1]=nums[j]
}
nums[0]=last
}
console.log(nums)
};
rotate([1,2,3,4,5,6,7],3)
2.栈
1.给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。(leetcode20)
#思路:
1.边界判断: 先看是否是string
2.存储: stack=[]
2.map
3.for循环
4.判断:左括号——stack push(map数据)
5.判断:右括号——stack pop出来并和自己比较, 不一样 return false
6.如果stack长度为0 返回true
/**
* @param {string} s
* @return {boolean}
*/
/**
* @param {string} s
* @return {boolean}
*/
var isValid = function (s) {
if (typeof s !== 'string') return false
const len = s.length, stack = []
const map = {
'{': '}',
'[': ']',
'(': ')',
}
for (let i = 0; i < len; i++) {
const crt = s[i]
if(map[crt]) {
// 为左括号,则将对应右括号push到stack
stack.push(map[crt])
}else if(crt !== stack.pop()){
// 如果是右括号,则出栈对比
return false
}
}
return stack.length === 0
}
2.设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。(leetcode155)
#思路1.两个栈,一个存储数据,一个存储最小值。每次都存最小值,因为pop一个后,查看最小值
var MinStack = function() {
this.stack=[]
this._minStack=[]
};
/**
* @param {number} val
* @return {void}
*/
MinStack.prototype.push = function(val) {
this.stack.push(val)
this._minStack.push(Math.min(this._minStack[this._minStack.length-1],val))
};
MinStack.prototype.pop = function() {
this.stack.pop()
this._minStack.pop()
};
MinStack.prototype.top = function() {
return this.stack[[this.stack.length-1]]
};
MinStack.prototype.getMin = function() {
return this._minStack[[this._minStack.length-1]]
};
3.用栈实现队列(leetcode:232)
#思路:
1.stack1,stack2为了pop和peek使用 pop是最后循环后stack2中pop一个 而 peek是返回stack2的最后一个
2.stack1中push,empty判断两边stack是否都为空就行。
/**
* Initialize your data structure here.
*/
var MyQueue = function () {
this.stack1 = []
this.stack2 = []
};
/**
* Push element x to the back of queue.
* @param {number} x
* @return {void}
*/
MyQueue.prototype.transferData = function () {
while (this.stack1.length) {
this.stack2.push(this.stack1.pop())
}
}
MyQueue.prototype.push = function (x) {
this.stack1.push(x)
};
/**
* Removes the element from in front of queue and returns that element.
* @return {number}
*/
MyQueue.prototype.pop = function () {
if (!this.stack2.length) {
this.transferData()
}
return this.stack2.pop()
};
/**
* Get the front element.
* @return {number}
*/
MyQueue.prototype.peek = function () {
if (!this.stack2.length) {
this.transferData()
}
return this.stack2[this.stack2.length - 1]
};
/**
* Returns whether the queue is empty.
* @return {boolean}
*/
MyQueue.prototype.empty = function () {
return this.stack1.length === 0 && this.stack2.length===0
};
/**
* Your MyQueue object will be instantiated and called as such:
* var obj = new MyQueue()
* obj.push(x)
* var param_2 = obj.pop()
* var param_3 = obj.peek()
* var param_4 = obj.empty()
*/
4.比较含退格的字符串(leetcode:844)
思路:
1.栈的push和pop思路
2.for循环
3.不等于#的时候存储push
4.等于#的时候直接pop(判断是否为空)
同理 字符串
1.for循环
2.不等于#的时候str+=item
3.等于#的时候str.substring(0,str.length-1)(判断是否为空) 等于截掉最后一个字符串
function stringFor(str, lastStr){
for (let i = 0; i < str.length; i++) {
if (str[i] != '#') {
//stack.push(str[i])
lastStr+=str[i]
}else if(str[i] == '#' && lastStr.length){
//stack.pop(str[i])
lastStr=lastStr.substring(0,lastStr.length-1)
}
}
return lastStr
}
var backspaceCompare = function (S, T) {
//let stackS = []
//let stackT = []
let lastS=''
let lastT=''
//stringFor(S,stackS)
return stringFor(S,lastS)===stringFor(T,lastT)
};
5.删除字符串中的所有相邻重复项(leetcode:1047)
/**
* @param {string} S
* @return {string}
*/
var removeDuplicates = function (S) {
if (typeof S !== 'string') return false
let len = S.length;
var stack=[]
for (let i = 0; i < len; i++) {
var lenStack=stack.length
if(stack[lenStack-1]!==S[i]){
stack.push(S[i])
}else if(lenStack) {
stack.pop()
}
}
return stack.join('')
};
1.使用栈存储
Day2
日期:210328
3.双指针
1.接雨水(leetcode:84)
思路:
双指针法(我就是看着代码,一个步骤一个步骤写出来,读懂技巧啦~)
1.使用左指针l=0,右指针r=n-1,左侧最高高度l_max,右侧最高高度r_max
2.比如r_max>l_max,就去关注l,并计算接水容量=l_max-自身高度,故res+=l_max-height[l],l++
3.l<=r 退出循环while
4.返回res
/**
* @param {number[]} height
* @return {number}
*/
var trap = function (heights) {
if (heights.length === 0) return 0;
let n = heights.length;
let l_max = heights[0];//左侧最高初始值
let r_max = heights[n - 1];//右侧最高初始值
let l = 0;//左指针
let r = n - 1;//右指针
var res = 0 //记录接水量
while (l <= r) {
l_max = Math.max(l_max, heights[l]) //左侧max高度
r_max = Math.max(r_max, heights[r]) //右侧max高度
if (l_max < r_max) {
res += l_max - heights[l]//左max高度-自身高度
l++ //指针往右移
} else {
res += r_max - heights[r]
r--
}
}
return res
};
Day2
日期:210408
4.merge
1.49. 字母异位词分组
思路:
1.变成同样的key,然后通过map存储数组
2.返回map.values()值
/**
* @param {string[]} strs
* @return {string[][]}
*/
var groupAnagrams = function(strs) {
let map=new Map()
for(let str of strs){
let arr=Array.from(str)
let key=arr.sort().toString()
let list=map.has(key)?map.get(key):new Array()
list.push(str)
map.set(key,list)
}
return Array.from(map.values())
};
groupAnagrams(["eat", "tea", "tan", "ate", "nat", "bat"])
2.字母异位词分组(leetcode:49)
思路:
1.while循环common prefix和str[i]比较chartAt[index] 如果一样的话index++
2.prefix=str[i].substring(0,index)
举例:
leet leed led
1.leet & leed 对比 lee
2.lee & led 对比 le
/**
* @param {string[]} strs
* @return {string}
*/
var longestCommonPrefix = function(strs) {
if(!Array.isArray(strs)){
return false
}
if(strs.length==0){
return ''
}
let prefix=strs[0];
for(let str of strs){
prefix=getCommonPrefix(prefix,str)
if(!prefix){
break
}
}
return prefix
};
var getCommonPrefix=(str1,str2)=>{
let length = Math.min(str1.length, str2.length);
let index=0;
while(index<length && str1.charAt(index)===str2.charAt(index)){
index++
}
return str1.substring(0,index)
}
longestCommonPrefix(["flower","flow","flight"])