LeetCode 热题 100 | 普通数组

devtools/2025/1/16 6:37:56/

普通数组基础

  • 动态规划五部曲:
    1.确定dp数组的含义
    2.递推公式
    3.dp数组初始化
    4.遍历顺序
    5.模拟dp数组
  • 合并区间提前排序好数组
  • 轮转数组先翻转全部元素,再根据k % nums.length来翻转不同区间。
  • 前缀和,后缀和的提前计算。如果想省空间,可以把输出数组当作前缀和先存储着,然后动态计算后缀和。
  • 在原数组上进行哈希可以用 置换 或者 负号+下标

53. 最大子数组和

题目讲解:LeetCode
重点:

  1. 确定递推公式。dp[i]是必须选取下标i的子数组的最大和。

思路:

  1. 确定dp数组的含义
    dp[i]是必须选取下标i的子数组的最大和
  2. 递推公式
    dp[i]=max(nums[i], dp[i-1]+nums[i])
  3. dp数组初始化
    dp[0] = nums[0]
  4. 遍历顺序
    从头到尾
  5. 模拟dp数组
    -2, 1, -2, 4, 3, 5, 6, 1, 5

复杂度:

  • n 是数组长度
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)
public int maxSubArray(int[] nums) {int[] dp = new int[nums.length];dp[0] = nums[0];int result = dp[0];for (int i = 1; i < nums.length; i++) {// 重点: 递推公式, 必须取下标i的元素dp[i] = Math.max(nums[i], dp[i - 1] + nums[i]);result = Math.max(result, dp[i]);}return result;
}

56. 合并区间

题目讲解:LeetCode
重点:

  1. 提前按照start从小到大排序好数组

思路:

  1. 提前按照start从小到大排序好数组
  2. 把intervals[0]加入到result中,然后开始遍历intervals。如果当前区间跟result中的最后一个区间重叠了,则更新result中的最后一个区间。如果没有重叠,则直接加入到result中。

复杂度:

  • n 是intervals数组长度
  • 时间复杂度:O(nlogn)。排序的时间
  • 空间复杂度:O(n)
public int[][] merge(int[][] intervals) {List<int[]> result = new ArrayList<>();// 重点: 提前排序数组Arrays.sort(intervals, Comparator.comparingInt(o -> o[0]));result.add(intervals[0]);for (int i = 1; i < intervals.length; i++) {// 重点: 出现重叠时取最大区间if (result.get(result.size() - 1)[1] >= intervals[i][0]) {result.get(result.size() - 1)[1] = Math.max(result.get(result.size() - 1)[1], intervals[i][1]);} else {result.add(intervals[i]);}}return result.toArray(new int[result.size()][]);
}

189. 轮转数组

题目讲解:LeetCode
重点:

  1. 使用额外数组:%nums.length根据新数组位置取模看在旧数组哪个位置
  2. 数组翻转:先将所有元素翻转,再翻转[0, k % n − 1]和[k % n, n − 1]

思路:

  • 使用额外数组
    初始化新数组,旧数组元素索引+k对旧数组长度取模就是在新数组的位置。
  • 数组翻转
    先将所有元素翻转,这样尾部的 k % n 个元素就被移至头部。再翻转[0, k % n − 1]的元素和[k % n, n − 1]的元素就能得到答案

复杂度:

  • n 是数组长度
  • 使用额外数组
    时间复杂度:O(n)
    空间复杂度:O(n)
  • 数组翻转
    时间复杂度:O(n)
    空间复杂度:O(1)
// 使用额外数组
public void rotate(int[] nums, int k) {int[] newNums = new int[nums.length];for (int i = 0; i < nums.length; i++) {// 重点: i+k是新数组的位置, %nums.length根据新数组位置取模看在旧数组哪个位置newNums[(i + k) % nums.length] = nums[i];}System.arraycopy(newNums, 0, nums, 0, nums.length);
}
// 数组翻转
public void rotate(int[] nums, int k) {// 重点: 先将所有元素翻转, 这样尾部的 k % n 个元素就被移至头部// 再翻转[0,k%n−1]的元素和[k%n,n−1]的元素就能得到答案reverse(nums, 0, nums.length - 1);reverse(nums, 0, k % nums.length - 1);reverse(nums, k % nums.length, nums.length - 1);
}
public void reverse(int[] nums, int start, int end) {while (start < end) {int temp = nums[start];nums[start] = nums[end];nums[end] = temp;start++;end--;}
}

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

题目讲解:LeetCode
重点:

  1. 左右乘积列表:提前计算好每个元素左侧和右侧所有数字的乘积。
  2. 动态构造R数组:先把输出数组当作 L 数组来计算,然后再动态构造 R 数组得到结果。

思路:

  • 左右乘积列表
  1. 两个数组分别存储每个元素左侧和右侧所有数字的乘积。然后遍历数组,左右相乘就可以得到每个位置的答案。
  • 动态构造R数组
  1. 先把输出数组当作 L 数组来计算,然后再动态构造 R 数组得到结果。

复杂度:

  • N 是数组长度
  • 左右乘积列表
    时间复杂度:O(N)
    空间复杂度:O(N)
  • 动态构造R数组
    时间复杂度:O(N)
    空间复杂度:O(1)
// 左右乘积列表
public int[] productExceptSelf(int[] nums) {int[] result = new int[nums.length];int[] L = new int[nums.length];// 重点: 存储每个元素左侧所有数字的乘积L[0] = 1;for (int i = 1; i < nums.length; i++) {L[i] = L[i - 1] * nums[i - 1];}int[] R = new int[nums.length];// 重点: 存储每个元素右侧所有数字的乘积R[nums.length - 1] = 1;for (int i = nums.length - 2; i >= 0; i--) {R[i] = R[i + 1] * nums[i + 1];}for (int i = 0; i < nums.length; i++) {result[i] = L[i] * R[i];}return result;
}
// 动态构造R数组
public int[] productExceptSelf(int[] nums) {int[] result = new int[nums.length];// 重点: 先把输出数组当作 L 数组来计算result[0] = 1;for (int i = 1; i < nums.length; i++) {result[i] = result[i - 1] * nums[i - 1];}// 重点: 然后再动态构造 R 数组得到结果int curR = nums[nums.length - 1];for (int i = nums.length - 2; i >= 0; i--) {result[i] = result[i] * curR;curR *= nums[i];}return result;
}

41. 缺失的第一个正数

题目讲解:LeetCode
重点:

  1. 对于一个长度为 N 的数组, 其中没有出现的最小正整数只能是[1,N+1]

思路:

  • 负号+下标哈希法
    1.把不在[1,N]范围内的数修改成N+1,这样削减所有废数。
    2.再把小于等于N的元素当作下标,把对应位置(1就是索引0)改为负数。
    3.这时还是正数的元素对应的下标加一就是缺失的最小正数,说明这个下标从来没当作元素出现过。
  • 置换法
    1.每次遍历都把该位置上的元素放到它对应的位置上,这样再遍历的时候,如果某个元素不是下标加一说明我们缺失这个正数。

复杂度:

  • N 是数组的长度
  • 负号+下标哈希法
    时间复杂度:O(N)
    空间复杂度:O(1)
  • 置换法
    时间复杂度:O(N)
    空间复杂度:O(1)
// 负号+下标哈希法
public int firstMissingPositive(int[] nums) {// 重点: 把不在[1,N]范围内的数修改成N+1, 这样削减所有废数for (int i = 0; i < nums.length; i++) {if (nums[i] <= 0 || nums[i] >= nums.length + 1) nums[i] = nums.length + 1;}// 重点: 把小于等于N的元素对应的位置(1就是索引0)改为负数for (int i = 0; i < nums.length; i++) {int num = Math.abs(nums[i]);if (num <= nums.length) {nums[num - 1] = -Math.abs(nums[num - 1]);}}// 重点: 这时还是正数的对应下标+1就是缺失的最小正数, 说明这个下标数字从来没出现过for (int i = 0; i < nums.length; i++) {if (nums[i] > 0) return i + 1;}return nums.length + 1;
}
// 置换法
public int firstMissingPositive(int[] nums) {// 重点: 每次遍历都把该位置上的元素放到它对应的位置上for (int i = 0; i < nums.length; i++) {while (nums[i] >= 1 && nums[i] <= nums.length && nums[nums[i] - 1] != nums[i]) {int temp = nums[nums[i] - 1];nums[nums[i] - 1] = nums[i];nums[i] = temp;}}for (int i = 0; i < nums.length; i++) {if (nums[i] != i + 1) return i + 1;}return nums.length + 1;
}

http://www.ppmy.cn/devtools/150869.html

相关文章

funcaptcha手势指向验证码识别

注意&#xff0c;本文只提供学习的思路&#xff0c;严禁违反法律以及破坏信息系统等行为&#xff0c;本文只提供思路 如有侵犯&#xff0c;请联系作者下架 本文滑块识别已同步上线至OCR识别网站&#xff1a; http://yxlocr.nat300.top/ocr/other/21 该验证码会给出某物品所有的…

JAVA多线程学习

文章目录 线程相关概念线程创建继承Thread类Runnable接口多个线程同时操作同一个对象测试&#xff1a;实现callable接口(了解)静态代理lamda表达式 线程状态线程停止线程休眠线程礼让 线程相关概念 线程&#xff1a;是进程的一部分&#xff0c;一个进程之内的线程之间共享进程的…

基于禁忌搜索算法的TSP问题最优路径搜索matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于禁忌搜索算法的TSP问题最优路径搜索&#xff0c;旅行商问题&#xff08;TSP&#xff09;是一个经典的组合优化问题。其起源可以追溯到 19 世纪初&#xff0c;…

CSS3的aria-hidden学习

前言 aria-hidden 属性可用于隐藏非交互内容&#xff0c;使其在无障碍 API 中不可见。即当aria-hidden"true" 添加到一个元素会将该元素及其所有子元素从无障碍树中移除&#xff0c;这可以通过隐藏来改善辅助技术用户的体验&#xff1a; 纯装饰性内容&#xff0c;如…

【初识扫盲】厚尾分布

厚尾分布&#xff08;Fat-tailed distribution&#xff09;是一种概率分布&#xff0c;其尾部比正态分布更“厚”&#xff0c;即尾部的概率密度更大&#xff0c;极端值出现的概率更高。 一、厚尾分布的特征 尾部概率大 在正态分布中&#xff0c;极端值&#xff08;如距离均值很…

动态规划——树形DP

题目清单 acwing285.没有上司的舞会 状态表示 d p [ u ] [ 0 / 1 ] dp[u][0/1] dp[u][0/1] 集合&#xff1a;对于以u节点为根的子树&#xff0c;选择&#xff08;1&#xff09;或不选择&#xff08;0&#xff09;u节点的方案。 属性&#xff1a; m a x max max 状态计算 d p …

Node.js入门html,css,js 30年了nodejs环境 09年出现 15年

Node.js入门 html,css,js 30年了 nodejs环境 09年出现 15年 nodejs为我们解决了2个方面的问题&#xff1a; 【锦上添花】让我们前端工程师拥有了后端开发能力&#xff08;开接口&#xff0c;访问数据库&#xff09; - 大公司BFF&#xff08;50&#xff09;【✔️】前端工程…

深入理解计算机系统阅读笔记-第十二章

第12章 网络编程 12.1 客户端-服务器编程模型 每个网络应用都是基于客户端-服务器模型的。根据这个模型&#xff0c;一个应用时由一个服务器进程和一个或者多个客户端进程组成。服务器管理某种资源&#xff0c;并且通过操作这种资源来为它的客户端提供某种服务。例如&#xf…