算法打卡第四天

112 阅读2分钟
  1. 剑指 Offer 03. 数组中重复的数字
  2. 剑指 Offer 53 - I. 在排序数组中查找数字 I
  3. 剑指 Offer 53 - II. 0~n-1中缺失的数字

剑指 Offer 03. 数组中重复的数字

在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/sh… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题意理解 找到数组中的任一重复数字 遍历当前数组, 如果索引 = 下标,则向后遍历,否则进行交换

// 比较好的一种方法
let cur
for (let i = 0; i < nums.length; i++) {
    while (nums[i] != i) {
        cur = nums[i]
        if (nums[i] == nums[cur]) {
            return nums[i];
        } else {
            nums[i] = nums[cur];
            nums[cur] = cur;
        }
    }
}

// 牺牲速度 减少内存消耗
// for (let i = 0; i < nums.length; i++) {
//     console.log(nums[i],nums.indexOf(nums[i]),nums.lastIndexOf(nums[i]));
//     if (nums.indexOf(nums[i]) == nums.lastIndexOf(nums[i])) {
//         console.log(1);
//         continue;
//     }
//     return nums[i]
// }

// 使用Set
// let newNums = new Set();
// for (let i = 0; i < nums.length; i++) {
//     if (newNums.has(nums[i])) {
//         return nums[i]
//     }
//     newNums.add(nums[i])
// }

// 利用值即索引
// let newNums = [];
// for (let i = 0; i < nums.length; i++) {
//     if (newNums[nums[i]] === nums[i]) {
//         return nums[i]
//     }
//     newNums[nums[i]] = nums[i]
// }

// 暴力
// let newNums = [];
// for (let i = 0; i < nums.length; i++) {
//     if(!newNums.includes(nums[i])){
//         newNums.push(nums[i])
//         continue
//     }
//     return nums[i]
// }

// 使用Map
// let map = new Map();
// for (let i = 0; i < nums.length; i++) {
//     if (map.has(nums[i])) {
//         return nums[i]
//     }
//     map.set(nums[i], 1)
// }

剑指 Offer 53 - I. 在排序数组中查找数字 I

统计一个数字在排序数组中出现的次数。

题意分析 数组已排序, 所以只需查找改数字的起始位置就可以统计出来

目前我已知好的方法

var search = function(nums, target) {
    const startIndex = nums.indexOf(target)
    const endIndex = nums.lastIndexOf(target)
    if (startIndex === -1) {
        return 0
    }
    return endIndex - startIndex + 1
};

剑指 Offer 53 - II. 0~n-1中缺失的数字

一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

题意分析 题中给出的数组索引和索引值相同, 不相同的就是索要找的数字

  1. 先把边界值处理一下;如果nums[0]!==[0]或nums.length===0,则返回0;如果nums[nums.length-1]===nums.length-1,则返回nums.length
  2. 其他情况在中间,二分查找即可,终止条件left>right,返回left; 如果mid===nums[mid],在要找的数在右边;否则在左边
function missingNumber(nums) {
    // for (let i = 0; i < nums.length; i++) {
    //     if (nums[i] !== i) {
    //         return i
    //     }
    // }
    // return nums.length

    // 二分查找
    const length = nums.length;
    if (!length) {
        return 0
    }
    let left = nums[0];
    let right = nums[length - 1];
    if (right === length - 1) {
        return length
    }
    if (left !== 0) {
        return 0
    }
    while (left <= right) {
        let mid = (left + right) / 2 | 0;
        if (mid === nums[mid]) {
            left = mid + 1
        } else {
            right = mid - 1
        }
    }
    return left

    // 递归加二分
    // const length = nums.length;
    // if (!length) {
    //     return 0
    // }
    // let left = nums[0];
    // let right = length - 1;
    // // 处理边界
    // if (nums[right] === right) {
    //     return length
    // }
    // if (left !== 0) {
    //     return 0
    // }
    // function rec(num1, num2) {
    //     let mid = (num1 + num2) / 2 | 0;
    //     if (num1 > num2) {
    //         return num1;
    //     }
    //     if (nums[mid] === mid) {
    //         return rec(mid + 1, num2)
    //     }
    //     if (nums[mid] > mid) {
    //         return rec(num1, mid - 1)
    //     }
    // }
    // const res = rec(left, right)
    // return res;
}