迎战蓝桥 算法·每日一题(详解+多解)-- day1
Posted 爱干饭的猿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了迎战蓝桥 算法·每日一题(详解+多解)-- day1相关的知识,希望对你有一定的参考价值。
🤞目录🤞
【大家好,我是爱干饭的猿,如果喜欢这篇文章,点个赞👍,关注一下吧,后续会一直分享题目与算法思路】
🏀1. 二维数组中的查找
描述:
在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
[ [1,2,8,9],
[2,4,9,12],
[4,7,10,13],
[6,8,11,15] ]给定 target = 7,返回 true。
给定 target = 3,返回 false。
数据范围:矩阵的长宽满足 0 \\le n,m \\le 5000≤n,m≤500 , 矩阵中的值满足 0 \\le val \\le 10^90≤val≤109
进阶:空间复杂度 O(1)O(1) ,时间复杂度 O(n+m)O(n+m)
解题思路:
🎈1. 方法一: 查找的本质是排除,使用可以用双重循环,如果arr[i][j] = target,则找到target,返回true,但是效率太低。
🎈2. 方法二:我们可以将target 与右上角值比较,达到每次排除一行或一列的效果
如果target 大于右上角值,则排除当前行;
如果target 小于右上角值,则排除当前列;
🎈方法二:代码如下:
public class SearchIN2DArr_1
public boolean Find(int target, int [][] array)
if(array.length == 0 )
return false;
int row = 0;
int col = array[0].length - 1;
while(row < array.length && col >= 0)
// array[row][col] 一定是当前行最大的
if(target < array[row][col])
// 排除当前列
col --;
else if(target > array[row][col])
// 排除当前行
row ++;
else
return true;
return false;
🏀2. 旋转数组的最小数字
描述:
有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。
数据范围:1 \\le n \\le 100001≤n≤10000,数组中任意元素的值: 0 \\le val \\le 100000≤val≤10000
要求:空间复杂度:O(1)O(1) ,时间复杂度:O(logn)O(logn)
解题思路:
🎈1. 方法一:理论上,我们可以进行一次遍历即可,因为是非降序数组arr[i] < arr[i+1],所以当旋转后,遇到arr[i] > arr[i+1]时,该值(arr[i+1])就是最小值。
🎈2. 方法二:我们可以使用二分法进行定位,时间复杂度更低,定义 left 最左,right 最右,mid 中间
因为数组非降序,所以
如果arr[left] <= arr[mid],旋转数组就在mid右侧[mid...right],使left = mid;
如果arr[left] > arr[mid],旋转数组就在mid右侧[left...mid],使right = mid;
范围不断缩小,当left 与 right 相邻时,arr[right] 就是最小值。
🎈方法一:代码如下
public int minNumberInRotateArray1(int [] array)
if(array == null || array.length == 0)
return 0;
for(int i = 0; i < array.length-1; i++)
// 遇到arr[i] > arr[i+1]时,该值arr[i+1]就是最小值
if(array[i] > array[i+1])
return array[i+1];
return array[0];
🎈方法二:代码如下
public static int minNumberInRotateArray2(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])
if (right - left == 1)
mid = right;
break;
mid = left + ((right - left) >> 1);
// 恰巧left right mid 值相等
if (array[left] == array[mid] && array[left] == array[right])
int restlt = array[left];
for (int i = left + 1; i < right; i++)
if (restlt > array[i])
restlt = array[i];
return restlt;
if (array[left] <= array[mid])
// 旋转数在右侧,[mid...right]
left = mid;
else
// 旋转数在左侧,[left...mid]
right = mid;
return array[mid];
🏀3. 调整数组顺序使奇数位于偶数前面
描述:
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。(进阶:保证奇偶位置不变)
示例:
[1, 2, 3, 4, 5]
输出:
[1, 3, 5, 2, 4]
解题思路:
🎈1. 方法一:使用二分法,定义 left 最左,right 最右,遍历数组,找 arr[left] 为偶数,arr[right] 为奇数,然后交换两值。
🎈2. 方法二:(进阶:保证奇偶位置不变):因为相对位置不能改变,不能用二分法,用直接插入法。遍历数组,当找到奇数时,将该奇数之前的偶数都后移一位,然后该奇数存入偶数前的位置。
🎈方法一:代码如下
// 若相对位置可以改变,使用二分法
public static void reOrderArray1(int [] array)
int left = 0;
int right = array.length - 1;
while (left < right)
// &运算 0&1=0,1&1=1,1&0=0,0&0=0
while ((array[left] & 1) == 1 && left < right)
// 找到偶数
left++;
while ((array[right] & 1) == 0 && left < right)
// 找到奇数
right--;
if(left < right)
// 交换三联
int temp = array[left];
array[left] = array[right];
array[right] = temp;
🎈方法二:代码如下
// 因为相对位置不能改变,不能用二分法,用直接插入
public static void reOrderArray2(int [] array)
// 记录已排奇数的末位置索引
int k = 0;
for (int i = 0; i < array.length; i++)
// &运算 0&1=0,1&1=1,1&0=0,0&0=0
// 找到奇数
if((array[i] & 1) == 1)
int temp = array[i];
int j = i;
// 将 k~j 的偶数后移
while(k < j)
array[j] = array[j-1];
j--;
array[k] = temp;
k++;
以上是关于迎战蓝桥 算法·每日一题(详解+多解)-- day1的主要内容,如果未能解决你的问题,请参考以下文章