目前更新了:二分法,快排, js创建链表, 动态规划, 异或运算,三数之和 ,翻转链表(全部,) 局部,两个栈模拟队列, 经典递归 等
- FindIndex 找到数组中的
第一个
目标值并且返回目标值的下标
, 没有找到就返回-1
判断后返回值,不用手动return
const index = nums.findIndex(item=>item===target)
- find 找到数组中
第一个
符合条件的值
, 没有找到就返回undefined
find对空数组不起作用 sort
会改变原数组
nums.sort((a,b)=>a-b) //升序
nums.sort((a,b)=>b-a) //降序
二分查找 二分详解
二分查找 : 适用于升序数组 , 判断条件是left < right
,不符合条件就返回-1
- 我解题的时候纠结数组分别是奇数和偶数的时候中间值mid怎么取 , 但是不必纠结这个问题 , 因为除以二的时候它们都是有可能出现的 ,
- 重点是判断
边界问题
, 下面采用了左闭右闭
的解法 , 所以判断循环的时候条件是left <= right
, 因为[left , right]
是有意义的 - 当我计算mid的时候使用了
mid = ( left + right ) / 2
, 出来的结果错误的(可能是因为left+right超过了定义变量时的大小),然后我又改变了一种写法:mid = (right-left)/2+left ,计算出来的index居然有小数!!?? 尝试了一下,在js里面5/2=2.5....
- 正确的写法:
const mid = Math.floor((right-left)/2)+left
//防止计算时溢出
let nums = [1,5,6,2,8,89,7,21,4,6,63,10]
const target = 8
//使用二分查找来找到 target 在 nums 中对应值的下标
//查找的条件是查找范围不为空
nums.sort((a,b)=>a-b)
console.log(nums)
var search = function(nums,target){
let left = 0
let right = nums.length-1
while(left <= right){
//每次判断之前都重置 mid
// const mid = (left+right)/2
const mid = Math.floor((right-left)/2)+left
const num = nums[mid]
if(num === target){
return mid
}else if(target > num){
left = mid+1
}else{
right = mid-1
}
}
return -1
}
const result = search(nums,target)
console.log(result);
这道异曲同工之妙,就是缩小空间
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。
如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
var searchInsert = function(nums, target) {
//法一
/* let index = nums.findIndex(item=>item==target)
if(index != -1){
return index
}else{
let index2 = nums.findIndex(item=>item>target)
if(index2==-1)return nums.length
else return index2
} */
//二分法
let left = 0
let right = nums.length-1
let flag = 0
while(left <= right){
let mid = Math.floor((right-left)/2)+left
let num = nums[mid]
if(target == num){
return mid
}else if(target > num){
left = mid + 1
/ /区间缩小到 left 和 right 相等的时候,从这里就出去了,
/ /此时left 在 原来 left = right 那个值的左边一位 ,
/ /刚好就是找不到值要插入的index
}
else
{
right = mid - 1
}
}
return left
};
快排(双边循环 , 递归)
每次都将最左边的值作为基准值
, 然后从最左边的left 和 最右边的 right 开始查找 , 从right开始 , right找的是比基准值小的 , 找到之后left 就开始找 , 找的是比基准值大的 , 找完一轮后交换left 和right 的值, 最后left 和right 重合的时候 , 交换基准值和left 的值
,然后使用递归 , 分别排序基准值左边的 和 右边的
let num = [5,8,6,3,9,2,1,7]
function myquickSort(num,left,right){
let flag = left
if(left>=right)return;
while(left<right){
//找到符合的right
while(right>left&&num[right]>=num[flag])
right--
//找到符合的left
while(right>left&&num[left]<=num[flag])
left++
//交换两者的值
if(left<right)
[num[right],num[left]] = [num[left],num[right]]
}
//交换基准值和rightleft重合的值
[num[left],num[flag]] = [num[flag],num[left]]
return left;
}
function jisuan (num , left , right){
if(left>=right)return;
let flag = myquickSort(num,left,right)
jisuan(num,left,flag-1)
jisuan(num,flag+1,right)
}
jisuan(num,0,num.length-1)
console.log(num);
快排(单边循环 递归)
let num = [4,7,3,5,6,2,8,1]
//单边循环
let quickSort = (num, left, right) => {
let flag = left
let mark = left
while(left<=right){
if(num[left]<num[flag])
{
//这个时候mark就要往右移动一位 , 因为找到了一个小于flag 的数
mark++
[num[left],num[mark]] = [num[mark],num[left]]
}
left++
}
//交换基准数 和 mark 的值
[num[flag],num[mark]] = [num[mark],num[flag]]
//最后要返回基准数
return mark
}
let jisuan = (num, left, right) => {
//既然是递归 , 就要有结束条件
if(left>=right)return;
let flag = quickSort(num, left, right)
jisuan(num, left, flag - 1)
jisuan(num, flag + 1, right)
}
jisuan(num, 0, num.length - 1)
console.log(num);
快排 (非递归)
//当数据量很大的时候 , 递归快排会造成栈溢出 , 为了解决这个问题 , 我们使用js数组 来模拟栈 ,
//将待排序的[left,right]保存到数组中 , 循环取出进行快排
// let num = [4, 7, 3, 5, 6, 2, 8, 1]
let num = [1,3,2,5,9,6,8,7]
//非递归实现快排
const quickSort = (num, left, right) => {
let flag = left
let mark = left
while (left <= right) {
if (num[left] < num[flag]) {
//这个时候mark就要往右移动一位 , 因为找到了一个小于flag 的数
mark++
[num[left], num[mark]] = [num[mark], num[left]]
}
left++
}
//交换基准数 和 mark 的值
[num[flag], num[mark]] = [num[mark], num[flag]]
//最后要返回基准数
return mark
}
//使用非递归的方式进行快排
const jisuan = (num,left,right)=>{
let list = [[left,right]]
while(list.length!=0){
let now = list.pop()
if(now[0]>=now[1])