首页 > 技术文章 > leetcode数组典型题目小结

njuwxc 2021-03-29 16:52 原文

数组与矩阵

数组与矩阵的基本知识:

1.数组:数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按有序的形式组织起来的一种形式。

首先,数组会利用索引来记录每个元素在数组中的位置,且在大多数编程语言中,索引是从0算起的。我们可以根据数组中的索引,快速访问数组中的元素。事实上,这里的索引其实就是内存地址。

作为线性表的实现方式之一,数组中的元素在内存中是连续存储的,且每个元素占用相同大小的内存。

在具体的编程语言中,数组的实现方式具有一定差别。比如 C++ 和 Java 中,数组中的元素类型必须保持一致,而 Python 中则可以不同。相比之下,Python中的数组(称之为list)具有更多的高级功能

2.在Java中表示矩阵,使用的是二维数组来表示。

Q.283

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

示例:输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明:必须在原数组上操作,不能拷贝额外的数组。 尽量减少操作次数。

算法:在原有数组上操作,设置index=0,从数组第一个元素开始遍历,遇到非0元素就从index=0开始存放到原数组覆盖,index++。直到遍历完所有的非0数,最后将不足原数组长度的部分,填充0元素即可。

Q566

在MATLAB中,有一个非常有用的函数 reshape,它可以将一个矩阵重塑为另一个大小不同的新矩阵,但保留其原始数据。

给出一个由二维数组表示的矩阵,以及两个正整数rc,分别表示想要的重构的矩阵的行数和列数。

重构后的矩阵需要将原始矩阵的所有元素以相同的行遍历顺序填充

如果具有给定参数的reshape操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。//要进行可行性检验

示例 1:

输入: nums = [[1,2], [3,4]] r = 1, c = 4 输出: [[1,2,3,4]] 解释: 行遍历nums的结果是 [1,2,3,4]。新的矩阵是1*4矩阵, 用之前的元素值一行一行填充新矩阵。

算法思想:首先要是实现重构,必须满足一个前提就是原有矩阵的mn=rc。注意重构的矩阵是将原有的矩阵按照行进行顺序输入到新矩阵。设置一个参数index=0,然后每次导入就+1,新矩阵的行列号为index/n,index%n

Q485

给定一个二进制数组, 计算其中最大连续 1 的个数。

输入:[1,1,0,1,1,1] 输出:3 解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.

算法:数组中可能存在多个连续的1,故所需设置一个count来进行每一次的计数,并设置一个maxCount来表示最大值。

每一次遇到1后就count++,遇到0就利用数学类Math.max()比较当前count和maxCount值,并更新maxCount。

最后结束循环,再比较一次count和maxCount,因为最后一次的count可能更大。

Q240

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:

每行的元素从左到右升序排列。 每列的元素从上到下升序排列。

如果直接简单遍历,时间复杂度是O(n^2)。考虑到矩阵本身是有序的。从最小行和最大列的交点或者最大行和最小列的交点开始搜索。

可以大大减小运算量。index1和index2分别表示行和列。若此时的值小于target,index1++,若此时的值大于target,index2--,直到相等时候输出。

Q378

给你一个 n x n 矩阵 matrix ,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素。 请注意,它是排序后 的第 k 小元素,而不是第 k 个不同的元素。

算法思想:1.直接暴力遍历然后排序求出第K小的元素。

2.二分查找。因为矩阵是有序的,最大和最小元素分别是右下角和左上角元素。以此为上下界left和right。二分查找后,比mid小的元素总在其左上部分,可以判断这个数目的多少,然后不断缩小范围查找即可。运算量小很多。

3.利用priorityqueue构造最大堆实现

PriorityQueue

优先级队列:数据组织不同于普通的队列。普通队列的数据组织是按照先进先出的原则组织的,而优先级队列的数据进入队列是按照关键字有序的顺序,插入关键字的时候会自动按照关键字顺序插入。PriorityQueue是基于优先堆的一个无界队列,这个优先队列中的元素可以默认自然排序或者通过提供的Comparator(比较器)在队列实例化的时排序。要求使用Java Comparable和Comparator接口给对象排序,并且在排序时会按照优先级处理其中的元素。底层数据结构是二叉堆。

详细介绍见:https://blog.csdn.net/u010623927/article/details/87179364

Q645

Hashmap

哈希表

见IDEA

https://blog.csdn.net/woshimaxiao1/article/details/83661464

Map.Entry<Integer,int[]> entry =map.entrySet();//新建entry存储键值对

Q287

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。

假设 nums 只有 一个重复的整数 ,找出 这个重复的数 。

