判断str是否有数字
function strnum(str) {
var a1 = new RegExp('[0-9]')
var new_str = a1.test(str)
return new_str
}
计算两个数相乘的值,未知小数(求精度)
function num(a, b) {
var a1 = a.toString();
var a2 = b.toString();
var b1 = (a1.indexOf('.') == -1) ? 0 : (a1.length - a1.indexOf('.') - 1);
var b2 = (a2.indexOf('.') == -1) ? 0 : (a2.length - a2.indexOf('.') - 1);
// var c = Math.max(b1, b2);
var a=b1+b2
return parseFloat(a1 * a2).toFixed(a);
}
// console.log(num(8.21,21))
计算一个数的幂(可以是小数)
function Power(base, exponent) {
if(base != 0 || exponent != 0){
var base1 = base.toString();
var len = (base1.indexOf('.') != -1) ? (base1.length - base1.indexOf('.') - 1) : 0; // 获取数的小数位数
var sum = '1';
var len1 = 0;
if(exponent >= 0){
// 一个一个相乘,跟两数相乘一样的做法
for(var i = 0;i < exponent; i++){
len1 += len;
var a = parseFloat(sum*base1).toFixed(len1)
sum = a.toString()
}
return sum
}
else{
for( var i=0; i > exponent; i--){
len1 += len;
var a = parseFloat( sum * base1 ).toFixed(len1)
sum = a.toString()
}
return parseFloat(1/sum)
}
}else{
console.log(false)
}
}
// console.log(Power(10,-1))
数组去重1
// 数组去重1
function setnum1(arr) {
var a = new Set(arr)
return [...a] //集合转成数组
// return Array.from(a); //集合转成数组
}
//数组去重2
function setnum2(arr) {
var a = {}
var data = []
for (var i in arr) {
if (!a[arr[i]]) {
a[arr[i]] = true
data.push(arr[i])
}
}
return data
}
// console.log(setnum2([1,2,3,1,4]))
// 数组去重3
var setNum3 = function (arr) {
const m = new Map()
arr.forEach((item) => {
if (!m.has(item)) {
m.set(item, 1)
}
})
const result = []
m.forEach((value, key) => {
result.push(key)
})
return result
}
字符串去重(跟数组去重差不多,先把字符串转成数组)
function setstr(arr) {
var a = arr.split('')
var b = new Set(a)
return [...b].join('');
// return Array.from(b).join('')
}
var setStr2 = function (arr1) {
const arr = arr1.split('')
const m = new Map()
arr.forEach((item) => {
if (!m.has(item)) {
m.set(item)
}
})
const result = []
m.forEach((item, value) => {
result.push(value)
})
return result
}
不需要借助第三个临时变量,实现两个变量的交换:
// 只能交换数字
jiaohuan(10, 8)
function jiaohuan(a, b) {
var a1 = a;
var b1 = b;
a1 = a1 + b1;
b1 = a1 - b1;
a1 = a1 - b1;
console.log(a1)
console.log(b1)
}
// 或者
var foo = '我是foo'
var bar = '我是bar'
[foo, bar] = [bar, foo]
字符串反向
function strfan(str) {
var a = str.split('')
var b = a.reverse().join('')
return b;
}
判断是否是回文
function huiwen(str) {
var a = str.split('')
var b = a.reverse().join('')
if (str === b) {
return 'Y'
} else {
return "N"
}
}
给你一个字符串 s,找到 s 中最长的回文子串。力扣第5
// 最长回文子串
function zuichanghuiwen (s) {
if (s.length < 2) {
return s
}
// 把每一个字符当成是对应子串的中心字符,进行遍历
let str = ''
for (let i = 0; i < s.length; i++) {
// 回文子串是偶数的情况
huiwen(i, i + 1)
// 回文子串是奇数的情况
huiwen(i, i)
}
function huiwen(a, b) {
while(a >= 0 && b < s.length && s[a] === s[b]) {
a--
b++
}
// b - a - 1即是对应回文的长度
// 注意此处a,b的值循环完后 是恰好不满足循环条件的时刻
// 此时a到b的距离为b-a+1,但是ab两个边界不能取 所以应该取a+1到b-1的区间 长度是b-a-1
if(b - a - 1 > str.length) {
// slice也要取[a + 1,b - 1]这个区间
str = s.slice(a + 1, b)
}
}
return str
}
console.log(zuichanghuiwen('sdadadasdasdsadscxccfwcsc'))
// 或者
const longestPalindrome = (s) => {
if (!s || s.length === 0) {
return "";
}
let longest = "";
for (let i = 0; i < s.length; i++) {
let oddPalindrome = expandAroundCenter(s, i, i);
let evenPalindrome = expandAroundCenter(s, i, i + 1);
if (oddPalindrome.length > longest.length) {
longest = oddPalindrome;
}
if (evenPalindrome.length > longest.length) {
longest = evenPalindrome;
}
}
return longest;
}
const expandAroundCenter = (s, left, right) => {
while (left >= 0 && right < s.length && s[left] === s[right]) {
left--;
right++;
}
return s.substring(left + 1, right);
}
// 示例用法
const str = "babad";
const longestPal = longestPalindrome(str);
console.log(longestPal); // 输出 "bab"
Z 字形变换 力扣第六题
var convert = function(s, numRows) {
if (s.length === 1 || numRows === 1) {
return s
}
let arr = Array(numRows).fill('')
let j = 0
let flag = true
for (let i = 0; i < s.length; i++) {
if(flag) {
if (j < numRows - 1) {
arr[j] += s.charAt(i)
j++
} else {
flag = false
}
}
if(!flag) {
if (j > 0) {
arr[j] += s.charAt(i)
j--
} else {
i--
flag = true
}
}
}
return arr.join('')
};
力扣第九 回文数
例如123456的长度是parseInt(Math.log10(123456)) ===> 5
实际长度是再+1
js 的** 代表的是方,即10**2 即是Math.pow(10,2) ===> 100
// 不使用字符串进行判断
var isPalindrome = function(x) {
if (x < 0) return false
if( x < 10) return true
let a = parseInt(Math.log10(x))
for (let i = a; i > 0; ) {
// 判断前后是否相等,不相等直接返回false
if(parseInt(x/(10**i)) !== x%10) {
return false
}
// 去掉最前面跟最后面的那个数字
x = parseInt((x%(10**i))/10)
// i进行-2,因为上面去除了两个数字
i -= 2
}
// 一直都没有return ,代表没有不相等的 所以直接返回true
return true
};
//使用字符串辅助只需以下即可,第一转成字符串,第二转成数组,第三翻转字符串数组,第四转成字符串,第五判断俩是否相等
盛最多水的容器 力扣第11
利用双指针解法,一个从左开始一个从右开始,
一开始i和j指针在最两侧,此时宽度最大。高低是较低的那条。然后考虑指针移动。移动高度较小的那条。直至i跟j重合
var maxArea = function(height) {
let max = 0
// for(let i = 0; i < height.length; i++) {
// for(let j = height.length - 1; j > i; j--){
// max = Math.max(max, (j - i) * Math.min(height[i], height[j]))
// }
// }
// return max
let i = 0
let j = height.length - 1
while (i < j) {
max = Math.max(max, (j - i) * Math.min(height[i], height[j]))
if (height[i] > height[j])
j--
else
i++
}
return max
};
数组里是否有两个数之和等于某个数
function addtwoarr() {
}
有一个数组,其他数都出现两次,只有一个数出现一次,找出出现一次的值
/*解题思路:用异或解决(两个相同的数异或结果为0,一个不为0的数跟0异或结果为这
个数本身)*/
function oneshu(arr) {
var a = 0
for (var i in arr) {
a = a ^ arr[i]
}
return a
}
// console.log(oneshu([1,2,3,3,2]))
有一个数组,其他数出现两次,只有一个数出现一次,找出出现一次的值(可能有字符)
function onechar(strarr) {
var a = 0;
var b
for (var i in strarr) {
if ((strarr[i] >= 'a' && strarr[i] <= 'z') || strarr[i] >= 'A' && strarr[i] <= 'Z') {
b = strarr[i].charCodeAt()//把这个字符变成数字
} else {
b = strarr[i];
}
a = a ^ b;
}
return String.fromCharCode(a)//把a重新变成字符
}
// console.log(onechar(['a','a','b','b','c']))
找出句子中的最长的单词,并返回他的长度
function lenci(str) {
var arr = str.split(' ');
var a = 0;
arr.map(function (item) {
if (item.length > a) {
a = item.length
}
})
return a
}
// console.log(lenci('a aa aaaaa aaaa a'))
字符串是否是指定字符结尾
function strtail(str, target) {
var len = target.length
var a = str.slice(str.length - len, str.length);
return (a === target) ? true : false;
//或者用substr()截取字符串的方法
}
// console.log(strtail('asdasdcx',"cxa"));
判断字符串是否有指定子字符串
function strtrue(str, target) {
return (str.indexOf(target) == -1) ? false : true
}
// console.log(strtrue('asdasdxc','xc'))
字符串中出现最多的字符,返回该字符,及次数{‘字符’:次数}
function strmax(str) {
var a = str.split('');
var target = {}
for (var i in a) {
if (!target.hasOwnProperty(a[i])) {
target[a[i]] = 1
} else {
target[a[i]] += 1;
}
}
var b = 0;
var c;
for (var i in target) {
if (b < target[i]) {
c = i;
b = target[i]
}
}
var aa = {}
aa[c] = b
return aa
}
// console.log(strmax(' afjghdfraaaasdenas'))
扁平化数组,并排序1
var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]
function bianpinghua(arr, newarr = []) {
arr.forEach(item => {
if (Object.prototype.toString.call(item) === '[object Array]') {
bianpinghua(item, newarr)
} else {
if (!newarr.includes(item)) {
newarr.push(item)
}
}
})
return newarr.sort((a,b) => a-b)
}
console.log(bianpinghua(arr))
扁平化数组,并排序2
var old_arr=[ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];
// 数组拍平
var level_arr=old_arr.flat(4);
//数组去重
var Distinct=Array.from(new Set(level_arr));
// 排序
var sort= Distinct.sort((a, b) =>a - b)
console.log("new arr",sort)
排序算法
冒泡排序
function maopao(arr) {
for (var i = 0; i < arr.length; i++) {
for (var j = 0; j < (arr.length - i); j++) {
if (arr[j] > arr[j + 1]) {
var a = arr[j + 1];
arr[j + 1] = arr[j]
arr[j] = a
}
}
}
return arr
}
// console.log(maopao([1, 5, 4, 2, 9, 3]))
插入排序(把无序的第一个插入到有序的适当位置上)
function charu(arr) {
for (var i = 0; i < arr.length; i++) {
var a = arr[i]
var b = i;//当前记录位置
for (var j = i; j >= 0; j--) {
if (a < arr[j]) {
arr[j + 1] = arr[j]//实现前后交换
b = j//放到指定的位置的下标
}
}
arr[b] = a;
}
return arr
}
快速排序
function quickSort(arr){
//如果数组<=1,则直接返回
if(arr.length<=1){return arr;}
var pivotIndex=Math.floor(arr.length/2);
//找基准,并把基准从原数组删除
var pivot=arr.splice(pivotIndex,1)[0];
//定义左右数组
var left=[];
var right=[];
//比基准小的放在left,比基准大的放在right
for(var i=0;i<arr.length;i++){
if(arr[i]<=pivot){
left.push(arr[i]);
}
else{
right.push(arr[i]);
}
}
//递归
return quickSort(left).concat([pivot],quickSort(right));
}
选择排序
function selectSort(arr){
var len = arr.length
for(var i= 0;i<len-1;i++){
for(var j = i+1;j<len;j++){
if(arr[i]>arr[j]){
var temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
}
}
return arr
}
/*选择排序的思想是:把每一个数都与第一个数比较,如果小于第一个数,就把它们交换位
置;这样一轮下来,最小的数就排到了最前面;重复n-1轮,就实现了选择排序*/
防抖
在事件触发n秒后再执行回调函数,若在n秒内又触发了事件,则重新计时
function debounce(fn, wait) {
var timeout = null; //定义一个定时器
return function() {
var self = this
var args = arguments
if(timeout !== null)
clearTimeout(timeout); //清除这个定时器
timeout = setTimeout(function () {
fn.apply(self, args )
timeout = null
}, wait);
}
}
function handle() {// 处理函数
console.log(Math.random());
}
window.addEventListener('scroll', debounce(handle, 1000));// 滚动事件
1.时间戳解决函数节流
节流: 在事件触发后每n秒执行一次回调函数,若在n秒内又触发了事件,则忽略该次事件
var throttle = function(func, delay) {
var prev = Date.now();
return function() {
var context = this; //this指向window
var args = arguments;
var now = Date.now();
if (now - prev >= delay) {
func.apply(context, args);
prev = Date.now();
}
}
}
function handle() {
console.log(111);
}
window.addEventListener('scroll', throttle(handle, 1000));
2.定时器解决函数节流
var throttle = function(func, delay) {
var timer = null;
return function() {
var context = this;
var args = arguments;
if (!timer) {
timer = setTimeout(function() {
func.apply(context, args);
timer = null;
}, delay);
}
}
}
function handle() {
console.log(222);
}
window.addEventListener('scroll', throttle(handle, 1000));
/*3.综合解决函数节流,因为前面的两个都有缺陷,会导致第一次不会立刻执行,
希望第一次触发马上执行函数,最后一次触发也可以执行一次事件处理函数*/
var throttle = function(func, delay) {
var timer = null;
var startTime = Date.now(); //设置开始时间
return function() {
var curTime = Date.now();
var remaining = delay - (curTime - startTime); //剩余时间
var context = this;
var args = arguments;
clearTimeout(timer);
if (remaining <= 0) { // 第一次触发立即执行
func.apply(context, args);
startTime = Date.now();
} else {
timer = setTimeout(func, remaining);
//取消当前计数器并计算新的remaining
}
}
}
function handle() {
console.log(222);
}
window.addEventListener('scroll', throttle(handle, 1000));
广度优先跟深度优先
let node = [
{
'label': '1'
},
{
'label':'2',
'child': [
{
'label': '2-1'
},
{
'label': '2-2',
'child': [
{
'label': '2-2-1'
},
{
'label': '2-2-2'
},
{
'label': '2-2-3'
}
]
},
{
'label': '2-3'
}
]
},
{
'label': '3'
}
]
// 广度优先
let stash = []
let nodes = []
function gd (node) {
node.forEach(item => {
stash.push(item)
nodes.push(item.label)
})
whild(stash.length){
let item = stash.shift()
if(item.child){
gd(item.child)
}
}
}
//深度优先1
let nodeslist = []
function sd(node){
if(node !== null) {
node.forEach(item => {
nodeslist.push(item.label)
if (item.child) {
sd(item.child)
}
})
}
}
//深度优先2
function sd(node){
let nodeslist = []
if(node !== null) {
node.forEach(item => {
nodeslist.push(item.label)
if (item.child) {
nodeslist = nodeslist.concat(sd(item.child))
}
})
}
return nodeslist
}
// 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标,你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
var twoSum = function(nums, target) {
let a = []
for(let i = 0;i < nums.length;i++){
let index = a.indexOf(target - nums[i])
if(index === -1){
a[i] = nums[i]
} else {
return [index, i]
}
}
};
手撕new
js的new操作符做了哪些事情
1、创建一个空的对象
2、链接到原型
3、绑定this指向,执行构造函数
4、确保返回的是对象
function _new(fn, ...arg) {
const obj = Object.create(fn.prototype);
const ret = fn.apply(obj, arg);
return ret instanceof Object ? ret : obj;
}
function foo(name, age) {
this.name = name;
this.age = age;
//console.log(this); //此时this已经发生变化了
}
var f = _new(foo,'dzy',18);
console.log(f);
第二种
function New() {
var obj = {};
var Constroctor = [].shift.call(arguments); // 将第一个值拿出来
obj.__proto__ = Constroctor.prototype; // 将对象与构造函数原型链接起来
var result = Constroctor.apply(obj, arguments); // 将构造函数的this指向这个对象,并传递参数
return typeof result === "object" ? result : obj;
}
js链式调用
class Person {
constructor(name) {
this.name = name;
this.queue = Promise.resolve(); // 初始队列为一个已解决的 Promise
}
say(message) {
this.queue = this.queue.then(() => {
return new Promise((resolve) => {
console.log(message + this.name);
resolve();
});
});
return this; // 返回当前实例,以支持链式调用
}
sleep(duration) {
this.queue = this.queue.then(() => {
return new Promise((resolve) => {
setTimeout(resolve, duration);
});
});
return this; // 返回当前实例,以支持链式调用
}
eat(food) {
this.queue = this.queue.then(() => {
return new Promise((resolve) => {
console.log(food);
resolve();
});
});
return this; // 返回当前实例,以支持链式调用
}
}
function a(name) {
return new Person(name);
}
a("小明").say("hi").sleep(1000).eat("水果").sleep(2000).eat("123").sleep(3000).eat("456").sleep(1000).eat(789);