leetCode-热题100-普通数组合集(JavaScript)

普通数组

[1- 最大数组和](#1- 最大数组和)

[2- 合并区间](#2- 合并区间)

[3- 轮转数组](#3- 轮转数组)

[4- 除了自身以外数组的乘积](#4- 除了自身以外数组的乘积)

[5- 缺失的第一个正数](#5- 缺失的第一个正数)

1- 最大数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组是数组中的一个连续部分。

复制代码
var maxSubArray = function(nums) {
    // 贪心算法
    // Kadane算法
    // currentSum 记录当前的累加和
    let currentSum = nums[0]
    // maxSum 记录历史最高分(初始化为 nums[0])。
    let maxSum = nums[0]
    for(let i = 1; i < nums.length; i++){
        if (currentSum > 0) {
            // 如果前面的累加和是正数,对我有正面贡献,我就加上它
            currentSum += nums[i];
        } else {
            // 如果前面的累加和是负数或0,对我没好处,我直接从当前数字重新开始
            currentSum = nums[i];
        }
        // 更新最高分
        maxSum = Math.max(currentSum,maxSum)
    }
    return maxSum
};

2- 合并区间

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间

复制代码
var merge = function(intervals) {
    // 合并区间:先升序排序,再判断是否需要合并
    if(intervals.length === 0) return []
    // 按子区间左端点升序排序
    intervals.sort((a,b)=>a[0]-b[0])
    // 记录合并后的区间
    let result = []
    // 取排序后的第一个区间作为合并中的区间
    let prev = intervals[0]
    // 遍历后续区间,是否重叠需要合并
    for(let i =1;i < intervals.length; i++){
        // 依次遍历后面的区间
        let curr = intervals[i]
        // 有重叠:curr的左端点 <= prev的右端点
        if(curr[0] <= prev[1]){
            // 更新prev的右端点为两个区间中的右端点的较大值
            prev[1] = Math.max(prev[1],curr[1])
        }else{
            // 无重叠,将当前prev存入结果数组
            result.push(prev)
            // 取curr作为当前prev,进行下一轮比较
            prev = curr
        }
    }
    // 最后一个合并好的区间也要存入
    result.push(prev)
    return result
};

var merge = function(intervals) {
    // 和上一个解法逻辑相同
    // 但不用另外使用一个prev来维护正在合并中的区间
    // 使用result中的最后一个区间作为prev
    // 每次比较不是直接在result中添加新的curr就是维护更新旧的prev的右端点
    let result = []
    intervals.sort((a,b)=>a[0]-b[0])
    for(let curr of intervals){
        //
        if(result.length === 0 || curr[0] > result[result.length - 1][1]){
            result.push(curr)
        }else{
            result[result.length - 1][1] = Math.max(curr[1],result[result.length - 1][1])
        }
    }
    return result
};

3- 轮转数组

给定一个整数数组 nums,将数组中的元素向右轮转 k个位置,其中 k是非负数。

复制代码
var rotate = function(nums, k) {
    // 三步反转法
    // 轮转后的结果其实就是把数组分成两部分,然后分别处理
    // 1.反转整个数组元素
    // 2.反转前k个数组元素
    // 3.反转剩余数组元素

    // k可能会大于数组长度
    k = k%nums.length
    // 反转函数
    const reverse = (start,end) => {
        while(start < end){
            [nums[start], nums[end]] = [nums[end], nums[start]]
            start++
            end--
        }
    }
    // 三步翻转法
    reverse(0,nums.length-1)
    reverse(0,k-1)
    reverse(k,nums.length-1)

    // 向右移动 k 位,本质上是把末尾的 k 个元素挪到最前面
    // 局部反转将每一部分的顺序修正回正向
};

4- 除了自身以外数组的乘积

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除了 nums[i] 之外其余各元素的乘积 。

题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。

不要使用除法, 且在 O(n) 时间复杂度内完成此题。

复制代码
var productExceptSelf = function(nums) {
    // 前缀积 × 后缀积:(i 左边所有数的乘积) × (i 右边所有数的乘积)
    const n = nums.length
    // answer维护元素左边的前缀积
    let answer = new Array(n)
    // 第一个元素左边有没有元素,初始化第一个元素的前缀积为1
    answer[0] = 1

    // 计算每一个元素的前缀积
    for(let i = 1; i < n; i++){
        // 当前元素的前缀积 = 前一个元素的前缀积*前一个元素值
        answer[i] = answer[i-1] * nums[i-1]
    }

    // 使用right维护后缀积,逻辑和前缀积一样
    let right = 1
    for(let i = n-1; i >= 0; i--){
        // 此时answer[i]已经是i的前缀积了
        // right是i的后缀积
        answer[i] = answer[i] * right

        // 更新后缀积,为下一个i-1元素准备
        right *= nums[i]
    }

    return answer
};

5- 缺失的第一个正数

给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。

请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。

复制代码
var firstMissingPositive = function(nums) {
    // 萝卜回家
    // 数组中每一个数字x 呆在数组索引值为x-1的位置
    // 判断nums[i] = nums[nums[i] - 1],如果不匹配,进行交换
    // 最后返回第一个不在自己索引值位置的正整数i+1(nums[i] != i+1)

    const n = nums.length
    // 原地交换,让数字 x 放到索引 x-1 的位置上
    for(let i = 0; i < n; i++){
        // 在合理范围 (1 到 n)
        while(nums[i] > 0 && nums[i] <= n && nums[i] !== nums[nums[i] - 1]){
            // 在 JavaScript 中,如果你使用 [a, b] = [b, a] 进行变量交换,且前一行代码没有以分号结尾,JS 引擎会把前一行和这一行连起来解析,导致报错。
            const targetIndex = nums[i] -1;
            // 交换位置
            [nums[i], nums[targetIndex]] = [nums[targetIndex], nums[i]]
        }
    }
    // 查找第一个不在自己位置上的正整数
    for(let i = 0; i < n; i++){
        if(nums[i] !== i +1){
            return i+1
        }
    }
    // 如果全部都在位置上,返回 n + 1
    return n+1
}
相关推荐
元亓亓亓16 小时前
LeetCode热题100--5. 最长回文子串--中等
linux·算法·leetcode
月明长歌16 小时前
Java多线程线程池ThreadPoolExecutor理解总结:6 个核心参数 + 4 种拒绝策略(附完整示例)
java·开发语言
找不到、了16 小时前
JVM 跨代引用与 Card Table 机制
java·jvm
sunywz16 小时前
【JVM】(2)java类加载机制
java·jvm·python
千金裘换酒16 小时前
LeetCode 环形链表+升级版环形链表
算法·leetcode·链表
小鸡吃米…16 小时前
机器学习中的随机森林算法
算法·随机森林·机器学习
进阶小白猿16 小时前
Java技术八股学习Day13
java·jvm·学习
CodeAmaz16 小时前
ConcurrentHashMap(JDK 7/8)详细介绍
java·hashmap·线程安全map
大猫和小黄16 小时前
Tomcat vs Undertow 全面对比
java·tomcat