一、调整数组顺序使奇数位于偶数前面
二、判断二维数组中是否包含某数三、旋转数组的最小数字四、数组中出现次数超过一半的数字
一、调整数组顺序使奇数位于偶数前面
牛客链接
描述:
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
解题思路:
此题要求奇数与偶数的相对位置不发生改变,并且奇数要位于偶数的前面,此时我们可以利用插入排序的思想:让奇数插入到数组的前面,偶数统一往后移动,以此达到题述目的。
代码示例:
public class Solution { //将偶数统一往后移动,将奇数插入 public void reOrderArray(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。
查找的过程本质就是排除的过程
解题思路:
让目标值与数组右上角的元素进行比较,由于数字从左到右,从上到下都是递增的,如果目标值小于右上角元素,则排除最后一列元素,因为左上角元素是最后一列元素中最小的数,目标值比一列中最小的元素都小,则这一列的元素就都可以被排除,数组对应的列数减一列;如果目标值大于右上角元素,则排除右上角元素所在位置的一整行,因为右上角元素是这一行中最大的元素,目标值比这一行最大的元素都大,则这一行元素都被排除,对应的行数加一行;以此方式遍历完整个数组,直到找到目标元素。
代码示例:
public class Solution { public boolean Find(int target, int [][] array) { if(array == null){ return false; } int i = 0; //记录二维数组行数 int j = array[0].length - 1; //记录二维数组列数 while(i < array.length && j >= 0){ if(target < array[i][j]) { //将目标元素与数组右上角元素相比 j--; } else if(target > array[i][j]){ i++; }else{ return true; } } return false; } }三、旋转数组的最小数字
牛客链接
描述:
有一个长度为 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左侧还是右侧。(注意,只要有两者不相等,我们就能判定应该如何缩小范围)。
方法一:
import java.util.ArrayList; public class Solution { public int minNumberInRotateArray(int [] array) { if(array == null || array.length == 0){ return 0; } for(int i = 0; i < array.length-1; i++){ //前半段非递减,后半段非递减,引起递减的数字,就是最小值 if(array[i] > array[i+1]){ return array[i+1]; } } //整个数组是非递减的,最小值在最开始的地方 return array[0]; } }
方法二:
import java.util.ArrayList; public class Solution { //5 1 2 3 4 //3 4 5 1 2 public int minNumberInRotateArray(int [] array) { if(array == null ||array.length == 0){ return 0; } 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; }else if(array[mid] < array[left]){ right = mid; } } return array[mid]; } }四、数组中出现次数超过一半的数字
牛客链接
描述:
给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。
思路一:排序,出现次数最多的数字,一定在中间位置。然后检测中间出现的数字出现的次数是否符合要求。
先将数组进行排序,然后得到数组中间位置元素,遍历数组并记录中间位置元素出现的次数,最后判断中间位置元素出现次数是否等于数组长度的一半,如果超过数组长度的一半,则返回该元素,反之返回0。
import java.util.*; public class Solution { public int MoreThanHalfNum_Solution(int [] array) { if(array == null){ return 0; } 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; } return 0; } }
**思路二:**定义map,使用<数字,次数>的映射关系,最后统计每个字符出现的次数。
import java.util.*; public class Solution { public int MoreThanHalfNum_Solution(int [] array) { if(array == null){ return 0; } //第一个Integer表示数组中的元素,第二个Integer表示数组中元素出现的次数 Mapmap = new HashMap<>(); 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]; } } return 0; } }
**思路三:**目标条件:目标数据超过数组长度的一半,那么对数组,我们同时去掉两个不同的数字,到最后剩下的一个数就是该数字。如果剩下两个,那么这两个也是一样的,就是结果,在其基础上把最后剩下的一个数字或者两个回到原来数组中,将数组遍历一遍统计一下数字出现次数进行最终判断。
import java.util.*; public class Solution { public int MoreThanHalfNum_Solution(int [] array) { if(array == null){ return 0; } int target = array[0]; int count = 1; for(int i = 1;i < array.length;i++){ if(count == 0){ target = array[i]; count = 1; }else if(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;
以上。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)