LeetCode 之算法篇(1)

本篇文章做leetcode top 100的的一些内容总结,以供后面复习使用

文章目录

    • 题目
      • 41. 缺失的第一个正数 (未掌握)
      • 合并区间
      • 轮转数组
      • 238. 除自身以外数组的乘积

题目

41. 缺失的第一个正数 (未掌握)

这道题的关键点在于对桶排序变形,或者说借助桶排序的思想。在桶排序中,我们会将元素放入对应桶中,然后按顺序取出桶中元素。

1、将数组中的每个元素放到正确的位置: 对于每个元素 nums[i],如果它在区间 [1, n] 内,将它放到正确的位置上,即 nums[i] 应该在数组中的索引位置 nums[i]-1 上。这样一来,遍历完数组后,第一个不在正确位置上的元素就是缺失的最小正整数。
2、查找第一个不在正确位置上的元素: 继续遍历数组,找到第一个满足 nums[i] != i + 1 的元素,即 nums[i] 就是缺失的最小正整数。

/*** @param {number[]} nums* @return {number}*/
var firstMissingPositive = function(nums) {const n = nums.length;for (let i = 0; i < n; i++) {while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] !== nums[i]) {// 将 nums[i] 放到正确的位置[nums[nums[i] - 1], nums[i]] = [nums[i], nums[nums[i] - 1]];}}// 查找第一个不在正确位置上的元素for (let i = 0; i < n; i++) {if (nums[i] !== i + 1) {return i + 1;}}// 如果数组中都是正确位置的元素,则缺失的是 n+1return n + 1;
};

如果看完上面这段代码,还是不理解。为什么是这么一段代码,主要有两处代码
1、nums[nums[i] - 1] !== nums[i]
2、[nums[nums[i] - 1], nums[i]] = [nums[i], nums[nums[i] - 1]]

while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] !== nums[i]) {// 将 nums[i] 放到正确的位置[nums[nums[i] - 1], nums[i]] = [nums[i], nums[nums[i] - 1]];
}

首先这段代码作用就是将nums[i]放到正确的位置。

Q:什么是正确的位置?
A:一般来说,数组的索引是从 0 开始的。所以,如果元素 nums[i] 是最小正整数 1,那么它应该放置在数组的索引位置 0 上;如果 nums[i] 是最小正整数 2,那么它应该放置在数组的索引位置 1 上,以此类推。那么 nums[i] 的正确位置就是 nums[i] - 1(比如nums[2]的位置在1上面,nums[2] - 1 = 1)

条件 nums[nums[i] - 1] !== nums[i] 的意思是:当前元素 nums[i] 不在正确的位置上。

具体来说,nums[i] - 1 表示 nums[i] 在数组中正确的位置,因为数组索引是从 0 开始的,而我们希望最小正整数从 1 开始。所以,如果 nums[i] 已经在正确的位置上,那么 nums[i] 应该等于 nums[nums[i] - 1]。

如果 nums[i] 不在正确的位置上,即 nums[i] - 1 处的值不等于 nums[i],就需要进行位置交换。这样一来,通过循环的一系列位置交换,每个元素最终都会被放到它正确的位置上。

这个条件的目的是避免不必要的交换操作,提高算法效率。因为如果元素已经在正确的位置上,就不需要进行交换了,直接继续遍历下一个元素。

OK,那么位置交换代码就是 [nums[nums[i] - 1], nums[i]] = [nums[i], nums[nums[i] - 1]];

将当前元素 nums[i] 放到它在数组中正确的位置上,即 nums[i] - 1 处。这样的操作保证了数组的结构类似于桶排序,每个元素都在正确的位置上。

这种位置交换的思路是为了满足题目中对于最小正整数的要求,同时在 O(n) 时间复杂度和常数级别额外空间的条件下完成。通过这样的交换操作,最终的数组结构使得第一个不在正确位置上的元素就是缺失的最小正整数。


