javascript排序算法对比
时间复杂度看运行情况,空间复杂度看占用的空间
冒泡排序:
export default (arr) => { // 冒泡排序 for (let i = arr.length - 1, tmp; i > 0; i--) { for (let j = 0; j < i; j++) { tmp = arr[j] if (tmp > arr[j + 1]) { arr[j] = arr[j + 1] arr[j + 1] = tmp } } } return arr }
选择排序:
//选择排序 export default (arr) => { // 选择排序 for (let i = 0, len = arr.length, min; i < len; i++) { min = arr[i] for (let j = i + 1; j < len; j++) { if (arr[j] < min) { let c = min min = arr[j] arr[j] = c } } arr[i] = min } return arr }
常规做法:
export default (arr) => { // 如果数组长度小于2返回0 if (arr.length < 2) { return 0 } // 排序 arr.sort() // 用它来保存相邻元素的最大差值 let max = 0 for (let i = 0, len = arr.length - 1, tmp; i < len; i++) { tmp = arr[i + 1] - arr[i] if (tmp > max) { max = tmp } } return max }
export default (arr) => { if (arr.length < 2) { return 0 } let max = 0 let len = arr.length - 1 let space for (let i = len, tmp; i > 0; i--) { for (let j = 0; j < i; j++) { tmp = arr[j] if (tmp > arr[j + 1]) { arr[j] = arr[j + 1] arr[j + 1] = tmp } } if (i < len) { space = arr[i + 1] - arr[i] if (space > max) { max = space } } } return Math.max(max, arr[1] - arr[0]) }
export default (arr) => { // 进行升序排序 arr.sort((a, b) => a - b) // 声明一个空数组用来存储奇偶排序后的数组 let r = [] // 记录奇数、偶数位下标 let odd = 1 let even = 0 // 对数组进行遍历 arr.forEach(item => { if (item % 2 === 1) { r[odd] = item odd += 2 } else { r[even] = item even += 2 } }) return r }
export default (arr,k)=>{ arr.sort((a,b)=>b-a)[k-1] } export default (arr, k) => { let len = arr.length - 1 for (let i = len, tmp; i > len - k; i--) { for (let j = 0; j < i; j++) { if (arr[j] > arr[j + 1]) { tmp = arr[j] arr[j] = arr[j + 1] arr[j + 1] = tmp } } } // arr[len+1-k] return arr[len - (k - 1)] }
export default (arr) => { // 过滤掉非正整数 arr = arr.filter(item => item > 0) // 正整数数组是不是为空 if (arr.length) { // 升序,目的:方便从左到右取最小值arr[0] arr.sort((a, b) => a - b) // 如果第一个元素不为1,返回1 if (arr[0] !== 1) { return 1 } else { // 从左边开始遍历,只要下一个元素和当前元素差值》1说明当前元素的下一个值(+1) for (let i = 0, len = arr.length - 1; i < len; i++) { if (arr[i + 1] - arr[i] > 1) { return arr[i] + 1 } } // 如果数组是连续的正整数【1,2,3,4,5,6】 return arr.pop() + 1 } } else { return 1 } } export default (arr) => { arr = arr.filter(item => item > 0) // 实现选择排序,先拿到最小值,如果第一个元素不是1直接返回1,如果是1,就要比相邻元素差值 for (let i = 0, len = arr.length, min; i < len; i++) { min = arr[i] for (let j = i + 1; j < len; j++) { if (arr[j] < min) { let c = min min = arr[j] arr[j] = c } } arr[i] = min if (i > 0) { if (arr[i] - arr[i - 1] > 1) { return arr[i - 1] + 1 } } else { if (min !== 1) { return 1 } } } return arr.length ? arr.pop() + 1 : 1 }
递归:
export default (str) => { // 保存所有符合条件的IP地址 let r = [] // 分四步递归处理ip分段 let search = (cur, sub) => { // 边界条件 if (cur.length === 4 && cur.join('') === str) { r.push(cur.join('.')) } else { // 正常的处理过程 for (let i = 0, len = Math.min(3, sub.length), tmp; i < len; i++) { tmp = sub.substr(0, i + 1) if (tmp < 256) { search(cur.concat([tmp]), sub.substr(i + 1)) } } } } search([], str) return r }
拆分单词:
export default (str, words) => { // 保存结果 let result = [] // 记录数组的长度,做边界条件计算 let num = words.length // 递归函数体 let range = (r, _arr) => { if (r.length === num) { result.push(r) } else { _arr.forEach((item, idx) => { let tmp = [].concat(_arr) tmp.splice(idx, 1) range(r.concat(item), tmp) }) } } range([], words) // [0, 9, -1] filter 之后[0,9] return result.map(item => { return str.indexOf(item.join('')) }).filter(item => item !== -1).sort() }
棒球求和
export default (arr)=>{ //用数组实现堆栈结构 pop push let result=[] //上一轮的数据 let pre1 //上上轮的数据 let pre2 //对数组进行遍历,遍历的目的是处理得分 arr.forEach(item=>{ switch(item){ case 'C': if(result.length){ result.pop() } break case 'D': pre1=result.pop() result.push(pre1,pre1*2) break case '+': pre1=result.pop() pre2=result.pop(pre2,pre1,pre2+pre1) break default: result.push(item*1) } }) return result.reduce((total,num)=>{return total+num}) }
export default (arr)=>{ let result=[] let reg=/1{2,}/g //把二维数组重新表达,把相邻的1提取出来(起始点+截止点) arr= arr.map(item=>{ let str=item.join('') let r=reg.exec(str) let rs=[] while(r){ rs.push([r.index,r.index + r[0].length-1]) //起始位置和结尾位置 r=reg.exec(str) } return rs }) //通过递归计算相邻的矩阵 let maxRect=(arr,result,n=1)=>{ //弹出第一行 let top=arr.pop() //弹出第二行 let next=arr.pop() //记录第一行的每一个起始点和截止点 let tt //记录第二行的每一个起始点和截止点 let nn //记录交叉的起始索引 let start //记录交叉的截止位置 let end let width=1 let maxWidth=1 n++ for(let i=0,il=top.length;i<il;i++){ tt=top[i] for(let j=0,jl=next.length;j<jl;j++){ nn=next[j] width=Math.min(tt[1],nn[1])-Math.max(tt[0],nn[0]) if(width>maxWidth){ maxWidth=width start=Math.max(tt[0],nn[0]) end =Math.min(tt[1],nn[1]) } } } //如果没有找到交叉点 if(start===undefined||end===undefined){ if(n<3){ return false }else{ width=rop[0][1]-top[0][0]+1 if(width>1){ result.push((n-1)*width) } } }else{ arr.push([[start,end]]) maxRect(arr,result,n++) } } while(arr.length>1){ maxRect([].concat(arr),result) arr.pop() } //取最大值 let max=0 let item=result.pop() while(item){ if(item> max){ max>=item } item=result.pop() } return max>0?max:-1 }