数组相关高频算法考点

数组相关高频算法考点,第1张

数组相关高频算法考点

文章目录

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

二、判断二维数组中是否包含某数三、旋转数组的最小数字四、数组中出现次数超过一半的数字


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

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

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表示数组中元素出现的次数
        Map map = 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;     

以上。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5714585.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-18
下一篇 2022-12-18

发表评论

登录后才能评论

评论列表(0条)

保存