常见js手写题2
PromiseAll、PromiseRace、走楼梯问题、repeat函数、最长回文子串、两数/三数和
PromiseAll
//特点:等所有Promise执行成功,再resolve;一旦有一个失败回调第一个失败 function PromiseAll(arr){ return new Promise(){ let index = 0, resArr = []; if(arr.length === 0){resolve resArr} //处理传入为空的情况 function deal(index,item){ resArr.push(item); index ++; if(index === arr.length){ return resolve(resArr) } } for(let i =0;i < arr.length;i++){ Promise.resolve(arr[i]).then( res=>{deal(i,res)}, err=>{throw new Error(err+'err')} ) } } }
PromiseRace
//特点:返回最快的Promise,不管执行成功或失败
function PromiseRace(arr){
return new Promise((resolve,reject)=>{
arr.forEach(item=>{
item.then(resolve,reject)
})
})
}
走棋盘问题
//需求:输入楼梯阶数n,每次走一步或者两步,返回可能结果数
//解法1:递归
function Deal(n){
if(n ===1 || n ===2){
return n
}
return Deal(n-1)+Deal(n-2)
}
//解法2:dp, 用以解决基数n较大使用递归导致的内存占用太多
function Deal(n){
if(n === 1 || n === 2){
return n
}
let dp =[];
dp[0]=1;
dp[1]=2;
for(let i=2;i < n;i++){
dp[i] = dp[i-1]+dp[i-2]
}
return dp[n-1]
}
rePeat函数
//需求:输入func、执行次数times、时延wait;返回一个函数每隔时延回调输入
function rePeat(func,times,wait){
return (...arg)=>{
let self = this
let timer = setInterval(()=>{
if(times>0){
fn.apply(self,arg)
times --;
} else {
clearTimeOut(timer)
}
},wait)
}
}
最长回文子串
//需求:输入一个字符串,找出其中最长的回文子串
//解法1:暴力法(略)两轮遍历获取所有子串可能性,判断是否回文,时间复杂度o(n^3)
//解法2:动态规划
function Deal(str){
let max =0,
result = '',
dp=[];
for(let n =0;n < str.length;n++){
dp[n] = [];//构建二维数组dp
}
for(let k=0;k < str.length;k++){ //一轮遍历所有可能的子串始末下标差值k
for(let i=0;i < str.length-k;i++){ //二轮遍历所有可能子串的起始下标i
j=i+k; //得到子串末尾下标j
if(k === 0){ //若差值为0,代表子串长度为1,一定回文
dp【i】【j】 = true
} else if (k <=2){ 若差值为1或2,代表子串长度为2或3,当首位相同回文
if(str[i] === str[j]){
dp【i】【j】 = true
}else{
dp【i】【j】 = false
}
} else { //差值大于2,子串长度大于3,回文条件:首尾相同且内部回文
if(str[i] === str[j] && dp【i+1】【j-1】){
dp【i】【j】 = true
} else {
dp【i】【j】 = false
}
}
if(dp【i】【j】 && k>max){
max = k;
result = str.slice(i,j+1);
}
}
}
return result
}
=2){>
两数之和
//需求:输入数组、目标和;返回和等于目标的两数下标
function sumOfTwo(arr,target){
let res=[]; //维护一个hash-map
for(let i=0;i < arr.length;i++){
if(res[arr[i]] === undefined){
res[target - arr[i]] = i
} else {
return [res[arr[i]],i]
}
}
}
三数之和
//需求:输入数组;返回三数之和为0的数
function sumOfThree(arr){
arr=arr.sort((a,b)=>a-b) //对输入数组排序
let res = [];
for(let i=0;i < arr.length-2;i++){
if(i>=1 && arr[i] === arr[i-1]){ //对第一位i去重
continue;
}
let j = i+1,
k = arr.length-1;
while(j < k){
let sum = arr[i]+arr[j]+arr[k];//获取三数之和
if(sum ===0){
res.push(arr[i],arr[j],arr[k])
j++;
while(arr[j] === arr[j-1]){ //对第二位数j去重
j++;
}
}
else if(sum < 0){
j++;
}
else if(sum > 0){
k--;
}
}
}
return res;
}
//需求:输入楼梯阶数n,每次走一步或者两步,返回可能结果数
//解法1:递归 function Deal(n){ if(n ===1 || n ===2){ return n } return Deal(n-1)+Deal(n-2) } //解法2:dp, 用以解决基数n较大使用递归导致的内存占用太多 function Deal(n){ if(n === 1 || n === 2){ return n } let dp =[]; dp[0]=1; dp[1]=2; for(let i=2;i < n;i++){ dp[i] = dp[i-1]+dp[i-2] } return dp[n-1] }
rePeat函数
//需求:输入func、执行次数times、时延wait;返回一个函数每隔时延回调输入
function rePeat(func,times,wait){
return (...arg)=>{
let self = this
let timer = setInterval(()=>{
if(times>0){
fn.apply(self,arg)
times --;
} else {
clearTimeOut(timer)
}
},wait)
}
}
最长回文子串
//需求:输入一个字符串,找出其中最长的回文子串
//解法1:暴力法(略)两轮遍历获取所有子串可能性,判断是否回文,时间复杂度o(n^3)
//解法2:动态规划
function Deal(str){
let max =0,
result = '',
dp=[];
for(let n =0;n < str.length;n++){
dp[n] = [];//构建二维数组dp
}
for(let k=0;k < str.length;k++){ //一轮遍历所有可能的子串始末下标差值k
for(let i=0;i < str.length-k;i++){ //二轮遍历所有可能子串的起始下标i
j=i+k; //得到子串末尾下标j
if(k === 0){ //若差值为0,代表子串长度为1,一定回文
dp【i】【j】 = true
} else if (k <=2){ 若差值为1或2,代表子串长度为2或3,当首位相同回文
if(str[i] === str[j]){
dp【i】【j】 = true
}else{
dp【i】【j】 = false
}
} else { //差值大于2,子串长度大于3,回文条件:首尾相同且内部回文
if(str[i] === str[j] && dp【i+1】【j-1】){
dp【i】【j】 = true
} else {
dp【i】【j】 = false
}
}
if(dp【i】【j】 && k>max){
max = k;
result = str.slice(i,j+1);
}
}
}
return result
}
=2){>
两数之和
//需求:输入数组、目标和;返回和等于目标的两数下标
function sumOfTwo(arr,target){
let res=[]; //维护一个hash-map
for(let i=0;i < arr.length;i++){
if(res[arr[i]] === undefined){
res[target - arr[i]] = i
} else {
return [res[arr[i]],i]
}
}
}
三数之和
//需求:输入数组;返回三数之和为0的数
function sumOfThree(arr){
arr=arr.sort((a,b)=>a-b) //对输入数组排序
let res = [];
for(let i=0;i < arr.length-2;i++){
if(i>=1 && arr[i] === arr[i-1]){ //对第一位i去重
continue;
}
let j = i+1,
k = arr.length-1;
while(j < k){
let sum = arr[i]+arr[j]+arr[k];//获取三数之和
if(sum ===0){
res.push(arr[i],arr[j],arr[k])
j++;
while(arr[j] === arr[j-1]){ //对第二位数j去重
j++;
}
}
else if(sum < 0){
j++;
}
else if(sum > 0){
k--;
}
}
}
return res;
}
//需求:输入一个字符串,找出其中最长的回文子串
//解法1:暴力法(略)两轮遍历获取所有子串可能性,判断是否回文,时间复杂度o(n^3) //解法2:动态规划 function Deal(str){ let max =0, result = '', dp=[]; for(let n =0;n < str.length;n++){ dp[n] = [];//构建二维数组dp } for(let k=0;k < str.length;k++){ //一轮遍历所有可能的子串始末下标差值k for(let i=0;i < str.length-k;i++){ //二轮遍历所有可能子串的起始下标i j=i+k; //得到子串末尾下标j if(k === 0){ //若差值为0,代表子串长度为1,一定回文 dp【i】【j】 = true } else if (k <=2){ 若差值为1或2,代表子串长度为2或3,当首位相同回文
if(str[i] === str[j]){ dp【i】【j】 = true }else{ dp【i】【j】 = false } } else { //差值大于2,子串长度大于3,回文条件:首尾相同且内部回文 if(str[i] === str[j] && dp【i+1】【j-1】){ dp【i】【j】 = true } else { dp【i】【j】 = false } } if(dp【i】【j】 && k>max){ max = k; result = str.slice(i,j+1); } } } return result } =2){>
两数之和
//需求:输入数组、目标和;返回和等于目标的两数下标
function sumOfTwo(arr,target){
let res=[]; //维护一个hash-map
for(let i=0;i < arr.length;i++){
if(res[arr[i]] === undefined){
res[target - arr[i]] = i
} else {
return [res[arr[i]],i]
}
}
}
三数之和
//需求:输入数组;返回三数之和为0的数
function sumOfThree(arr){
arr=arr.sort((a,b)=>a-b) //对输入数组排序
let res = [];
for(let i=0;i < arr.length-2;i++){
if(i>=1 && arr[i] === arr[i-1]){ //对第一位i去重
continue;
}
let j = i+1,
k = arr.length-1;
while(j < k){
let sum = arr[i]+arr[j]+arr[k];//获取三数之和
if(sum ===0){
res.push(arr[i],arr[j],arr[k])
j++;
while(arr[j] === arr[j-1]){ //对第二位数j去重
j++;
}
}
else if(sum < 0){
j++;
}
else if(sum > 0){
k--;
}
}
}
return res;
}
function sumOfTwo(arr,target){ let res=[]; //维护一个hash-map for(let i=0;i < arr.length;i++){ if(res[arr[i]] === undefined){ res[target - arr[i]] = i } else { return [res[arr[i]],i] } } }
//需求:输入数组;返回三数之和为0的数
function sumOfThree(arr){ arr=arr.sort((a,b)=>a-b) //对输入数组排序 let res = []; for(let i=0;i < arr.length-2;i++){ if(i>=1 && arr[i] === arr[i-1]){ //对第一位i去重 continue; } let j = i+1, k = arr.length-1; while(j < k){ let sum = arr[i]+arr[j]+arr[k];//获取三数之和 if(sum ===0){ res.push(arr[i],arr[j],arr[k]) j++; while(arr[j] === arr[j-1]){ //对第二位数j去重 j++; } } else if(sum < 0){ j++; } else if(sum > 0){ k--; } } } return res; }