leetCode-hot100-数组专题之求和+数学定理+其他

数组专题之求和+数学定理+其他

    • 求和
      • 1.两数之和
      • 15.三数之和
    • 数学定理
      • 169.多数元素
    • 其他
      • 4.寻找两个正序数组的中位数
      • 128.最长连续序列

求和

数组求和问题,即计算数组中所有元素的总和,是编程中常见的任务。以下是一些常用的解决方法:
1. 循环遍历

  • 基本思路: 通过循环遍历数组中的每个元素,并将它们累加起来。
  • 实现方式:
    * for 循环: 遍历数组索引,访问并累加每个元素。
    * while 循环: 通过索引或指针遍历数组,访问并累加每个元素。
    * foreach 循环: 遍历数组元素,直接访问并累加每个元素 (适用于 PHP 等语言)。

2. 递归

  • 基本思路: 将数组分为两部分,递归计算每一部分的总和,然后将它们相加。
  • 实现方式: 定义一个递归函数,输入数组及其起始和结束索引,递归计算左右两部分的总和,并返回它们的和。

3. 高级方法

  • 数学公式: 利用数学公式,例如高斯求和公式,直接计算数组中所有元素的总和。
  • 并行计算: 利用多线程或分布式计算,将数组分割成多个部分,并行计算每个部分的总和,最后将它们相加。

4. 哈希表
(1)快速查找和去重:

  • 去重: 通过哈希表,我们可以快速判断一个元素是否已经存在于数组中,从而避免重复计数,这在计算不重复元素的总和时很有用。

  • 快速查找:在某些情况下,我们需要先查找数组中是否存在特定的元素,然后再决定是否将其加入总和。哈希表可以提供快速查找的功能,从而优化整个求和过程。

(2)优化排序数组求和:

  • 前缀和:如果数组是排序的,我们可以利用哈希表来快速计算任意区间内元素的总和。具体方法是将每个元素及其索引存储在哈希表中,然后利用二分查找快速定位到区间起始位置,并计算区间内元素的总和。

(3)复杂求和:

  • 加权求和: 如果数组元素具有不同的权重,我们可以将元素和权重作为键值对存储在哈希表中,然后根据权重计算加权总和。

1.两数之和

思路1:暴力枚举法
暴力枚举法很简单,遍历nums数组的每一个元素,找到和target-nums[i]相同的元素即可。
时间复杂度:需要使用到两层for循环,所以时间复杂度为O(n^2)
代码实现

class Solution {public int[] twoSum(int[] nums, int target) {for(int i=0;i<nums.length;i++){for(int j=i+1;j<nums.length;j++){if(nums[j]==target-nums[i]){return new int[] {i,j};}   } }return null;}
}

思路2:哈希表法
使用哈希表来解决该问题的思路是,创建一个哈希表来存放数据,其中keytarget-nums[i]value为对应的索引。在遍历数组时,将数组中元素的值和对应的索引记录到哈希表中,检查当前元素的补数(target-nums[i])是否在哈希表中,如果在,其value即为所求,若不在,将元素记录到哈希表中并接着遍历数组。
时间复杂度:只需要遍历一次数组,用到一个for循环,所以时间复杂度为O(n)
代码实现

class Solution {public int[] twoSum(int[] nums, int target) {Map<Integer,Integer> tab = new HashMap<>();for(int i=0;i<nums.length;i++){int tar = target-nums[i];if(tab.containsKey(tar)){return new int[] {i,tab.get(tar)};}else{tab.put(nums[i],i);}}return null;}
}

15.三数之和

思路
本题采用枚举+双指针的做法,外循环对nums的元素依次遍历,在遍历时寻找可以和外循环元素相加为0的元素对,内层循环采用首尾双指针进行遍历,但是这样做的前提是需要首先对数组进行排序,最后需要注意由于不能输出重复的结果,所以每次遍历时都要跳过相同元素。详细的讲解参考视频讲解-三数之和。
时间复杂度
这段代码的时间复杂度为O(n^2),其中n为数组nums的长度。主要的时间复杂度来源于两层循环,外层循环遍历数组nums,内层循环使用双指针法遍历数组中的剩余元素。在最坏情况下,内层循环的时间复杂度为O(n),所以总的时间复杂度为O(n^2)
代码实现

class Solution {public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> ans = new ArrayList<>();//对数组进行排序,方便采用首尾指针进行遍历Arrays.sort(nums);for(int i=0;i<nums.length;i++){//跳过重复元素if(i > 0 && nums[i] == nums[i-1]) continue;int l = i + 1;int r = nums.length - 1;int target = 0 - nums[i];while(l < r){if(nums[l] + nums[r] == target){ans.add(Arrays.asList(nums[i],nums[l],nums[r]));//跳过重复元素while(l < r && nums[l] == nums[ l + 1]) l++;while(l < r && nums[r] == nums[r - 1]) r--;l++;r--;}else if(nums[l] + nums[r] < target){l++;}else{r--;}}}return ans;}
}

