js的一些简单算法(包括一些经典力扣,持续解题)

13 篇文章 0 订阅
判断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);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值