0


数组相关高频算法考点

文章目录


一、调整数组顺序使奇数位于偶数前面

牛客链接
描述:
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变
解题思路:
此题要求奇数与偶数的相对位置不发生改变,并且奇数要位于偶数的前面,此时我们可以利用插入排序的思想:让奇数插入到数组的前面,偶数统一往后移动,以此达到题述目的。
代码示例:

publicclassSolution{//将偶数统一往后移动,将奇数插入publicvoidreOrderArray(int[] array){if(array ==null|| array.length ==0){return;}int k =0;for(int i =0;i < array.length;i++){//如果数组中得数字是奇数if(array[i]%2!=0){int tmp = array[i];int j = i;//记录下出现奇数位置的下标while(j > k){//将偶数统一往后移动一位
                    array[j]= array[j -1];
                    j--;}
                array[k++]= tmp;}}}}

二、判断二维数组中是否包含某数

牛客链接
描述:
在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数

[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]

给定 target = 7,返回 true。
给定 target = 3,返回 false。
查找的过程本质就是排除的过程
解题思路:
让目标值与数组右上角的元素进行比较,由于数字从左到右,从上到下都是递增的,如果目标值小于右上角元素,则排除最后一列元素,因为左上角元素是最后一列元素中最小的数,目标值比一列中最小的元素都小,则这一列的元素就都可以被排除,数组对应的列数减一列;如果目标值大于右上角元素,则排除右上角元素所在位置的一整行,因为右上角元素是这一行中最大的元素,目标值比这一行最大的元素都大,则这一行元素都被排除,对应的行数加一行;以此方式遍历完整个数组,直到找到目标元素。
代码示例:

publicclassSolution{publicbooleanFind(int target,int[][] array){if(array ==null){returnfalse;}int i =0;//记录二维数组行数int j = array[0].length -1;//记录二维数组列数while(i < array.length && j >=0){if(target < array[i][j]){//将目标元素与数组右上角元素相比
                j--;}elseif(target > array[i][j]){
                i++;}else{returntrue;}}returnfalse;}}

三、旋转数组的最小数字

牛客链接
描述:
有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[5,1,2,3,4]这样的。请问,给定这样一个旋转数组,求数组中的最小值。
解题思路:
方法一:理论上,遍历一次即可,但是我们可以根据题面使用稍微高效且更简单一点的做法按照要求,要么是一个非递减排序的数组最小值在最开始),要么是一个旋转(最小值在中间某个地方)而且,旋转之后有个特征,就是在遍历的时候,原始数组是非递减的,旋转之后,就有可能出现递减,引起递减的数字,就是最小值
方法二:采用二分查找的方式,进行定位。定义首尾下标,因为是非递减数组旋转,所以旋转最后可以看做成两部分,前半部分整体非递减,后半部分整体非递减,前半部分整体大于后半部分。所以,我们假设如下定义,

left

指向最左侧,

right

指向最右侧,

mid

为二分之后的中间位置。则:

a[mid] >= a[left]

,说明

mid

位置在原数组前半部分,进一步说明,**目标最小值,在

mid

的右侧**,让

left=mid

a[mid] < a[left]

, 说明

mid

位置在原数组后半部分,进一步说明,**目标最小值,在

mid

的左侧**,让

right=mid

;这个过程,会让

[left, right]

区间缩小;
这个过程中,left永远在原数组前半部分,right永远在原数组的后半部分,而范围会一直缩小
当left和right相邻时,right指向的位置,就是最小元素的位置,但是,因为题目说的是非递减,也就意味着数据允许重复,因为有重复,就可能会有

a[left] == a[mid] ==a[right]

的情况,我们就无法判定数据在

mid

左侧还是右侧。(注意,只要有两者不相等,我们就能判定应该如何缩小范围)。
方法一:

importjava.util.ArrayList;publicclassSolution{publicintminNumberInRotateArray(int[] array){if(array ==null|| array.length ==0){return0;}for(int i =0; i < array.length-1; i++){//前半段非递减,后半段非递减,引起递减的数字,就是最小值if(array[i]> array[i+1]){return array[i+1];}}//整个数组是非递减的,最小值在最开始的地方return array[0];}}

方法二:

importjava.util.ArrayList;publicclassSolution{//5 1 2 3 4//3 4 5 1 2publicintminNumberInRotateArray(int[] array){if(array ==null||array.length ==0){return0;}int left =0;int right = array.length -1;int mid =0;while(array[left]>= array[right]){//数组中是2个数的情况下if(right - left ==1){
                mid = right;break;}//不能分辨中间值和两边值的大小//             mid =  (right + left) / 2;
            mid = left +(right - left)/2;if(array[left]== array[right]&& array[mid]== array[left]){int res = array[mid];//因为两边值相等,所以不需要考虑两边值的情况for(int i = left +1;i < right;i++){if(res > array[i]){
                        res = array[i];}}return res;}if(array[mid]>= array[left]){
                left = mid;}elseif(array[mid]< array[left]){
                right = mid;}}return array[mid];}}

四、数组中出现次数超过一半的数字

牛客链接
描述:
给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
例如输入一个长度为9的数组

[1,2,3,2,2,2,5,4,2]

。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。

思路一:排序,出现次数最多的数字,一定在中间位置。然后检测中间出现的数字出现的次数是否符合要求。
先将数组进行排序,然后得到数组中间位置元素,遍历数组并记录中间位置元素出现的次数,最后判断中间位置元素出现次数是否等于数组长度的一半,如果超过数组长度的一半,则返回该元素,反之返回0。

importjava.util.*;publicclassSolution{publicintMoreThanHalfNum_Solution(int[] array){if(array ==null){return0;}int len = array.length /2;Arrays.sort(array);int key = array[len];int count =0;for(int i =0;i < array.length;i++){if(array[i]== key){
                count++;}}if(count > len){return key;}return0;}}

思路二:定义map,使用<数字,次数>的映射关系,最后统计每个字符出现的次数。

importjava.util.*;publicclassSolution{publicintMoreThanHalfNum_Solution(int[] array){if(array ==null){return0;}//第一个Integer表示数组中的元素,第二个Integer表示数组中元素出现的次数Map<Integer,Integer> map =newHashMap<>();for(int i =0;i < array.length;i++){if(!map.containsKey(array[i])){//map中不包含该元素,则将元素放入map,并将计数值设置为1
                   map.put(array[i],1);}else{//通过key值获取到对应的value值int count = map.get(array[i]);
                 count++;
                 map.put(array[i],count);}if(map.get(array[i])> array.length/2){return array[i];}}return0;}}

思路三:目标条件:目标数据超过数组长度的一半,那么对数组,我们同时去掉两个不同的数字,到最后剩下的一个数就是该数字。如果剩下两个,那么这两个也是一样的,就是结果,在其基础上把最后剩下的一个数字或者两个回到原来数组中,将数组遍历一遍统计一下数字出现次数进行最终判断。

importjava.util.*;publicclassSolution{publicintMoreThanHalfNum_Solution(int[] array){if(array ==null){return0;}int target = array[0];int count =1;for(int i =1;i < array.length;i++){if(count ==0){
                target = array[i];
                count =1;}elseif(array[i]== target){
                count++;}else{
                count--;}}
        count =0;for(int i =0;i < array.length;i++){if(target == array[i]){
                count++;}}return count > array.length/2? target :0;

以上。


本文转载自: https://blog.csdn.net/dddddrrrzz/article/details/122752508
版权归原作者 来学习的小张 所有, 如有侵权,请联系我们删除。

“数组相关高频算法考点”的评论:

还没有评论