合并区间

解题思路:先排序后遍历
1、首先,按照区间的起始位置对所有区间进行排序。
2、接着,遍历排序后的区间,依次合并重叠的区间。具体做法是比较当前区间的起始位置和上一个合并后区间的结束位置,如果发现有重叠,则合并;否则,将当前区间加入结果集。
3、最终得到的结果集即为合并后的不重叠区间数组。

/*** @param {number[][]} intervals* @return {number[][]}*/
var merge = function(intervals) {if (!intervals || intervals.length === 0) {return [];}// 按照区间的起始位置进行排序intervals.sort((a, b) => a[0] - b[0]);const merged = [intervals[0]];for (let i = 1; i < intervals.length; i++) {const currentInterval = intervals[i];const lastMerged = merged[merged.length - 1];// 如果有重叠,则合并区间if (currentInterval[0] <= lastMerged[1]) {lastMerged[1] = Math.max(lastMerged[1], currentInterval[1]);} else {// 否则,将当前区间加入结果集merged.push(currentInterval);}}return merged;
};

轮转数组

/*** @param {number[]} nums* @param {number} k* @return {void} Do not return anything, modify nums in-place instead.*/
function rotate(nums, k) {const n = nums.length;k %= n;  // 处理 k 大于数组长度的情况// 整体反转reverse(nums, 0, n - 1);// 前 k 个元素反转reverse(nums, 0, k - 1);// 后 n-k 个元素反转reverse(nums, k, n - 1);
}// 反转数组的指定区间
function reverse(nums, start, end) {while (start < end) {const temp = nums[start];nums[start] = nums[end];nums[end] = temp;start++;end--;}
}

将数组元素向右轮转 k 个位置的思路是通过反转数组的不同部分来实现的。这种思路的来源可以追溯到翻转字符串的问题,其中我们也会使用类似的方法。

反转数组的思路:

1、整体反转: 先将整个数组进行反转,这样原来数组的末尾元素就变成了开头。
2、部分反转: 接着,对前 k 个元素进行反转,这样原来数组的开头 k 个元素就变成了末尾。
3、再次部分反转: 最后,对剩余的 n-k 个元素进行反转,将它们恢复到正确的顺序。
这样整个过程就相当于是将数组的元素向右轮转了 k 个位置。

为什么是执行三次反转呢?

在这里,执行三次反转是为了保持反转的方向,确保数组的元素正确地向右轮转 k 个位置。具体来说:

1、整体反转是为了将原数组的末尾元素移动到数组的开头。
2、第一次部分反转是为了将这些位于开头的元素移动到正确的末尾位置。
3、第二次部分反转是为了将原来的开头元素恢复到数组的正确位置。

这种思路的直观性在于,通过反转数组的不同部分,可以有效地实现循环移动的效果。这种方法在处理数组旋转等问题时非常常见。


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

这道题目考察的是数组的乘积累积。解决这类问题的一种常见思路是使用前缀乘积和后缀乘积。

解题思路:
1、计算前缀乘积: 从左到右遍历一次数组,计算每个元素左侧所有元素的乘积。即 prefixProduct[i] 表示 nums[0]nums[1]…*nums[i-1]。
2、计算后缀乘积: 从右到左遍历一次数组,计算每个元素右侧所有元素的乘积。即 suffixProduct[i] 表示 nums[i+1]nums[i+2]…*nums[n-1]。
3、计算结果数组: 对于每个位置 i,结果数组中的元素就是 prefixProduct[i] * suffixProduct[i]。
下面是使用这种思路的示例代码:

