leetcode数组汇总_Leetcode题解(6)- 2018 力扣 Leetcode CN 高频题汇总 part 2 数组

# 数组

# 乘积最大子序列

Leetcode 152题。

# 问题

给定一个整数数组 nums ,找出一个序列中【乘积最大】的【连续】子序列(该序列至少包含一个数)。

# 思路

类似于之前 和最大的子序列(leetcode 53) 中的思路,动态规划的方法,那个题目的答案如下:

在这个题目中,采用类似的方法,也设定一个阶段性的累乘变量,设定一个全局的最大值变量,逐个往后找更新即可。

但需要注意:累乘时会出现负值的情况,也就是说比如之前的累乘积是-100,是最小的,但万一下一个数字是负数,就会发生逆转,乘积就变成最大的了。因此,需要两个阶段性变量,分别记下累乘的最大和最小值。

# 代码

# 旋转数组

Leectode 189

# 问题

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。

示例 :

输入: [1,2,3,4,5,6,7] 和 k = 3

输出: [5,6,7,1,2,3,4]

可以多想几种方案;要使用空间复杂度为1的原地算法

# 思路

1)两层循环,外层k遍,内层每一遍都将所有元素往右挪动1个位置

2)三次翻转;第一次对整个数组进行翻转,然后分别将前k个元素翻转、后面的元素翻转

3)不限制空间的话可以开辟新空间,将前后两部分重新进行拼接;或者可以从后面依次pop出k个元素,依次append到前面;都可以实现旋转

# 代码

按照三次翻转来写。注意:k可能会大于n,我们取k=k%n即可

# 存在重复元素

Leetcode 217

# 问题

给定整数数组,判断是否存在重复元素

# 思路

1)n2的复杂度,暴力两层循环去逐个判断

2)排序,然后扫一遍检查相邻两元素是否有相等的情况

3)转为set,判断set长度与list是否相等

4)从前向后扫,把出现过的元素记下来,每个新元素检查下之前是否出现过

# 代码

python投机取巧法:

# 移动0

leetcode 283

# 问题

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

必须在原数组上操作,不能拷贝额外的数组。

尽量减少操作次数。

# 思路

其实就是把非0元素往前挪,也不需要交换之类的搞那么复杂,挪到最后余下的都填成0即可。

# 代码

# 打乱数组

Leetcode 384

# 问题

打乱一个没有重复元素的数组。

# 思路

感觉是个奇怪的题啊,python可以用random库的shuffle来打散,或者用代码里的方法随机交换来打散。

注意深靠背和浅拷贝。

# 代码

# 两个数组的交集

Leetcode 349题。

# 问题

给定两个数组,编写一个函数来计算它们的交集。

例如,输入: nums1 = [1,2,2,1], nums2 = [2,2]

输出: [2]

输出结果中,每个元素一定是唯一的。

可以不考虑输出结果的顺序。

# 思路

由于这个题中结果要求不出现重复元素,所以可以先分别将两个数组set一下,去重,然后取set的交集。可使用python本身的交集操作符,一行代码搞定;或者遍历一个set同时在另一个中查找,来求交集。

如果不支持set,用最原始的做法的话,可以先遍历一个list,同时在另一个list中查找,如果找得到,并且这个元素未在结果list中出现的话,则将该元素加入到结果list中,完成题目要求。

还有一些方法,也参见下一道题里的描述。

# 代码

补充一下,两个set之间 & 可以求交集,| 求并集, - 求差集

# 两个数组的交集 2

Leetcode 350题。

# 问题

与上一个题的区别在于,这个题要求元素可以多次出现。

比如下面示例,2在两个list中都出现了两次,则输出两个2

输入: nums1 = [1,2,2,1], nums2 = [2,2]

输出: [2,2]

进阶思考: 如果给定的数组已经排好序呢?你将如何优化你的算法?

如果 nums1 的大小比 nums2 小很多,哪种方法更优?

如果 nums2 的元素存储在磁盘上,磁盘内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?

# 思路

1)暴力法:两层for循环,但需要注意本题中允许多次出现,所以内层循环里当某个元素被使用过一次之后,要把它置空一下避免后面再次被计数用到。

2)有序时,两路并进

如果两个数组有序,可以两路并进,类似于merge,详见下面的代码。

3)哈希表

对其中一个数组构建哈希表,遍历另一数组元素时可快速查找是否重复。这是适合上一题的做法,本题中由于允许重复,哈希表中需要记录元素的出现次数,每次查找一个之后把计数减1,减到0了就相当于找不到。

这个做法感觉还是答题时必须得想到的,相比暴力减少了很多次内层的遍历操作。

# 代码

按照上面的方案2 来写

# 递增的三元子序列

Leetcode 334 题。

# 问题

给定一个未排序的数组,判断这个数组中是否存在长度为 3 的递增子序列。

数学表达式如下:

要求算法的时间复杂度为 O(n),空间复杂度为 O(1)

# 思路

需要仔细点读题,ijk并不要求是连续的(如果是连续的,这个题出的未免也太简单了啊喂

思路是从左往右挨个读,记下当前的最小值和第二小的值,并随着读取不断更新。如果遇到比第二小还大的数,说明形成了递增的三元子序列。

# 代码

# 搜索二维矩阵 II

Leetcode 240 题,剑指Offer第一题,详见 剑指Offer(opens new window)

# 除自身以外数组的乘积

Leetcode 238题。

# 问题

给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。

要求:不要使用除法;o(n)时间复杂度

# 思路

不能使用除法,所以最直观的思路——先求总的乘积再除以每个元素——就行不通了(实际上这种想法也不那么简单吧,比如说对0元素的处理就挺麻烦)

我们以每个数为中心,可以将数组分成左右两块,该处的值就是左右两边的乘积再乘起来。所以只需要从左到右累乘一遍,再从右到左累乘一遍就可以。

# 代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值