知识拓展Java中动态数组的使用(ArrayListList
区别
1.ListArrayList的泛型等效类,List是一个接口,而ArrayList是一个类,它实现了List接口,所以List不能被构造,List list=new List()这种写法是错误的,而ArrayList就可以被构造。List list = new ArrayList();这句创建了一个ArrayList的对象后把向上转型成了List。此时它是一个List对象了,有些ArrayList有但是List没有的属性和方法,它就不能再用了。而ArrayList list=new ArrayList();创建一对象则保留了ArrayList的所有属性。
2.List相比ArrayList来说更加安全,因为ArrayList加入的数据为object类型,需要装箱和拆箱操作。List声明时就决定了类型,所以是类型安全的,省掉了装箱与拆箱的过程,并且效率更高。
用法
1.定义
ArrayList

ArrayList list1 = new ArrayList();

List

List<List<Integer>> list2 = new ArrayList<>();

2.添加元素
ArrayList
(1)添加单个元素

list1.Add(1);

(2)添加多个元素

list1.addAll(Arrays.asList(a,b,c));

List:
(1)添加单个元素

list2.Add(1);

(2)添加多个元素

list2.add(Arrays.asList(a,b,c));

数学定理

169.多数元素

思路1:
使用哈希表来解决,在哈希表中记录每个数组元素出现的次数,以数组元素为key,出现次数为value,遍历数组,如果nums[i]的出现次数大于n/2,则返回该元素,否则,更新该元素在哈希表中的value值。
时间复杂度:
时间复杂度取决于两个主要因素:循环遍历不同元素的次数和在HashMap中添加和访问元素的次数。

  • 在循环遍历数组元素时,需要遍历n个元素,因此时间复杂度为O(n)
  • 在HashMap中添加或访问元素的平均时间复杂度为O(1)。但是在最坏情况下,所有元素都是不同的,因此在HashMap中添加或访问元素的时间复杂度为O(n)
  • 因此,总体时间复杂度为O(n^2)
    需要注意的是,虽然代码中使用了HashMap来记录元素出现的次数,但是在最坏情况下,每次遍历都需要进行线性搜索以查找元素是否已经在HashMap中。这会导致时间复杂度较高。
    代码实现:
class Solution {public int majorityElement(int[] nums) {Map<Integer,Integer> record = new HashMap<>();int n = nums.length;int cpm = n / 2;for(int i = 0;i <n;i++){int count = record.getOrDefault(nums[i],0) + 1;if(count > cpm){return nums[i];}else{record.put(nums[i],count);}}return -1; }
}

思路2:
Boyer-Moore 投票算法:每次都找出一对不同的元素,从数组中删除,直到数组为空或只有一种元素。如果存在元素 e 出现频率超过半数,那么数组中最后剩下的就只有 e。简单来说,就是数组元素之间相互抵消,遇到相同的就加1,不同的就减1,当count‘为0的时候就需要更新比较的元素值,说明上一个元素已经被抵消完了,需要换一个出现次数更多的元素,最后剩下来的元素一定是那个多数元素,视频讲解点击视频讲解-多数元素。
时间复杂度:
时间复杂度为O(n),其中n是数组nums的长度。
代码实现:

class Solution {public int majorityElement(int[] nums) {int ans = -1;int count = 0;for(int i = 0; i < nums.length;i++){if(count == 0){ans = nums[i];count++;}else if(nums[i] == ans){count++;}else{count--;}}return ans;}
}

其他

4.寻找两个正序数组的中位数

思路
该题的解决采用二分思想,只需要给出两个有序数组一个恰当的【分割线】,中位数的值就由位于这个【分割线】的两侧的数来决定,确定分割线的位置使用二分查找法,需要注意的点是:分割线左边的所有元素的数值<分割线右边所有元素的数值
注:这里的思路写的比较简单,详细的可以看这个视频详细思路-寻找两个正序数组的中位数
时间复杂度
时间复杂度为O(log min(m,n)),m,n分别为两数组的长度,空间复杂度为O(1)
代码实现:

class Solution {public double findMedianSortedArrays(int[] nums1, int[] nums2) {//将nums1设置为长度较小的数组,方便代码的编写if(nums1.length>nums2.length){int[] temp = nums1;nums1 = nums2;nums2 = temp;}int m = nums1.length;int n = nums2.length;//计算分割线左边元素的数量int totalleft = (m+n+1)/2;//二分法查找nums1部分的分割线int left = 0;int right = m;while(left<right){//这是对于(left+right)/2的特殊处理方式,防止发生整型溢出//同时使用二分法时,如果出现left=i,则这里需要+1,否则不需要int i = left+(right-left+1)/2;int j = totalleft - i;if(nums1[i-1] > nums2[j]){right = i - 1;}else{left = i;}}int i = left;int j = totalleft - i;//最后得到两个数组分割线左右两边元素的最大值的最小值//为了防止出现分割线左右两边没有元素的极端情况加上判断int nums1LeftMax = i ==0 ? Integer.MIN_VALUE : nums1[i-1];int nums1RightMin = i ==m ? Integer.MAX_VALUE : nums1[i];int nums2LeftMax = j == 0 ? Integer.MIN_VALUE : nums2[j-1];int nums2RightMin = j == n ? Integer.MAX_VALUE : nums2[j];//计算中位数的值if(((m+n) % 2) == 1){return Math.max(nums1LeftMax,nums2LeftMax);}else{return (double) ((Math.max(nums1LeftMax,nums2LeftMax) + Math.min(nums1RightMin,nums2RightMin))) / 2;}}
}

128.最长连续序列

思路:
本题使用Set求解,将数组中的元素用Set存储,去掉重复元素。我们可以Set中的元素映射到一个数轴上来,可以看到连续的元素会形成一个区间,只要我们找到每个区间的第一个元素,然后通过判断Set中是否包含以该元素开头的连续区间的元素,最后得到区间的长度,然后在所有长度中取最大值即可。
时间复杂度:
时间复杂度为O(n),其中n是数组nums的长度。
代码实现:

class Solution {public int longestConsecutive(int[] nums) {Set<Integer> set = new HashSet<>();int ans = 0;for(int num : nums){set.add(num);}for(int item : set){if(!set.contains(item - 1)){int x = item + 1;while(set.contains(x)) x++;ans = Math.max(ans,x - item);}}return ans;}
}

知识扩展:
HashSet的使用
HashMap同时也被称为集合,该容器中只能存储不重复的对象,常用来去重。
(1)新建一个HashSet

HashSet<String> st = new HashSet<String>();

(2)添加元素

st.add("hello");

(3)删除元素

st.remove("hello");

(4)判断某个元素是否在Set中

st.contains("hello");

(5)清空Set

st.clear();

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

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

相关文章

介绍一下js的节流与防抖

在JavaScript中&#xff0c;节流&#xff08;Throttling&#xff09;和防抖&#xff08;Debouncing&#xff09;是两种常用的优化高频率触发事件的策略。它们主要用于限制函数的执行频率&#xff0c;以避免因频繁触发导致的性能问题。 1. 防抖&#xff08;Debouncing&#xff…

numpy.ndarray是什么类型

numpy.ndarray是什么类型 numpy.ndarray 类型的特点创建 numpy.ndarray示例代码总结 numpy.ndarray是什么类型 numpy.ndarray 是 NumPy 库中的一个核心数据类型&#xff0c;用于表示多维数组。它是 NumPy 中最重要的数据结构之一&#xff0c;提供了高效的数值计算能力。下面是对…

PPP与HDLC的异同

PPP&#xff08;点对点协议&#xff09;与HDLC&#xff08;高级数据链路控制&#xff09;都是数据链路层协议&#xff0c;用于在两点间提供可靠的通信链接&#xff0c;但它们在设计目标、应用场景、功能特性等方面存在一些显著的异同&#xff1a; 相同点&#xff1a; 目的相似…

nn.Embedding使用

nn.Embedding使用 Embedding.weight会从标准正态分布中初始化成大小为&#xff08;num_embeddings, embedding_dim&#xff09;的矩阵 PE矩阵的作用就是替换这个标准正态分布 input中的标号表示从矩阵对应行获取权重来表示单词 # 1.设置embedding结构 max_seq_len 1000 # 句…

配合busco训练Augustus

使用BUSCO的结果来训练Augustus包括以下几个步骤。这些步骤会帮助你利用BUSCO评估的高质量基因来优化Augustus的基因预测模型。 步骤1&#xff1a;运行BUSCO 首先&#xff0c;你需要运行BUSCO来评估你的基因组或转录组。BUSCO会生成一些包含高质量单拷贝直系同源基因的信息文件…

【Java】面向对象的三大特征:封装、继承、多态

封装 什么叫封装&#xff1f; 在我们写代码的时候经常会涉及两种角色&#xff1a; 类的实现者 和 类的调用者。 封装的本质就是让类的调用者不必太多的了解类的实现者是如何实现类的&#xff0c; 只要知道如何使用类就行了&#xff0c;这样就降低了类使用者的学习和使用成本&a…

游戏主播到底是为游戏宣传还是蹭游戏带来的热度

易采游戏网6月1日最新消息&#xff1a;近日知名游戏主播周淑怡在社交平台上发表了自己对《地下城与勇士》手游(简称DNF手游)的点评。作为一款拥有庞大粉丝基础的端游改编作品&#xff0c;DNF手游自发布以来便受到了广泛关注。而周淑怡的点评不仅聚焦于游戏体验本身&#xff0c;…

Python代码:二十七、append函数

1、题目 牛牛有一个name [Niumei, YOLO, Niu Ke Le, Mona] 记录了他最好的朋友们的名字&#xff0c;请创建一个二维列表friends&#xff0c;使用append函数将name添加到friends的第一行。 假如Niumei最喜欢吃pizza&#xff0c;最喜欢数字3&#xff0c;YOLO最喜欢吃fish&…

Linux实验报告(一)——Linux系统安装与简单配置

目录 一、实验名称&#xff1a; 二、仪器、设备&#xff1a; 三、参考资料&#xff1a; 四、实验目的&#xff1a; 五、实验内容&#xff08;步骤&#xff09;&#xff1a; 六、实验数据&#xff08;程序&#xff09;记录&#xff1a; 七、实验结果分析&#xff1a; 八、…

XXE漏洞简介

目录 漏洞原理 漏洞危害 前置知识 XML简介 DTD简介 DTD的两种声明方式 实体 实体分类 内置实体(Built-inentities) 字符实体&#xff08;Characterentities&#xff09; 通用实体&#xff08;Generalentities&#xff09; 参数实体(Parameterentities) XXE漏洞…

嵌入式Linux shell编程实例

1. 输入两个数&#xff0c;实现两个数的相加 &#xff08;1&#xff09;具体实现代码如下 1 #!/bin/bash2 read a3 read b4 sum$(($a$b))5 echo "$sum"&#xff08;2&#xff09;编辑完内容后按Esc键再输入:wq保存&#xff0c;回车退出&#xff0c;执行结果如下图&a…

系统安全及其应用

系统安全及其应用 部署服务器的初始化步骤&#xff1a; 1、配置IP地址&#xff0c;网关&#xff0c;DNS解析 2、安装源&#xff0c;外网&#xff08;在线即可yum&#xff09; 内网&#xff08;只能用源码包编译安装&#xff09; 3、磁盘分区 lvm raid 4、系统权限配置和基础安…

用r语言处理 Excel数据当中的缺失值方法

以下是使用 R 编程语言处理 Excel 缺失数据的一些常见方法示例代码&#xff1a;&#xff08;无需循环&#xff09; 读取包含缺失数据的 Excel 文件 data <- read.csv(“your_file.csv”) 查看数据中是否有缺失值 sum(is.na(data)) 用平均值填充缺失值 data c o l u m …

Django里多app

在 Django 里的某一个项目&#xff0c;里面得包含很多 App (功能)&#xff0c;那么如何在该项目里管理这么多App呢&#xff1f; 先说明下背景&#xff1a;未先创建 apps 文件夹来存各个app文件夹&#xff0c;直接在项目文件目录里创建各个app。为了便于管理&#xff0c;得将各…

WireShark下载安装

下载地址 WireShark站内下载资源&#xff1a;&#xff08;土豪方便下载&#xff09; https://download.csdn.net/download/qq_58662768/89377088 官网下载&#xff1a; Wireshark Go Deep 进入主页后&#xff0c;选择Get Acquainted&#xff0c;再选择Download。 选择合适…

【vue3|第4期】Vue3的选项式与组合式

日期&#xff1a;2024年5月30日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对的地方&#xf…

【IPFS应用开发】基于IPFS的视频播放器

本系列文章是针对 https://blog.csdn.net/weixin_43668031/article/details/83962959 内容的实现所编写的。开发经历包括思考过程、重构和推翻重来。 基于IPFS的视频播放器 想写一个真正的、基于IPFS的&#xff0c;可以播放IPFS上的视频的程序支持多种数据加载格式同时支持单文…

CentOS7某天的samba服务搭建操作记录(还没成功)

#CentOS7 yum软件仓库阿里云 samba服务器配置失败 sensors成功了 (花了200元组装H61测试机&#xff0c;75元的主板只有一块能用&#xff0c;垃圾板但又不完全能用&#xff09; 2024.5月的某天记录如下&#xff1a; https://blog.csdn.net/dszgf5717/article/details/53732182 …

一篇文章讲透数据结构之树

一.树 1.1树的定义 树是一种非线性的数据结构&#xff0c;它是有n个有限结点组成的一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根在上&#xff0c;叶在下的。 在树中有一个特殊的结点&#xff0c;称为根结点&#xff0c;根结点…

Humanoid Whole-body Control

系列文章目录 前言 我们拟举办的研讨会旨在为生物力学和机器人学这两个学科架起一座桥梁&#xff0c;尤其侧重于人体运动分析和仿人机器人的全身控制。将人体运动转化为仿人机器人是一个新兴的跨学科领域。在过去二十年里&#xff0c;传统的双足行走步态生成和基于动态模型优化…