/*** @param {number[]} nums* @return {number[]}*/
var productExceptSelf = function(nums) {const n = nums.length;// 计算前缀乘积const prefixProduct = new Array(n).fill(1);let product = 1;for (let i = 1; i < n; i++) {product *= nums[i - 1];prefixProduct[i] = product;}// 计算后缀乘积并同时计算结果数组let suffixProduct = 1;for (let i = n - 1; i >= 0; i--) {prefixProduct[i] *= suffixProduct;suffixProduct *= nums[i];}return prefixProduct;
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/582402.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Leetcod面试经典150题刷题记录 —— 区间篇

Leetcod面试经典150题刷题记录 —— 区间篇 1. 汇总区间2. 合并区间3. 插入区间4. 用最少数量的箭引爆气球 1. 汇总区间 题目链接&#xff1a;汇总区间 - leetcode 题目描述&#xff1a; 给定一个 无重复元素 的 有序 整数数组 nums 。返回 恰好覆盖数组中所有数字 的 最小有序…

算法导论复习纲要

函数 1. 上界下界&#xff0c;紧确界的定义 2. 求解递推式&#xff0c;代入法&#xff0c;递归树法&#xff0c;主方法 分治算法 动态规划 1. 切割钢条&#xff1a;递归方法&#xff0c;动态的自上而下&#xff0c; 2. 矩阵乘法&#xff1a;最优子结构性的证明&#xff0c…

Go语言学习

1、运行和解析 go run 命令已包含了编译和运行。它会先在一个临时目录编译程序&#xff0c;然后执行完后清理掉. 如果在run的后面加上 --work参数来查看临时目录。 go run --work main.go也可以通过go build命令来编译代码&#xff0c;执行后会生成一个可以执行文件&#xff…

HIVE笔记

表关联 内连接&#xff08;INNER JOIN&#xff09; 返回两个表中满足关联条件的记录。 SELECT * FROM t1 INNER JOIN t2 ON t1.col1 t2.col2;左连接&#xff08;LEFT JOIN&#xff09; 返回左表中的所有记录&#xff0c;以及右表中满足关联条件的记录。 SELECT * FRO…

如何本地部署Nextcloud结合cpolar搭建专属私有云盘远程访问(内网穿透)

文章目录 摘要1. 环境搭建2. 测试局域网访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问 4 配置固定http公网地址4.1 保留一个二级子域名4.1 配置固定二级子域名4.3 测试访问公网固定二级子域名 摘要 Nextcloud,它是ownCloud的一个分支,是一个文件共享服…

如何用matlab制作游戏?

在MATLAB中制作游戏可以采用图形用户界面&#xff08;GUI&#xff09;或使用MATLAB的绘图和交互功能。以下是一些制作游戏的基本步骤&#xff1a; 使用 MATLAB GUI 制作游戏 打开 GUIDE&#xff08;GUI 开发环境&#xff09; 打开 MATLAB 并在命令行中输入 guide 打开 GUIDE。…

使用Rollup 搭建开发环境

1 什么是Rollup Rollup 是一个用于 JavaScript 的模块打包工具&#xff0c;它将小的代码片段编译成更大、更复杂的代码&#xff0c;例如库或应用程序。它使用 JavaScript 的 ES6 版本中包含的新标准化代码模块格式&#xff0c;而不是以前的 CommonJS 和 AMD 等特殊解决方案。(开…

算法设计与分析 | 矩阵连乘

题目描述 一个n*m矩阵由n行m列共n*m个数排列而成。两个矩阵A和B可以相乘当且仅当A的列数等于B的行数。一个N*M的矩阵乘以一个M*P的矩阵等于一个N*P的矩阵&#xff0c;运算量为nmp。 矩阵乘法满足结合律&#xff0c;A*B*C可以表示成(A*B)*C或者是A*(B*C)&#xff0c;两者的运算…

linux安装maven3.8.8官网下载安装

步骤 1&#xff1a;下载 Maven 安装包 打开浏览器&#xff0c;访问 Maven 官方网站&#xff1a;https://maven.apache.org/download.cgi在页面上找到最新的稳定版本的 Maven&#xff0c;复制下载链接。 步骤 2&#xff1a;使用终端下载 Maven 安装包 打开终端&#xff0c;使…

什么是https证书?

HTTPS证书&#xff0c;也称为SSL&#xff08;Secure Sockets Layer&#xff09;证书或TLS&#xff08;Transport Layer Security&#xff09;证书&#xff0c;是一种数字证书&#xff0c;用于在网络上建立安全的加密连接。它的主要目的是确保在互联网上进行的数据传输的安全性和…

Linux空间不足处理

目录 临时处理 杀死没在使用的后台进程&#xff08;某些进程可能会占用几十个G的空间&#xff09; 手动释放空间 清理/tmp/ray目录 永久处理 将文件挪至空间充足的挂载盘 将软件挪至空间充足的挂载盘&#xff0c;在原目录创建软链接 临时处理 杀死没在使用的后台进程&a…

Android : 画布绘制矩形和文字 让其居中显示简单应用

示例图&#xff1a; CenterView.java package com.example.demo;import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.Log; import android.view.View;public class Center…

Android 12 Token 机制

一、前言 在 android framework 框架中 activity 和 window 是相互关联的&#xff0c;而他们的管理者 AMS 和 WMS 是怎么来实现这种关联关系的&#xff0c;答案就是通过 token。 首先大家需要了解一下 LayoutParams&#xff0c;当然属性很多&#xff0c;简单了解即可&#xf…

深入理解ArkTS:Harmony OS 应用开发语言 TypeScript 的基础语法和关键特性

文章目录 前言TypeScript语法变量声明条件控制循环迭代函数类和接口模块开发文章总结要点总结前言 Harmony OS应用开发的主力语言ArkTS的前身TS语言的基本语法。通过学习变量的声明和数据类型、条件控制、函数声明、循环迭代等基本知识,并了解内核接口的声明和使用。同时还介…

openGauss学习笔记-175 openGauss 数据库运维-备份与恢复-导入数据-管理并发写入操作示例

文章目录 openGauss学习笔记-175 openGauss 数据库运维-备份与恢复-导入数据-管理并发写入操作示例175.1 相同表的INSERT和DELETE并发175.2 相同表的并发INSERT175.3 相同表的并发UPDATE175.4 数据导入和查询的并发 openGauss学习笔记-175 openGauss 数据库运维-备份与恢复-导入…

redis开启密码验证

开启密码验证 &#xff08;1&#xff09;配置文件中设置 redis.conf文件里面配置requirepass参数&#xff0c;redis认证密码&#xff1a;foobared&#xff0c;然后重启redis服务 ./redis-cli 127.0.0.1:6379> 127.0.0.1:6379> 127.0.0.1:6379> CONFIG SET requi…

训练和测试的loss、accuracy等数据保存到文件并读出

首先是写文件到excel import os.path from openpyxl import load_workbook import pandas as pd import matplotlib.pyplot as pltdef write_excel(excel_name, sheet_name, value):columns ["epoc", "train_loss", "train_acc", "test_a…

跟着野火学FreeRTOS:第一段(任务延时列表)

既然是延时列表&#xff0c;那肯定要先定义相应的链表&#xff0c;延时列表的定义如下。这里定义了两条延时列表&#xff08;其实就是前面小节里面提到的链表的根节点&#xff09;&#xff0c;一条是准备当记录 S y s t i c k Systick Systick周期个数的变量 x T i c k C o u n…

idea Spring Boot项目使用JPA创建与数据库链接

1.pom.xml文件中添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>…

创建和配置Spring MVC框架构建Web应用

1 认识Spring MVC Spring Web MVC是构建在Servlet API之上的Web框架&#xff0c;自诞生之时就被纳入了Spring框架中。其正式/官方名称为“Spring Web MVC”&#xff0c;源自其所属的模块&#xff08;spring-webmvc&#xff09;&#xff0c;但通常被称为“Spring MVC”。 1.1…