本文已参与「新人创作礼」活动,一起开启掘金创作之路。
题目
给定一个候选人编号的集合 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))
}