leetcode刷题总结

110 阅读2分钟

1.动态规划

1.1 返回方案数/组合数

排列数(顺序不同也是新的一种方案)

组合总和IV

var combinationSum4 = function(nums, target) {
    let dp=new Array(target+1).fill(0)
    dp[0]=1
    for(let i=1;i<=target;i++){
        for(let j=0;j<nums.length;j++){
            if(i-nums[j]>=0){
                dp[i]+=dp[i-nums[j]]
            }
        }
    }
    return dp[target]
};

组合数(顺序不同也是同一种方案)

零钱兑换II

var change = function(amount, coins) {
    const dp = new Array(amount + 1).fill(0);
    dp[0] = 1;
    for (const coin of coins) {
    //
        for (let i = coin; i <= amount; i++) {
            dp[i] += dp[i - coin];
        }
    }
    return dp[amount];
};

如果求组合数就是外层for循环遍历数组,内层for遍历目标值,内层要倒着遍历

如果求排列数就是外层for遍历目标值,内层for循环遍历数组

1.2 返回可能的具体方案/组合

这种一般都是回溯+剪枝。并不算动态规划,放这里是区分不同情况,防止该回溯的时候用动态规划。

组合总和

/**
 * @param {number[]} candidates
 * @param {number} target
 * @return {number[][]}
 */
var combinationSum = function(candidates, target) {
    const res=[]
    var dfs=function(index,target,arr){
        if(target===0){
            res.push([...arr])
            return
        }
        for(let i=index;i<candidates.length;i++){
            if(target-candidates[i]>=0){
                dfs(i,target-candidates[i],[...arr,candidates[i]])
            }
        }
    }

    dfs(0,target,[])

    return res
};

2.排序

2.1 堆排序

有图的排序过程

堆排序首先建堆,建堆从下往上、从右往左调整,每调整一个父子组合,都要看有没有影响下面的,再向下调整。调整完继续从下往上、从右往左调整。 然后最大的就被放到了数组第一位,与最后一位交换。交换后是从上向下调整一遍就行了,注意这次调整不能再调整数组最后一位了,这是易错点,调整上界要不断减少。

剑指offer求第k大的数

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */
var findKthLargest = function(nums, k) {
    heapSort(nums)
    return nums[nums.length-k]
    //堆排序
    function heapSort(nums){
        let count=1
        //建堆
        heapBuild(nums)
        while(count<=k){
            //交换并从上向下调整
            swap(nums,0,nums.length-count)
            count++
            justify(nums,0,nums.length-count)
        }
    }
    //建大根堆
    function heapBuild(nums){
        // 从最后一个非叶结点从右向左,从下向上调整
        for(let i=Math.floor((nums.length-1)/2);i>=0;i--){
            justify(nums,i,nums.length-1)
        }
    }

    //调整堆,选出左右孩子最大的与之交换,注意heapSize是调整堆的最大下标
    function justify(arr,start,heapSize){
        let left=2*start+1
        let right=2*start+2
        let largest=start
        if(left<=heapSize && arr[left]>arr[largest]){
            largest=left
        }
        if(right<=heapSize && arr[right]>arr[largest]){
            largest=right
        }
        if(largest!=start){
            swap(arr,largest,start)
            //交换以后引起下面不满足大根堆条件,继续递归调整
            justify(arr,largest,heapSize)
        }
    }

    function swap(arr,i,j){
        let temp=arr[i]
        arr[i]=arr[j]
        arr[j]=temp
    }
};

2.2 快速排序

function partition(arr,start,end){
        if(start<=end){
            return
        }
        let target=arr[start]
        let low=start,high=end
        while(low<high){
            while(low<high && arr[high]>=target){
                high--
            }
            arr[low]=arr[high]
            while(low<high && arr[low]<=target){
                low++
            }
            arr[high]=arr[low]
        }
        arr[low]=target
        partition(arr,start,low-1)
        partition(arr,low+1,end)
}
   
function quickSort(nums){
    partition(nums,0,nums.length-1)
}

数组中的第k大的数