前端算法(36)

47 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次 。

注意:解集不能包含重复的组合。 

输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

题目解析

思路一

我们使用原数组模拟hashMap,快速判断数字是否存在,例如:下标0为负数,代表1存在,下标1为负数,代表2存在,依此类推,第一个下标不为0的下标+1即为不存在的最小数,如果下标都为负数,则结果为nums.length+1。

var firstMissingPositive = function(nums) {
    var result = nums.length + 1;
    for(var i = 0; i < nums.length; i++) {
        if(nums[i] <= 0) {
            nums[i] = nums.length + 1;
        }
    }
    for(var i = 0; i < nums.length; i++) {
        if(nums[i] >= 1 && nums[i] <= nums.length) {
            var index = nums[i] - 1;
            var originNum = nums[index];
            nums[index] = -1;
            while(originNum >= 1 && originNum <= nums.length) {
                index = originNum - 1;
                originNum = nums[originNum - 1];
                nums[index] = -1;
            }
        }
    }
    for(var i = 0; i < nums.length; i++) {
        if(nums[i] > -1) {
            result = i+1;
            break;
        }
    }
    return result;
};

思路二

我们先进行排序,这里我们使用快排,然后在新数组中找1,找不到就输出1,找到了就进入新的循环继续判断,找到1所在的下标mid,从mid开始往大的数遍历,如果后一个数和前一个数的差值小于等于1,就继续遍历,否则输出mid+1所在下标的值

/**
 * @param {number[]} nums
 * @return {number}
 */
var firstMissingPositive = function(nums) {
    let sorted = quickSort(nums)
    let low = 0
    let high = sorted.length - 1
    let target = 1
    while (low <= high){
        let mid = Math.floor((low + high) / 2)
        if (sorted[mid] == 1){
            while (mid < sorted.length){
                if (sorted[mid + 1] - sorted[mid] <= 1){
                    mid++
                    target = sorted[mid] + 1
                }else {
                    target = sorted[mid] + 1
                    break;
                }
            }
            break;
        } else if (sorted[mid] < 1){
            low = mid + 1
        } else {
            high = mid - 1
        }
    }
    return target
};
let quickSort = (arr) => {
    if (arr.length <= 1) return arr
    let pivotIndex = Math.floor(arr.length / 2)
    let pivot = arr.splice(pivotIndex, 1)[0]
    let left = []
    let right = []
    for (let i = 0; i < arr.length; i++) {
        if (arr[i] < pivot){
            left.push(arr[i])
        } else {
            right.push(arr[i])
        }
    }
    return quickSort(left).concat([pivot], quickSort(right))
}