这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战
数组相关的算法题目是比较高频的,通过本文希望能够对你数组相关的算法能力有所帮助。
找出给定数组中的最大和最小元素
问题描述:
给你一个数字数组。你需要在数组中找到最小和最大的数。
思路:
- 定义两个变量max,min,用来存放最大和最小元素
- 遍历数组
- 如果当前元素大于max,则将当前元素赋值给max
- 如果当前元素小于min,则将当前元素赋值给min
- 最后max和min则是最大和最小的元素
代码实现:
1 | java复制代码public class FindLargestSmallestNumberMain { |
查找数组中缺少的数字
问题描述:
给定一个包含1到n的整数递增数组,但数组中从1到n的一个数字缺失了。你需要提供一个最佳的解决方案来找到丢失的数字。数字不会在数组中重复。
例如:
1 | java复制代码int[] arr1={7,5,6,1,4,2}; |
思路:
- 因为数组中元素是递增的,所以可以使用公式
n=n*(n+1)/2
求n个数的和 - 计算出给定数组中元素的和
- 使用n个数的和减去数组中元素的和结果便是缺少的数字
代码实现:
1 | java复制代码public class MissingNumberMain { |
从旋转的有序数组中查找元素
问题描述:
给定一个排序和旋转的数组,如下所示:
1 | java复制代码int arr[]={16,19,21,25,3,5,8,10}; |
该数组是从一个有序数组arr[]={3,5,8,10,16,19,21,25}
旋转后所得。
要求在在O(log n)
时间复杂度的数组中搜索到一个指定元素。
思路:
- 如果直接遍历数组,则时间复杂度为
O(n)
,不符合题目要求; - 因为数组是由有序数组旋转所得,所以在某个下标的之前和之后是有序的;
- 然后按照二分法查找。
算法逻辑:
- 计算出中位下标mid=(low+high)/2;
- 如果arr[mid]等于要查找的数字则返回;
- 如果[low…mid]是有序的;
- 如果要查找的数字在[low…mid],则high=mid-1;
- 如果要查找的数字不在[low…mid],则low=mid+1;
- 如果[mid…high]是有序的;
- 如果要查找的数字在[mid…high],则low=mid+1;
- 如果要查找的数字不在[mid…high],则high=mid-1;
代码实现:
1 | java复制代码public class SearchElementSortedAndRotatedArrayMain { |
找到有序旋转数组中的最小元素
问题描述:
有序旋转数组定义同上一题,例如:
1 | java复制代码int arr[]={16,19,21,25,3,5,8,10}; |
同样要求时间复杂度为O(log n)
。
思路:
与上题类似,因数组可以拆分为前后两个有序数组,可以通过二分查找法的变体来完成;
- 计算出中位下标mid=(low+high)/2;
- 如果[mid…high]是有序的;
- 最小值在右边,high=mid;
- 否则最小值在左边,low= mid+1;
代码实现:
1 | java复制代码public class MinimumElementSortedAndRotatedArrayMain { |
查找数组中第二大的与元素
问题描述:
给定一个旋转有序数组,如下所示:
1 | java复制代码int[] arr1={7,5,6,1,4,2}; |
找出第二大的元素:6
思路:
可以对数组排序,然后返回数组中的倒数第二个元素,时间复杂度为O(nlogn)
。
- 定义最大值highest 和第二大值变量secondHighest
- 对数组进行遍历
- 如果当前元素大于最大值
- 将highest赋值给secondHighest
- 将当前元素赋值给highest
- 否则,如果当前元素大于secondHighest
- 将当前元素赋值给secondHighest
代码实现:
1 | java复制代码public class FindSecondLargestMain { |
找出数组中出现奇数次的数
题目描述:
给定一个整数数组, 只有一个数字出现奇数次,其他数字都出现偶数次。 你需要找到奇数次出现的数字。 需要用O(n)时间复杂度和O(1)空间复杂度来解决它。
思路1:
暴力解法:使用两层循环,记录每个元素出现的次数,这种方法的时间复杂度为O(n^2),不是最优解。
思路2:
使用Hash,将数字作为key,出现的次数作为value,每当key重复时,value+1,这种解法的时间复杂度为O(n),但是空间复杂度也为O(n),不符合要求。
代码实现:
1 | java复制代码int getOddTimesElementHashing(int ar[]) { |
思路3:
基于位运算异或操作。
异或运算:相同为0,不同为1。如a=1001,b=1010,则a^b=0010,a^a=0000。
按照题目描述,数组中只有1个数字出现奇数次,其他数字都是偶数次,则将所有数字异或运算后的结果就是出现奇数次的数字。
代码实现:
1 | java复制代码int getOddTimesElement(int arr[]) { |
该解法的时间复杂度为O(n)
;因为只使用了一个变量result
,所以空间复杂度为O(1)
。
计算火车站需要的最少站台数
题目描述:
给定两个数组,分别对应火车站车辆到达的时间和出站的时间,计算出火车站最少需要几个站台。
1 | java复制代码// 到达时刻表 |
思路1:
遍历两个数组,检查每个到达和出站的时间间隔有多少重叠。
这种方式的时间复杂度为O(n^2),不是最优解。
思路2:
使用归并排序的逻辑。
- 对到达和出发的数组进行排序;
- 因为到达和出站数量一样,则从两个数组中取出相同位置的元素比较时间大小;
- 如果到达时间早,则站台数加1;
- 如果出站时间早,则站台数减1;
- 在这个过程中记录最大的站台数;
- 最后返回最大站台数的值。
这种算法的时间复杂度为O(n*log n)。
代码实现:
1 | java复制代码public class TrainPlatformMain { |
数组中最两数之和最接近0的两个数
题目描述:
一个数组中有一系列的正数和负数,找出数组中两数之和最接近0的两个数。
例如:
1 | java复制代码array[]={1,3,-5,7,8,20,-40,6}; |
思路1:
暴力解法:将所有数字两两求和,如果和的绝对值更小,则赋值记录两数的值。
这种方法的时间复杂度为O(n^2)
,不是最优解。
代码实现:
1 | java复制代码public static void findPairWithMinSumBruteForce(int arr[]) { |
思路2:
- 对数组进行排序;
- 定义两个索引对应数组的开始位置l=0,一个在结束位置r=n-1;
- 按照l<r的条件循环
- 计算arr[l]+arr[r]的和sum
- 如果abs(sum)<abs(minSum),将l和r记录在最小的两个数组元素变量上;
- 如果sum>0,则sum要更接近0需要将大值往小移动,r–;
- 如果sum<0,则sum要更接近0需要将小值往大移动,l++。
代码实现:
1 | java复制代码public static void findPairWithMinSum(int arr[]) { |
该算法的时间复杂度为O(NLogN)
。
数组中最两数之和最接近X的两个数
该问题为上一题的进阶版,找出两数之和最接近X的数。
思路1:
暴力解法:两层循环,求和与最接近的数进行比较,如果更小则记录对应数字,时间复杂度为O(n^2),不是最优解。
思路2:
与上一题的区别在于该问题要对求和结果比较的值是指定的X,不是0,不能直接使用abs()函数的结果进行比较;那该如何处理呢?
可以通过将abs()结果减去X,则对应该问题的解法。
- 对数组进行排序;
- 定义两个索引对应数组的开始位置l=0,一个在结束位置r=n-1;
- 按照l<r的条件循环
- 计算
arr[l]+arr[r]-x
的结果diff - 如果abs(diff)<minDiff,将l和r记录在最小的两个数组元素变量上;
- 如果sum>x,则sum要更接近x需要将大值往小移动,r–;
- 如果sum<x,则sum要更接近x需要将小值往大移动,l++。
代码实现:
1 | java复制代码public static void findPairWithClosestToX(int arr[], int X) { |
数组中两数之和等于X的所有组合
题目描述:
给定一个数组和一个指定数字,查找出数组中所有两数之和等于指定数字的组合。
思路1:
两层循环暴力解法,时间复杂度低,不是最优解。
代码实现:
1 | java复制代码public static void findPairsWithSumEqualsToXBruteForce(int arr[], int X) { |
思路2:
对数组进行排序;
从数组的两端进行遍历,直到相遇,使用l代表左边,r代表右边;
如果arr[l]+arr[r]=X,则符合条件,打印结果,l–,r–;
如果arr[l]+arr[r]>X,则表示结果偏大,需要将大值降低,r–;
如果arr[l]+arr[r]<X,则表示结果偏小,需要将小值升高,l++;
代码实现:
1 | java复制代码public static void findPairsEqualsToX(int arr[], int X) { |
该解法时间复杂度为:O(NLogN)
。
思路3:
- 使用HashMap,将数组元素的值作为key,下标作为value放入map中;
- 遍历数组;
- 如果X-arr[i]在HashMap中存在,则从Map中取出结果,代表符合条件。
代码实现:
1 | java复制代码public static void findPairsEqualsToXUsingHashing(int arr[], int X) { |
本文转载自: 掘金