力扣算法从小白开始

本文详细介绍了从基础算法如二分查找、快速排序,到复杂问题的解决策略如动态规划。讲解了如何实现链表、最小栈以及优化时间和空间的动态规划算法。此外,还探讨了利用位运算解决奇数次数元素的问题,并介绍了经典算法如三数之和的解法。
摘要由CSDN通过智能技术生成

目前更新了:二分法,快排, js创建链表, 动态规划, 异或运算,三数之和 ,翻转链表(全部,) 局部,两个栈模拟队列, 经典递归 等

  1. FindIndex 找到数组中的第一个目标值并且返回目标值的下标 , 没有找到就返回-1
    判断后返回值,不用手动return
const index = nums.findIndex(item=>item===target)
  1. find 找到数组中第一个符合条件的 , 没有找到就返回 undefined find对空数组不起作用
  2. sort 会改变原数组
nums.sort((a,b)=>a-b) //升序
nums.sort((a,b)=>b-a) //降序

二分查找 二分详解

二分查找 : 适用于升序数组 , 判断条件是left < right ,不符合条件就返回-1

  1. 我解题的时候纠结数组分别是奇数和偶数的时候中间值mid怎么取 , 但是不必纠结这个问题 , 因为除以二的时候它们都是有可能出现的 ,
  2. 重点是判断边界问题 , 下面采用了左闭右闭的解法 , 所以判断循环的时候条件是 left <= right , 因为[left , right] 是有意义的
  3. 当我计算mid的时候使用了mid = ( left + right ) / 2 , 出来的结果错误的(可能是因为left+right超过了定义变量时的大小),然后我又改变了一种写法:mid = (right-left)/2+left ,计算出来的index居然有小数!!?? 尝试了一下,在js里面5/2=2.5....
  4. 正确的写法: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])
         
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值