前端算法笔记

经典冒泡排序

思路:比较相邻的元素,如果第一个比第二个大,就交换他们两个,对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对,最后的元素应该会是最大的数,
首次遍历区间:[0, arr.length -2],二次遍历区间:[首次遍历的位置 + 1, arr.length - 1],

 function bubbleSort(arr) {
   for(let i = 0; i < arr.length - 1; i++){ 
     for(let j = i + 1; j <= arr.length - 1; j++) { 
       if(arr[i] > arr[j]) {
         const tempVal = arr[i]
         arr[i] = arr[j]
         arr[j] = tempVal
       }
     }
   }
   return arr
 }

双指针-快速排序

思想:来自于快速排序,在一个有序的数组(从小到大)中最左边一定是最小值,最右边是最大值。我们可将最小值与最大值相加与目标值进行比较,如果两数之和大于目标值,我们就让最大值小一点(读取第二个最大值),如果两数之和小于目标 值,我们就让最小值大一点(读取第二个最小值),如果两数之和刚好等于目标值,保存最大值,最小值,并且让最大值小一 点,最小值大一点。需要注意的是前提条件是数组必须有序!

    function sum2(arr,tartgetVal) {
      const resulutArr = []
      const sortArr = arr.sort(function(a,b){
        return a - b
      })
      let start = 0 
      let end = sortArr.length - 1
      while(start < end) {
        if (sortArr[start] + sortArr[end] === tartgetVal) {
          resulutArr.push([sortArr[start], sortArr[end]])
          start += 1
          end -= 1
        } else if (sortArr[start] + sortArr[end] >= tartgetVal) {
          end -= 1
        } else {
          start += 1
        }
      }
      return resulutArr
    }
    const arr = [1, 4, 3, 2, 6, 5]
    sum2(arr,6)
	/* [Array(2),Array(2)]
		[1,5]
		[2,4]
	*/
	
    function sum3(arr, targetVal) {
      const sortArr  = arr.sort((a,b) => {
        return a - b; 
      })
      console.log(sortArr)
      let result = []
      const len = sortArr.length - 3
      for(let i = 0; i < sortArr.length -3; i++) {
        let left = i + 1, right = sortArr.length - 1
        while(left < right) {
          if(sortArr[i] + sortArr[left] + sortArr[right] === targetVal) {
            result.push([sortArr[i], sortArr[left], sortArr[right]])
            left += 1
            right -= 1
          } else if (sortArr[i] + sortArr[left] + sortArr[right] > targetVal) {
            right -= 1
          } else {
            left += 1
          }
        }
      }
      console.log(result)
      return result
    }
   const arr = [1, 4, 3, 2, 6, 5, 9, 8, 21, 22, 34, 10, 14]
   sum3(arr, 10)
/* 
 [Array(3), Array(3), Array(3)]
  0: [1, 3, 6]
  1: [1, 4, 5]
  2: [2, 3, 5]
*/

两个超长数字字符串和(直接相加会发生溢出)

思路:将超长字符串转换成数组,然后遍历元素进行计算,这里要特别注意字符串的长度差异,可以借助数组的reverse方法进行右对齐,计算完后再对数组reverse恢复,最后就是再次将结果转换成字符串。

	const str1 = '1116781231231231231'
    const str2 = '2224561297978978978989089'
    function fn(str1,tr2) {
      const arr = []
      // 右对齐进行计算
      const arr1 = str1.split('').reverse() 
      const arr2 = str2.split('').reverse()
      const len = arr1.length >= arr2.length ? arr1.length : arr2.length
      // 逢十进一
      let flag = 0
      for(let i = 0; i < len; i++) {
        if (arr1[i] === undefined) {
          arr1[i] = '0'
        } else if (arr1[i] === undefined) {
          arr2[i] = '0'
        }
        const tempResult = (Number(arr1[i]) + Number(arr2[i]) + flag) % 10 
        arr.push(tempResult)
        flag = Number(arr1[i]) + Number(arr2[i]) + flag >= 10 ? 1 : 0
      }  
      return arr.reverse().join('')    
    }
    console.log(fn(str1,str2))
    // 2224562414760210210220320

编辑距离

给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
1、插入一个字符
2、删除一个字符
3、替换一个字符
示例1
输入: word1 = “horse”, word2 = “ros”
输出: 3
解释:
horse -> rorse (将 ‘h’ 替换为 ‘r’)
rorse -> rose (删除 ‘r’)
rose -> ros (删除 ‘e’)

function getDistance(str1,str2) {
	

}

最长公共子序列(可以非连续)

思路:嵌套循环保存所有两个字符串的公共元素和下标,然后进行过滤
过滤条件:
1、不是按下标从小到大排序的项剔除;
2、相邻元素相同下标不同的剔除前一项;

function fn(text1,text2) {
  const arr = []
  for(let i = 0; len1 = text1.length, i < len1; i++) {
    for(let j = 0; len2 = text2.length, j < len2; j++) {
      if (text1[i] === text2[j] && arr.findIndex(item => j === item[0]) === -1) {
        arr.push([j,text2[j]])
      }
    }
  }
  console.log(arr)
  /*
	0: (2) [0, "o"]
	1: (2) [2, "o"]
	2: (2) [17, "o"]
	3: (2) [6, "a"]
	4: (2) [9, "b"]
	5: (2) [10, "t"]
	6: (2) [11, "y"]
	7: (2) [12, "c"]
	8: (2) [14, "d"]
	9: (2) [16, "e"]
  */
  const result = JSON.parse(JSON.stringify(arr))
  for(let i = 0; len3 = result.length, i < len3 - 1; i++) {
    if (result[i][0] > result[i+1][0] || result[i][1] === result[i+1][1]) {
      result.splice(i,1)
    }
  }
  console.log(result)
  /*
  	0: (2) [2, "o"]
	1: (2) [6, "a"]
	2: (2) [9, "b"]
	3: (2) [10, "t"]
	4: (2) [11, "y"]
	5: (2) [12, "c"]
	6: (2) [14, "d"]
	7: (2) [16, "e"]
  */
  return result.reduce((prev,next) => {
    return prev + next[1]
  },'')
}
const text1 = 'oajbtycqwmde'
const text2 = 'opoklgauibtycxdueo'
console.log(fn(text1,text2)) //oabtycde

