算法(algorithm),在数学(算学)和计算机科学之中,为任何良定义的具体计算步骤的一个序列,经常使用于计算、数据处理和自动推理。精确而言,算法是一个表示为有限长列表的有效方法。算法应包含清晰定义的指令用于计算函数。 - 来自维基百科git
算法看起来在离咱们通常的开发者不是很近,可是实际上又和咱们的开发息息相关。不一样的算法可能用不一样的时间、空间或效率来完成一样的任务。一个算法的优劣能够用空间复杂度与时间复杂度来衡量。如今想一想大学的时候没有好好的学习算法和数据结构真的是后悔的吐血。本文只是简单理解算法,并不会深刻的讨论。毕竟每个深刻讨论都够喝一壶了。只是理解一下算法的思惟和实现。 毕竟9月是个跳槽黄金时期,说不定能帮上你得忙呢?github
算法在在我看来最直观的做用就在于能够强化咱们的编程思惟逻辑。让我么养成是用简单的方式去解决问题的思惟方式。下面咱们一块儿来入算法的坑。本文中提到的相关的例子,都是相对比较简单的。大部分来自leetcode数组部分。代码都是我本身实现的,并不必定是最优解。欢迎各位大佬在issue中提交
更好的实现方式。解析都写到了代码注释中。算法
为了不一些没必要要的错误,文中的示例使用Typescript
编写,JavaScript
部分代码在这儿,本文主要分了两大部分 LeetCode/简单算法编程
给定一个排序数组,你须要在原地删除重复出现的元素,使得每一个元素只出现一次,返回移除后数组的新长度。不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。数组
示例 给定数组 nums = [1,1,2], 函数应该返回新的长度 2, 而且原数组 nums 的前两个元素被修改成 1, 2。 你不须要考虑数组中超出新长度后面的元素。缓存
/** * 1 删除排序数组中的重复项 * 给定一个排序数组,你须要在原地删除重复出现的元素,使得每一个元素只出现一次,返回移除后数组的新长度。 * 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 * 示例 * 给定数组 nums = [1,1,2], * 函数应该返回新的长度 2, 而且原数组 nums 的前两个元素被修改成 1, 2。 * 你不须要考虑数组中超出新长度后面的元素。 */
const removeDuplicates = function(nums: number[]): number {
let i: number = 0
for (let j = 0; j < nums.length; j++) {
if(nums[j] !== nums[i]) {
i++
nums[i] = nums[j]
}
}
nums.splice(i+1)
console.log(nums)
console.log(nums.length)
return i + 1
}
/** * 解析 * 方法 双指针法 * i是慢指针,j是快指针 当咱们遇到 nums[j] \neq nums[i]nums[j]≠nums[i] 时,跳太重复项的运行已经结束, * 所以咱们必须把它(nums[j]nums[j])的值复制到 nums[i + 1]nums[i+1]。而后递增 ii,接着咱们将再次重复相同的过程,直到 jj 到达数组的末尾为止。 * 复杂度分析: * 时间复杂度: O(n) 假设数组长度是n 那么i和j最多就是遍历n步 * 空间复杂度: O(1) */
removeDuplicates([0,0,1,1,1,2,2,3,3,4])
复制代码
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你能够尽量地完成更多的交易(屡次买卖一支股票)。数据结构
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉以前的股票)。函数
示例性能
输入: [7,1,5,3,6,4]学习
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候 卖出, 这笔交易所能得到利润 = 5-1 = 4 。 随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能得到利润 = 6-3 = 3 。
/** * 2: 买卖股票的最佳时机 * 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 * 设计一个算法来计算你所能获取的最大利润。你最多能够完成一次交易 * 注意:你不能同时参与多笔交易(你必须在再次购买前出售掉以前的股票) * * 输入: [7,1,5,3,6,4] * 输出: 7 * 解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能得到利润 = 5-1 = 4 。 * 随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能得到利润 = 6-3 = 3 。 */
// 第一种方式
const maxProfit = function (prices: number[]): number {
if(prices.length < 2) return 0
// 定义利润
let count: number = 0
let PreMin:number =prices[0]
// 获取最大的单天利润
for (let i = 0; i < prices.length; i++) {
count = Math.max(count, prices[i] - PreMin)
PreMin = Math.min(PreMin, prices[i])
}
console.log(count)
return count
}
/** * 解析: 贪心算法 */
console.log('=================股票最佳购买时机贪心算法===================');
console.log(maxProfit([7,1,5,3,6,4]));
console.log('====================================');
// 第二种方式 这种方式更加简单
const maxProfitMore = function (prices: number[]) :number{
if(prices.length < 2) return 0
let ret = 0
for (let i = 0; i < prices.length; i++) {
// 若是次日的价格大于当天的,那么就计算利润
if (prices[i+1] > prices[i]) {
ret += prices[i+1] - prices[i]
}
}
return ret
}
/** * 解析: 非贪心算法 * 只要下一天的价钱 大于今天的价钱 那咱们就卖出当前天的 最终的结果就是咱们的利润总和 */
console.log('==================股票最佳购买时机非贪心算法==================');
console.log(maxProfitMore([7,1,5,8,3,6,4]))
console.log('=============================================');
复制代码
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
示例 输入: [1,2,3,4,5,6,7] 和 k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右旋转 1 步: [7,1,2,3,4,5,6]
向右旋转 2 步: [6,7,1,2,3,4,5]
向右旋转 3 步: [5,6,7,1,2,3,4]
要求
要求使用空间复杂度为 O(1) 的原地算法。
/** * 3: 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。 * 要求O(1)的空间复杂度,对原数组进行操做 */
const rotate = function(nums: number[], k: number) {
// 循环k,经过k咱们能够肯定须要移动的次数
for (let i = 0; i < k; i++) {
// 先在前面插入咱们须要移动的地方
nums.unshift(nums[nums.length -1 - i])
}
// 最后再去处理咱们的数组
nums.splice(nums.length - k, k)
}
rotate([1,2,3,4,5,6,7],3)
复制代码
给定一个整数数组,判断是否存在重复元素。若是任何值在数组中出现至少两次,函数返回 true。若是数组中每一个元素都不相同,则返回 false。
示例 输入: [1,2,3,1] 输出: true
/** * 4: 存在重复 * 给定一个整数数组,判断是否存在重复元素。 * 若是任何值在数组中出现至少两次,函数返回 true。若是数组中每一个元素都不相同,则返回 false。 * * 这个必定不是最优解 */
const containsDuplicate = function (nums: number[]) :boolean{
// 设置flag
let judge = false
// 容错判断
if (nums.length <= 1) {
return judge
}
// 经过最简单直白的去重的思想去处理
let current :number[] =[]
for (let i = 0; i < nums.length; i++) {
if (current.indexOf(nums[i]) === -1) {
current.push(nums[i])
} else {
return judge = true
}
}
return judge
}
console.log('================是否存在重复算法====================');
console.log(containsDuplicate([3,1]))
console.log('====================================');
// 这个实际上是很是常见并且简单得一个算法 可是要考虑到得状况多一点
复制代码
给定一个非空整数数组,除了某个元素只出现一次之外,其他每一个元素均出现两次。找出那个只出现了一次的元素。
示例
输入: [2,2,1]
输出: 1
要求 你的算法应该具备线性时间复杂度。 不适用额外的空间来实现
/** * 5: 只出现一次得数字 * 给定一个非空整数数组,除了某个元素只出现一次之外,其他每一个元素均出现两次。找出那个只出现了一次的元素。 * 你的算法应该具备线性时间复杂度。 不使用额外空间来实现 */
const singleNumber = function(nums: number[]) :number {
let index= -1
// 双层进行比对 目的是当前key和数组中的每个key进行比较
nums.forEach((key, j)=> {
//每次循环小游标
let count = 0
for (let k = 0; k < nums.length; k++) {
if (key === nums[k]) {
count += 1
}
// 循环完找出符合条件的下标
if (k === nums.length -1 && count === 1) {
index = j
}
}
})
return nums[index]
}
console.log('=================查找单独数算法===================');
console.log(singleNumber([2,2,1,3,3]))
console.log('====================================');
复制代码
给定两个数组,编写一个函数来计算它们的交集。
示例
输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]
要求
/** * 6:求两个数组的交集 */
const intersect = function (nums1:number[], nums2:number[]) :number[]{
let arr:number[] = []
for (let i = 0; i < nums1.length; i++) {
if (nums2.indexOf(nums1[i]) !== -1 ) {
nums2.splice(nums2.indexOf(nums1[i]), 1)
arr.push(nums1[i])
}
}
return arr
}
/** * 解析: 在求交集的过程当中。主要的思想是关于什么是交集。 * 两个数组的重合部分理论上来说就是交集 * 循环其中一个数组nums1在后在另一个数组nums2中比对是否出现,若是出现的话就删除nums2中出现过的数组(注意是修改nums2) */
intersect([1,2,2,1], [2,2])
复制代码
给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一.你能够假设除了整数 0 以外,这个整数不会以零开头。
示例
输入: [1,2,3]
输出: [1,2,4]
/** * 7:加1 * 给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。 * 你能够假设除了整数 0 以外,这个整数不会以零开头。 */
const plusOne =function (nums: number[]) :number[] {
let j = nums.length - 1
// js没法正常表示大于16位的整数【非科学计数】
for (let i = nums.length - 1; i >=0; i--) {
// 开始逐个进行加法运算
if(i == j) {
// 大于10的状况
if(nums[i] + 1 >= 10){
nums[i] = nums[i] + 1 -10
j--
// 最后一次循环
if (i === 0) {
nums.unshift(1)
}
} else {
nums[j] ++
}
} else {
break
}
}
console.log(nums)
return nums
}
/** * 解析: 若是使用太大的数的话转成数字再加1是不行的,咱们须要对数组中的的单个数据进行运算,一样的是以辅助游标进行运算 * 辅助游标j的主要做用是记录须要+1的位置,若是当前的下标不等于j那么就跳出了循环:同时也提升了性能 */
console.log('================加1算法====================');
console.log(plusOne([8,2,1,,1,2,2,2,3,5,5,5,5,5,2,3,4,2,3,4,5,5,5,5,2,9]))
console.log('====================================');
复制代码
给定一个数组 nums,编写一个函数将全部 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
要求
/** * 8: 移动零 * 给定一个数组 nums,编写一个函数将全部 0 移动到数组的末尾,同时保持非零元素的相对顺序。 */
const moveZeroes = function(nums: number[]) {
// 0出现的个数
let j = 0
nums.forEach((el: number, index: number, arr: number[]) => {
if (nums[j] === 0) {
nums.splice(j, 1)
nums.push(0)
} else {
j++
}
})
console.log(nums)
}
/** * 解析: 新建一个小游标j 这个是用来标识0出现的地方,每次移动完以后小游标是不变化的,由于原数组已经修改因此要固定一下游标 * 双游标法在算法真的很实用 */
console.log('==================移动零算法==================');
moveZeroes([1,2,0,0,0,1])
console.log('====================================');
复制代码
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。你能够假设每一个输入只对应一种答案,且一样的元素不能被重复利用。
示例
给定 nums = [2, 7, 11, 15], target = 9
由于 nums[0] + nums[1] = 2 + 7 = 9
因此返回 [0, 1]
/** * 第一种解法 * @param nums * @param target */
const twoSumA = function (nums: number[], target: number) :number[] {
console.log('两数求和第一种解法')
let arr = [0,0] ,flag = false
for (let i = 0; i < nums.length; i++) {
compare(i)
if (flag) {
arr = [i, compare(i)]
break
}
}
/** * @param num */
function compare(index: number) :number {
for (let j = 0; j < nums.length; j++) {
if (j!== index && nums[index] + nums[j] === target) {
flag = true
return j
}
}
}
return arr
}
/** * 第二种解法 */
const twoSumB = function (nums: number[], target: number) :number[] {
let arr = [0,0]
console.log('两数求和第二种解法')
for (let i = 0; i < nums.length; i++) {
for (let j = 0; j < nums.length; j++) {
if (j!== i && nums[i] + nums[j] === target) {
return arr = [i,j]
}
}
}
return arr
}
// 在进行一个数组中两个数得比较中:必定要注意在相加得时候要排除自身去进行相加。
console.log('=================两数之和算法===================');
console.log(twoSumA([3,2,4],6))
console.log(twoSumB([2, 7, 11, 15],9))
console.log('====================================');
复制代码
判断一个 9x9 的数独是否有效。只须要根据如下规则,验证已经填入的数字是否有效便可。
示例
给定
[
["5","3",".",".","7",".",".",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
["8",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]
]
复制代码
输出 js true
说明
/** * 10:有效得数独 */
let board = /* [ ["5","3",".",".","7",".",".",".","."], ["6",".",".","1","9","5",".",".","."], [".","9","8",".",".",".",".","6","."], ["8",".",".",".","6",".",".",".","3"], ["4",".",".","8",".","3",".",".","1"], ["7",".",".",".","2",".",".",".","6"], [".","6",".",".",".",".","2","8","."], [".",".",".","4","1","9",".",".","5"], [".",".",".",".","8",".",".","7","9"] ]*/
[["7",".",".",".","4",".",".",".","."],
[".",".",".","8","6","5",".",".","."],
[".","1",".","2",".",".",".",".","."],
[".",".",".",".",".","9",".",".","."],
[".",".",".",".","5",".","5",".","."],
[".",".",".",".",".",".",".",".","."],
[".",".",".",".",".",".","2",".","."],
[".",".",".",".",".",".",".",".","."],
[".",".",".",".",".",".",".",".","."]
]
const isValidSudoku = function (board: string[][]): boolean {
let isPass = true
const sudokuDeep = 9 // 数独深度
// 判断行和列
for (let i = 0; i < sudokuDeep; i++) {
let row:any = {}
let col:any = {}
for (let j = 0; j < sudokuDeep; j++) {
// 判断行
/** * 判断方式 * 首先判断不为'.' => 而后判断是否存在row对象中 */
if (board[i][j] !== '.') {
if (row[board[i][j]]) {
console.log(board[i][j])
return isPass = false
} else {
row[board[i][j]] = board[i][j]
}
}
// 判断列
if (board[j][i] !== '.') {
if (col[board[j][i]]) {
console.log(board[j][i]);
return isPass = false
} else {
col[board[j][i]] = board[j][i]
}
}
// 判断九宫格 经过余数的形式判断出来当前所处的9宫格
// 先计算出位置
let c = Math.floor(i/3) // col位置
let r = Math.floor(j/3) // row 位置
// 勾勒出九宫格
for (let m = c*3; m < c*3 + 3; m++) {
for (let n = r * 3; n < r * 3 + 3; n++) {
if (m === i && n === j) {
// m === i && n === j 这时指向同一个位置
continue
} else {
// 最重要的一次求值判断
if(board[m][n] != '.' && board[i][j]!== '.' && (board[i][j]) === board[m][n]) {
return isPass = false
}
}
}
}
}
}
return isPass
}
console.log('=================有效数独算法结果===================');
console.log(isValidSudoku(board))
console.log('====================================');
复制代码
给定一个 n × n 的二维矩阵表示一个图像。将图像顺时针旋转 90 度。
示例
给定
[
[1,2,3],
[4,5,6],
[7,8,9]
],
复制代码
输出
[
[7,4,1],
[8,5,2],
[9,6,3]
]
复制代码
要求
你必须在原地旋转图像,这意味着你须要直接修改输入的二维矩阵。请不要使用另外一个矩阵来旋转图像。
/** * 11: 旋转图像 **/
const matrix = [
[1,2,3],
[4,5,6],
[7,8,9]
]
//
/* const matrix = [ [ 5, 1, 9,11], [ 2, 4, 8,10], [13, 3, 6, 7], [15,14,12,16] ] */
const rotateMaps = function (matrix:number[][]) {
const n = matrix.length
// 倒叙循环进行90度的反转
for (let i = n-1; i >= 0; i--) {
// 新数组补位到原数组中,为了是实现原地的旋转操做,若是不须要
for (let j = 0; j < n ; j++) {
// console.log(`当前坐标[${i},${j}]`)
const current = matrix[i][j]
matrix[j].push(current)
// 没完成一组的赋值操做,就删除旋转前数组
if(j === n - 1) {
matrix[i].splice(0, n)
}
}
}
console.log(matrix)
// return matrix
}
console.log('================旋转图像算法====================');
console.log(rotateMaps(matrix));
console.log('====================================');
复制代码
这一部分先出demo,后面的代码中的解析注释会慢慢加上
fid为0表明一级,fid若是和fid为0的cid相等的话表明二级 以此类推...
/** * 10: 找父亲节点 * fid为0表明一级,fid若是和fid为0的cid相等的话表明二级 以此类推... */
const findArr = [
{"fid":0,"cid":3,"flag":"最外层3"},
{"fid":0,"cid":4,"flag":"最外层4"},
{"fid":4,"cid":5,"flag":"最外层-4"},
{"fid":5,"cid":6,"flag":"最外层-4-1"},
{"fid":0,"cid":7,"flag":"最外层7"},
{"fid":7,"cid":8,"flag":"最外层-7"},
{"fid":0,"cid":9,"flag":"最外层9"},
{"fid":9,"cid":10,"flag":"最外层9-1"},
{"fid":9,"cid":11,"flag":"最外层9-2"},
{"fid":11,"cid":12,"flag":"最外层9-2-1"}
]
/** * 第一种方法:双递归方式 * @param arr */
const findfid = function (arr: any[]): any[] {
let newArr:any[] = []
for (let i = 0; i < arr.length; i++) {
let flagId = arr[i].cid // 取出来一个flag 这个是用于和下一个级别匹配的
for (let j = 0; j < arr.length; j++) {
const elJ = arr[j]
if (elJ.fid === flagId) { // fid 和 上级id 匹配
(arr[i].children = []).push(elJ)
}
}
// 只存入第一等级
arr[i].fid === 0 && newArr.push(arr[i])
}
return newArr
}
/** * 第二种方法: 使用对象存储id 而后和fid进行对比 * @param arr */
const findfidByObj = function (arr: any[]): any[] {
let newArr:any[] = []
let flagObj: any = {}
arr.forEach(v => {
flagObj[v.cid] = v
})
arr.forEach (item => {
// 根据当前遍历对象的fid,去map对象中找到对应索引的id
const top = flagObj[item.fid]
if (top) {
// 若是找到索引,那么说明此项不在顶级当中,那么须要把此项添加到,他对应的父级中
(top.children || (top.children = [])).push(item)
} else {
// 若是没有在map中找到对应的索引ID,那么直接把当前的item添加到newData结果集中做为顶级
newArr.push(item)
}
})
return newArr
}
console.log('====================================');
console.log('找父亲节点方式');
console.log(findfid(findArr))
console.log(findfidByObj(findArr))
console.log('====================================');
复制代码
选择排序(Selection sort)是一种简单直观的排序算法。它的工做原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到所有待排序的数据元素排完。 选择排序是不稳定的排序方法。
/** * 交换参数 * @param {*} arr * @param {*} a * @param {*} b */
const swap = function(arr: number[], a:number, b:number) {
let curr = arr[a]
arr[a] = arr[b]
arr[b] = curr
}
/** * * @param {选择排序算法} arr */
const sort = function (arr: number[]) {
console.time()
for (let i = 0; i < arr.length; i++) {
//假设遍历的当前第一个是最小的
let minIndex = i
//第二次遍历把arr[minIndex]和数组中的其余的值进行遍历
for (let j = 0; j < arr.length; j++) {
if(arr[minIndex] > arr[j]){
minIndex = j
}
}
//外层循环作交换
swap(arr,minIndex,i)
}
console.log(arr)
console.timeEnd()
}
sort([3,6,28,123,34])
复制代码
冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。它重复地走访过要排序的元素列,依次比较两个相邻的元素,若是他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。走访元素的工做是重复地进行直到没有相邻元素须要交换,也就是说该元素已经排序完成。
/** * @param {*冒泡排序算法} arr */
const bubbleSort = function (arr: number[]){
console.log('冒泡算法开始时间:')
console.time()
for (let i = 0; i < arr.length; i++) {
// 这个循环时获取到以后的项进行比较
for (let j = i+1; j > 0; j--) {
// 这个核心就是 若是当前项小于前一项那么当前项向上冒泡
if(arr[i] < arr[j-1]){
// 冒泡交换
swap(arr,j,j-1)
}
}
}
console.timeEnd()
console.log(arr)
}
bubbleSort([3,123,6,28,34])
复制代码
插入排序是基于比较的排序。所谓的基于比较,就是经过比较数组中的元素,看谁大谁小,根据结果来调整元素的位置。
//插入排序算法
/** * * @param {插入排序} arr */
const insertSort = function (arr: number[]){
console.time()
for (let i = 0; i < arr.length; i++) {
// 在一次循环的时候首先缓存下来当前的值和上一个index 缓存上一个index用来比较
let compareIndex = i -1
let currentValue = arr[i]
// 在当前位置能够比较而且当前的值小于前一项的值的时候插入缓存的值而后修改index
while (compareIndex >=0 && arr[compareIndex] > currentValue) {
arr[compareIndex + 1] = arr[compareIndex]
compareIndex--
}
arr[compareIndex + 1 ] = currentValue
}
console.timeEnd()
console.log(arr)
}
insertSort([3,2,1])
复制代码
二分查找也称为折半查找。是指在有序的数组里找出指定的值,返回该值在数组中的索引。
/** * 二分查找算法 * 什么叫二分查找? 二分查找也称为折半查找。是指在有序的数组里找出指定的值,返回该值在数组中的索引。 * (1)从有序数组的最中间元素开始查找,若是该元素正好是指定查找的值,则查找过程结束。不然进行下一步; * (2)若是指定要查找的元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半区域查找,而后重复第一步的操做; * (3)重复以上过程,直到找到目标元素的索引,查找成功;或者直到子数组为空,查找失败。 * 注意: 这个先要把数组排序一下 在有序数组中查找 * 优势是比较次数少,查找速度快,平均性能好; * 其缺点是要求待查表为有序表,且插入删除困难。所以,折半查找方法适用于不常常变更而查找频繁的有序列表。 */
/** * 非递归实现 * @param {*} arr * @param {*} target */
function binarySearcNoRecursive(arr: number[], target: number){
let low: number = 0, high: number = arr.length-1
while(low <= high) {
// 首先找到中间位置
let middle = ((high + low ) / 2)
if( target === arr[middle]){
return middle
} else if (target > arr[middle]){
low = middle + 1
} else if ( target < arr[middle] ){
high = middle -1
}else {
return -1
}
}
}
const result = binarySearcNoRecursive( [1,2,3,4,5,6,7,8,9,10,11,23,44,86], 23)
console.log(`二分查找不用循环找到的位置:${result}`)
/** * 递归实现 循环调用自身 * @param {*} arr * @param {*} target */
function binarySearcRecursive(arr: number[], low:number, high: number, target:number){
if(low > high){
return -1
}
let middle = ((high + low ) / 2)
if(arr[middle] === target){
return middle
} else if(arr[middle] > target){
high = middle -1
binarySearcRecursive(arr, low, high, target)
} else if(arr[middle] < target){
low = middle + 1
binarySearcRecursive(arr, low, high, target)
}
}
const recursiveRes = binarySearcNoRecursive( [1,2,3,4,5,6,7,8,9,10,11,23,44,86], 3)
console.log(`二分查找不用循环找到的位置:${recursiveRes}`)
复制代码
算法再编程中占据着至关重要的地位,语言的技术均可以速成。可是算法须要扎实的理论知识做为地基。本文只是根据leetcode中的题目,简单的实现一下。感觉一下算法的魅力。学习的话我建议仍是系统深刻的学。
相应的JavaScript
示例代码地址
原文地址 若是以为有用得话给个⭐吧