示例 1:

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

输入:nums = [3,1,3,4,2] 输出:3

算法:1.用哈希表统计每一个数出现的频次,然后判断重复与否。

2.使用二分法,left=1,right=length-1,mid=(left+right)/2,用count统计数组中小于等于mid数的个数。count>mid时,说明重复数在[left,mid],更新right=mid。否则说明重复数在(mid,right],更新left=mid+1;直到right=left得到最后的值。

Q667

给定两个整数 n 和 k,你需要实现一个数组,这个数组包含从 1 到 n 的 n 个不同整数,同时满足以下条件:

① 如果这个数组是 [a1, a2, a3, ... , an] ,那么数组 [|a1 - a2|, |a2 - a3|, |a3 - a4|, ... , |an-1 - an|] 中应该有且仅有 k 个不同整数;.

② 如果存在多种答案,你只需实现并返回其中任意一种.

输入: n = 3, k = 1 输出: [1, 2, 3] 解释: [1, 2, 3] 包含 3 个范围在 1-3 的不同整数, 并且 [1, 1] 中有且仅有 1 个不同整数 : 1

算法:原数组有n个整数,以此构造的数组有K个差值。满足这个条件的一种构造是{1,K+1,2,K,3,K-1...}设置interval差值变量,每次改变即可,奇数位等于前一项+interval,偶数位等于前一项-interval。

详细见IDEA的内容Q667

Q697

给定一个非空且只包含非负数的整数数组 nums,数组的度的定义是指数组里任一元素出现频数的最大值。

你的任务是在 nums 中找到与 nums 拥有相同大小的度的最短连续子数组,返回其长度

示例 1:输入:[1, 2, 2, 3, 1] 输出:2解释: 输入数组的度是2,因为元素1和2的出现频数最大,均为2. 连续子数组里面拥有相同度的有如下所示: [1, 2, 2, 3, 1], [1, 2, 2, 3], [2, 2, 3, 1], [1, 2, 2], [2, 2, 3], [2, 2] 最短连续子数组[2, 2]的长度为2,所以返回2.

算法:使用哈希表。

Q766

给你一个mxn的矩阵 matrix 。如果这个矩阵是托普利茨矩阵,返回 true ;否则,返回 false 。

如果矩阵上每一条由左上到右下的对角线上的元素都相同,那么这个矩阵是托普利茨矩阵 。

算法:检查每一个矩阵元素是否和左上的元素相同,一旦有不同即不是这种矩阵,全部遍历后满足就是这托普利茨矩阵。

Q565

索引从0开始长度为N的数组A,包含0到N - 1的所有整数。找到最大的集合S并返回其大小,其中 S[i] = {A[i], A[A[i]], A[A[A[i]]], ... }且遵守以下的规则。

假设选择索引为i的元素A[i]为S的第一个元素,S的下一个元素应该是A[A[i]],之后是A[A[A[i]]]... 以此类推,不断添加直到S出现重复的元素。

输入: A = [5,4,0,3,1,6,2] 输出: 4 解释: A[0] = 5, A[1] = 4, A[2] = 0, A[3] = 3, A[4] = 1, A[5] = 6, A[6] = 2.

其中一种最长的 S[K]: S[0] = {A[0], A[5], A[6], A[2]} = {5, 6, 2, 0}

算法:容易想到的是直接暴力求解,从一个数出发,遍历然后输出最长的集合。

但这样的算法复杂度很高,考虑到每一次从一个数出发,得到的是一个闭环的循环。所以考虑引入一个标记数组,表示已经访问过的数,这样可以大大减少运算量。

Q769

数组arr是[0, 1, ..., arr.length - 1]的一种排列,我们将这个数组分割成几个“块”,并将这些块分别进行排序。之后再连接起来,使得连接的结果和按升序排序后的原数组相同。

我们最多能将数组分成多少块?

示例 1:

输入: arr = [4,3,2,1,0] 输出: 1 解释: 将数组分成2块或者更多块,都无法得到所需的结果。 例如,分成 [4, 3], [2, 1, 0] 的结果是 [3, 4, 0, 1, 2],这不是有序的数组。

算法:1.满足要求的数组必须是前k+1个数最大值为k。以此即可解决。使用copyofrange获得子数组,注意函数第三个不包含上界,然后对子数组进行排序,判断最大值是不是k,若是,count++,否则不管。最终即可得到结果。

2.为了少使用其他类的方法,可以设置一个max值表示前i-1数组的最大值,然后每次和新的arr[i]比较更新。如果max==i,就++。

 

推荐阅读