最长连续公共子序列

const text1 = 'oajbtycqwmde'
    const text2 = 'opoklgauibtycxdueo'

    function fn(text1,text2) {
      const arr = []
      for(let i = 0; len1 = text1.length, i < len1; i++) {
        for(let j = 0; len2 = text2.length, j < len2; j++) {
          if (text1[i] === text2[j] && arr.findIndex(item => j === item[0]) === -1) {
            arr.push([j,text2[j]])
          }
        }
      }
      console.log(arr)
      	/*
      	0: (2) [0, "o"]
		1: (2) [1, "a"]
		2: (2) [3, "b"]
		3: (2) [4, "t"]
		4: (2) [5, "y"]
		5: (2) [6, "c"]
		6: (2) [10, "d"]
		7: (2) [11, "e"]
		*/
      const result = JSON.parse(JSON.stringify(arr))
      const strArr = []
      for(let i = 0; len3 = result.length, i < len3 - 1; i++) {
        if (result[i+1][0] - result[i][0] === 1) {
          strArr.push(result[i][1])
          if (i <= len3 - 3 && result[i+2][0] - result[i+1][0] !== 1) {
            strArr.push(result[i+1][1])
          }
        } else {
          strArr.push('-')
        }
      }
      console.log(strArr)
      //   ["o", "a", "-", "b", "t", "y", "c", "-", "d", "e"]
      const tempResult = strArr.join('').split('-').filter(item => !!item) || []
      console.log(tempResult)
      //   ["oa", "btyc", "de"]
      let maxLength = tempResult[0].length
      let maxStr = tempResult[0] || 'null'
      tempResult.forEach(item => {
        if (item.length > maxLength) {
          maxStr = item
        }
      })
      return maxStr
      // btyc
    }
    console.log(fn(text2,text1)) //btyc

零钱兑换

多段存在交集的时间段,判断是否存在间隔

思路: 先对时间段的开始时间进行升序排列;因为存在时间段的并集,所以需要对排序后的时间段,依次获取连续的时间段的最大时间并集,间断的就从新获取连续(时间段的开始时间小于前一时间段的结束时间)的时间段的最大时间并集,然后得到一系列的最大并集,然后对这一系列的最大并集进行时间间隔的判断。

例:时间段[1,3],[2,7],[8,11],[1,5 ],首先对时间段的开始时间进行升序排列,得到[1,3],[1,5],[2,7],[8,11],然后对这一系列的时间段进行遍历,用数组arr保存初始时间段[1,3],并使用变量temp记录[1,3]做为连续时间段的最大并集,遍历到[1,5]时,[1,5]开始时间小于temp[1,3]的结束时间,说明存在交集需要合并,因为已经是升序排列过所以开始时间不用比较,结束时间取较大,temp[1,3]更新为[1,5],另外需要更新数组arr已保存最大并集的结束时间为5,此时arr为[1,5];当遍历到[2,7],[2,7]开始时间小于temp[1,5]的结束时间,存在交集需要合并,因为升序排列所以开始时间不用比较,结束时间取较大,temp[1,5]更新为[1,7],同时更新数组arr已保存的最大并集的结束时间为7,此时arr为[1,7];当遍历到[8,11]时,[8,11]开始时间大于temp[1,7]的结束时间,不存在交集不需要合并,是一个新的最大并集,更新temp为[8,11],同时数组arr需要保存该最大并集,此时arr为[[1,7],[8,11]];依次遍历得到一系列的最大并集,然后进行间隙判断。

gapCheck(timeRangeList) {
    const __timeRangeList  = JSON.parse(JSON.stringify(timeRangeList))
    // 按开始时间排序, 会改变原数据
    __timeRangeList.sort((a, b) =>
      a.from <= b.from ? -1 : 1
    )
    const timeRangeListLength = __timeRangeList.length
    const timeRangeFirst = __timeRangeList[0]
    if (timeRangeListLength > 1) {
      let from = timeRangeFirst.from
      let to = timeRangeFirst.to
      const tempArr = []
      tempArr.push({ from, to})
      for (let i = 1; i < timeRangeListLength; i++) {
        const item = __timeRangeList[i]
        // from小于等于前一项的to, 需要合并,获取较大值的to
        if (item.from <= to && item.to > to) {
          to = item.to
          // 更新tempArr的最后一项的结束值
          tempArr[tempArr.length - 1].to = to
        }
        // from大于前一项的to,再次保存
        if (item.from > to) {
          from = item.from
          to = item.to
          tempArr.push({from,to})
        }
      }
      // console.log('tempArr', tempArr)
      for (let i = 0; i < tempArr.length - 1; i++) {
        // 前一项的截止时间
        const prevto = tempArr[i].to
        // 后一项的开始时间月份
        const nextfrom = tempArr[i * 1 + 1 + ''].from
        // 间隔1个月及以上需要提示
        const diffTime =
          new Date(nextfrom).getTime() -
          new Date(prevto).getTime()
        const oneMounth = 1 * 30 * 24 * 60 * 60 * 1000
        if (diffTime > oneMounth) {
          this.$notify.error({
            message:'There is a gap found in between your time range'})
          return false
        }
        return true
      }
    }
  }

高频算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值