力扣100题解及笔记 数组

 目录

1.力扣100题解及笔记 哈希-CSDN博客

2.力扣100题解及笔记 堆-CSDN博客

3.力扣100题解及笔记 栈-CSDN博客

4.力扣100题解及笔记 双指针-CSDN博客

5.力扣100题解及笔记 链表-CSDN博客

6.力扣100题解及笔记 二叉树-CSDN博客

7.力扣100题解及笔记 二分查找-CSDN博客

8.力扣100及题解 滑动窗口&子串-CSDN博客

9.力扣100题解及笔记 回溯-CSDN博客

10.力扣100题解及笔记 dp&多维dp-CSDN博客

11.力扣100题解及笔记 贪心-CSDN博客

12.力扣100题解及笔记 数组-CSDN博客

13.力扣100题解及笔记 技巧-CSDN博客

14.力扣100题解及笔记 矩阵-CSDN博客

15.力扣100题解及笔记 图论-CSDN博客

53.最大子树和

53. 最大子数组和

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

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

 

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:

输入:nums = [1]
输出:1
示例 3:

输入:nums = [5,4,-1,7,8]
输出:23
 

提示:

1 <= nums.length <= 105
-104 <= nums[i] <= 104
public class Solution {
    public int maxSubArray(int[] nums) {
        if (nums == null || nums.length == 0)  return 0;       
        int currentSum = nums[0]; // 当前子数组的和
        int maxSum = nums[0]; // 到目前为止找到的最大子数组和
        for (int i = 1; i < nums.length; i++) {//和为负数,则舍弃并重新开始计数
            currentSum = Math.max(nums[i], currentSum + nums[i]);
            maxSum = Math.max(maxSum, currentSum);
        }
        
        return maxSum;
    }
}

dp

class Solution {
    public int maxSubArray(int[] nums) {
        int[] f = new int[nums.length];
        f[0] = nums[0];
        int ans = f[0];
        for (int i = 1; i < nums.length; i++) {
            f[i] = Math.max(f[i - 1], 0) + nums[i];
            ans = Math.max(ans, f[i]);
        }
        return ans;
    }
}

56.合并区间

56. 合并区间

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


示例 1:

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:

输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。
 

提示:

1 <= intervals.length <= 104
intervals[i].length == 2
0 <= starti <= endi <= 104

比较当前区间与上一区间是否有重叠

class Solution {
    public int[][] merge(int[][] intervals) {
        Arrays.sort(intervals, (p, q) -> p[0] - q[0]);   //升序
        List<int[]> r = new ArrayList<>();
        for (int[] p : intervals) { // 遍历所有区间
            int l = r.size(); // l 表示当前存储的区间数量
            // 如果当前区间的左端点小于等于最后一个合并区间的右端点,则它们重叠,需要合并
            if (l > 0 && p[0] <= r.get(l - 1)[1])  r.get(l - 1)[1] = Math.max(r.get(l - 1)[1], p[1]);
            //重叠,更新最后一个区间的右端点为两者中的最大值
            else r.add(p);
            // 没有重叠,将当前区间添加到结果中
            }
        return r.toArray(new int[r.size()][]);
    }
}

189.轮转数组

189. 轮转数组

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

 

示例 1:

输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
示例 2:

输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释: 
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]
 

提示:

1 <= nums.length <= 105
-231 <= nums[i] <= 231 - 1
0 <= k <= 105

直接三次反转

class Solution {
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        k %= n; // 轮转 k 次等于轮转 k%n 次
        reverse(nums, 0, n - 1);
        reverse(nums, 0, k - 1);
        reverse(nums, k, n - 1);
    }

    private void reverse(int[] nums, int i, int j) {
        while (i < j) {
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
            i++;
            j--;
        }
    }
}

238.除自身以外乘积

238. 除自身以外数组的乘积

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

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

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

 

示例 1:

输入: nums = [1,2,3,4]
输出: [24,12,8,6]
示例 2:

输入: nums = [-1,1,0,-3,3]
输出: [0,0,9,0,0]
 

提示:

2 <= nums.length <= 105
-30 <= nums[i] <= 30
保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在  32 位 整数范围内
 

进阶:你可以在 O(1) 的额外空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组 不被视为 额外空间。)

class Solution {
    public int[] productExceptSelf(int[] nums) {
        int l = nums.length;
        if (l == 0) return new int[0];
        int[] res = new int[l];// res[i] 存储的是 nums[i] 左侧所有元素的乘积
        res[0] = 1;  // 初始化 res[0] 为 1,因为第一个位置的左侧没有元素
        int tmp = 1;  // 用于存储右侧乘积的临时变量
        //从左到右遍历,将每个位置 i 左侧的乘积存储到 res[i]
        for (int i = 1; i < l; i++)  res[i] = res[i - 1] * nums[i - 1];
        // 从右到左遍历数组,使用变量 tmp 来累积右侧的乘积
        for (int i = l - 2; i >= 0; i--) {
            tmp *= nums[i + 1];
            res[i] *= tmp;
        }
        return res;
    }
}

41.缺失第一个正数h

41. 缺失的第一个正数

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

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

示例 1:

输入:nums = [1,2,0]
输出:3
解释:范围 [1,2] 中的数字都在数组中。
示例 2:

输入:nums = [3,4,-1,1]
输出:2
解释:1 在数组中,但 2 没有。
示例 3:

输入:nums = [7,8,9,11,12]
输出:1
解释:最小的正数 1 没有出现。
 

提示:

1 <= nums.length <= 105
-231 <= nums[i] <= 231 - 1
 

public int firstMissingPositive(int[] nums) {
    int l = nums.length;
    // 只关心 [1, l] 范围内的数字,其他替换
    for (int i = 0; i < l; ++i) {
        if (nums[i] <= 0)  nums[i] = l + 1;
    }
    // 不使用额外空间的方式,在原数组上标记哪些正整数已经出现了
    // 将出现的正数对应的下标位置的数置为负数,标记 [1, l] 范围内出现过的数字
    for (int i = 0; i < l; ++i) {
        int num = Math.abs(nums[i]);  // 获取当前数字的绝对值
        if (num <= l) nums[num - 1] = -Math.abs(nums[num - 1]);
    }
    // 遍历数组,找到第一个大于 0 的数的位置,加 1 即为第一个缺失的正数
    for (int i = 0; i < l; ++i) {
        if (nums[i] > 0) return i + 1; 
    }
    // 如果数组中的所有数字都对应位置的值被置为负数,说明 [1, l] 范围内的数字全部存在
    return l + 1;  // 返回 l + 1,即第一个缺失的正数
}

原地哈希可还行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值