二维数组的查找、旋转数组的最小数字

📌导航小助手📌

      📖前面的话📖

           🔒题目一:二维数组中的查找🔒

                   🔐题目描述🔐

                   💡解题思路

                   🔑源代码

                   🖋总结🖋

           🔒题目二:旋转数组的最小数字🔒

                   🔐题目描述🔐

                   💡解题思路

                   🔑源代码

                   ​​​​​​​🖋总结🖋


 

 

📖前面的话📖

本专栏介绍的是 牛客网 上面的两道题解,同时 解题所用语言均为 Java语言 ~

牛客网链接:🚘牛客网直通车🚘

🔒题目一:二维数组中的查找🔒

✨题目链接:二维数组中的查找

 

🔐题目描述🔐

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

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

给定 target = 7,返回 true。

给定 target = 3,返回 false。


示例1:

输入:7,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]
返回值:true
说明:存在7,返回true  

示例2:

输入:1,[[2]]
返回值:false

 示例3:

输入:3,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]
返回值:false
说明:不存在3,返回false  

💡解题思路

思路一:

遍历二维数组,在期间进行判断,如果找到目标值,返回 true,如果找不到目标值,返回 false ~

缺点:效率低下 ~


思路二:

通过每一次查找,都会排除多个元素; 

通过观察,我们可以发现,每一行的最右上角的元素 都是该行的最大值,都是该列的最小值 ~

以所给的描述中的二维数组为例,假设此时所要查找的目标值是 7,那么,此时要比最右上角的值9 要小,就说明 目标值肯定不在该列(因为该列的最小值就是 最右上角的值9,目标值比这一列最小的值还要小),那么 此时就可以排除这一列的值了 ~

同样的道理,如果目标值要比最右上角的值还要大,就说明目标值就不再这一行,这样就直接排除了一行的值 ~

此时,此时查找的效率就相对于比较高了 ~

这种思路要考虑一下临界条件 !!!

🔑源代码

public class Solution {
    //二维数组的查找
    public boolean Find(int target, int [][] array) {
        //判断二维数组为null 或者 数组长度为 0 (非法情况)
        if(array == null || array.length == 0){
            return false;
        }
        //i、j表示的是数组的下标
        //i表示行,j表示列
        int i = 0;
        int j = array[0].length - 1;
        while (i<array.length && j>=0){
            //目标值大于最右边的值
            if(target > array[i][j]) {
                //不可能出现在这一行
                i++;
            }
            else if(target < array[i][j]) {
                j--;
            }
            else {
                return true;
            }
        }
        return false;
    }
}

🖋总结🖋

  • 需要注意的是 非法的情况:一是数组为 null,二是数组长度为 0;
  • 需要注意的是 二维数组中,第一行的长度可以用 array[0].length 来表示 ~

🔒题目二:旋转数组的最小数字🔒

✨题目链接:旋转数组的最小数字

🔐题目描述🔐

有一个长度为 n 的非降序数组,比如[1,2,3,4,5],将它进行旋转,即把一个数组最开始的若干个元素搬到数组的末尾,变成一个旋转数组,比如变成了[3,4,5,1,2],或者[4,5,1,2,3]这样的。请问,给定这样一个旋转数组,求数组中的最小值。

要求:空间复杂度:O(1),时间复杂度:O(logn) 。

示例1:

输入:[3,4,5,1,2]
返回值:1

 示例2:

输入:[3,100,200,3]
返回值:3

 

💡解题思路

思路一:

遍历整个数组,遍历期间,定义一个最小值,如果数组中的哪个元素要比最小值还要小,自动更新 ~

思路二:

由于数组非递减,而且是旋转过来的;

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

所以可以比较 当前值和下一个值的大小,如果当前值 <= 下一个值,那么就是正确的,可以换下一个;如果当前值 >= 下一个值的大小(第一次大于),那么就说明 下一个值就是我们要找的最小元素 ~

思路三: 

不管怎么旋转数组,得到的数组都可以把它看成两个 "非递减的" 部分,只是由于旋转次数的不同,最小值时在中间值的左边或右边或正好就是中间值罢了;

同时,前半部分的值 要在整体上 > 后半部分的值 ;

🔑源代码

import java.util.*;
import java.util.ArrayList;
public class Solution {
    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]) {
            //如果两个元素已经相邻了,说明最右侧的值一定是要找的值
            if(right - left == 1) {
                mid  = right;
                break;
            }
            //左边值 == 中间值 == 右边值 的情况
            if(array[left] == array[right] && array[left] == array[mid]) {
                int result = array[left];
                //一个一个遍历
                for (int i = left + 1; i < right; i++) {
                    if(result > array[i]) {
                        result = array[i];
                    }
                }
                return result;
            }
            //更新 mid 的值
            mid = (right + left) >> 1;
            
            //如果中间值 >= 左半部分的值,就说明 最小的值在右半部分,这就直接把左半部分的值给排除了
            if(array[mid] >= array[left]) {
                left = mid;
            }
            else {
                right = mid;
            }
        }
        return array[mid];
    }
}

🖋总结🖋

  • 该题仍然是查找类型的题目,如果一次可以排除多个元素显然是更好
  • 在使用二分查找的时候,需要另起判断 是否左中右值相等的情况

这篇博客就写到这里啦 ~

如果觉得写得不错的老铁们,一键三连起来吧 ~

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哎呀是小张啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值