标签:void table binary false 一个 题目 整数 范围 param
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
| a1 | a2 | a3 | a4 | a5 | a6 | 
|---|---|---|---|---|---|
| b1 | → | → | → | → | → | 
| c1 | ↓ | ||||
| d1 | ↓ | ||||
| e1 | ↓ | ||||
| f1 | ↓ | 
题目的理解错了,错误的认为,矩阵满足这样的规律:
| 1 | 2 | 3 | 4 | 
|---|---|---|---|
| 5 | 6 | 7 | 8 | 
| 9 | 10 | 11 | 12 | 
| 13 | 14 | 15 | 16 | 
其实这只是一个特例,题目只说举证中的元素满足“左小右大,上小下大”的特点,更一般的矩阵是这样的:
| 1 | 2 | 8 | 9 | 
|---|---|---|---|
| 2 | 4 | 9 | 12 | 
| 4 | 7 | 10 | 13 | 
| 7 | 8 | 15 | 15 | 
正确理解的题目的意思以后,我编写出了满足题目要求的代码。具体的思路是:遍历每一行,对每一行进行二分查找。
package com.learn.java;
import java.util.Arrays;
/**
 * @author xzy
 * @date 2020-03-25 18:56
 * 说明:
 */
public class Main {
    public static void main(String[] args) {
        Main main = new Main();
        int[][] array = new int[][]{
                {1, 2, 8, 9},
                {2, 4, 9, 12},
                {4, 7, 10, 13},
                {6, 8, 11, 15}
        };
        for (int i = 0; i < 40; i++) {
            System.out.println("target:" + i + " find:" + main.find(i, array));
        }
    }
    /**
     * @param target - 查找目标
     * @param array  - 查找数组
     * @return 找到:元素下标  找不到:-1
     */
    public int binarySearch(int target, int[] array) {
        // head:查找区间头 middle:查找区间中 end:查找区间尾
        int head = 0;
        int end = array.length - 1;
        int middle = end / 2;
        //1. 不可能找得到
        if (target < array[head] || target > array[end]) {
            return -2;
        }
        //2. 二分查找
        while (head <= end) {
            if (target == array[middle]) {
                //1. 找到
                return middle;
            } else if (target < array[middle]) {
                //2.向左侧继续找
                end = middle - 1;
                middle = (end - head) / 2 + head;
            } else {
                //3.向右侧继续找
                head = middle + 1;
                middle = (end - head) / 2 + head;
            }
        }
        return -1;
    }
    public boolean find(int target, int[][] array) {
        for (int row = 0; row < array[0].length; row++) {
            if (binarySearch(target, array[row]) >= 0) {
                return true;
            }
        }
        return false;
    }
}
仔细的琢磨“左小右大,上小下大”
| 1 | 2 | 3 | 9 | 
|---|---|---|---|
| 2 | 4 | 9 | 12 | 
| 4 | 7 | 10 | 13 | 
| 7 | 8 | 15 | 15 | 
第1行最右边的元素,是第一行最大的。
第2行最右边的元素,是前两行最大的。
第3行最右边的元素,是前三行最大的。
第4行最右边的元素,是前四行最大的。
第1列最后一个元素,是第一列最大的。
第2列最后一个元素,是前两列最大的。
第3列最后一个元素,是前三列最大的。
第4列最后一个元素,是前四列最大的。
新的算法思想:从行列角度出发,从第一行开始,将target与每一行最后一个元素比较,排除target不可能存在的行,同时排除target不可能存在的列。
以target == 11为例,将target与第一行最后一个元素9比较,发现target > 9,而9又是第1行最大的元素,显然,target不可能存在于第一行。继续将target与第二行最后一个元素12比较,发现target<12,而12又是第4列后3行中最小的元素,显然,target不可能存在于第4列。
上述算法不断缩小元素可能存在的范围,范围的缩小过程是这样的:
| 1 | 2 | 3 | 9 | 
|---|---|---|---|
| 2 | 4 | 9 | 12 | 
| 4 | 7 | 10 | 13 | 
| 7 | 8 | 15 | 15 | 
| 2 | 4 | 9 | 12 | 
|---|---|---|---|
| 4 | 7 | 10 | 13 | 
| 7 | 8 | 15 | 15 | 
| 2 | 4 | 9 | 
|---|---|---|
| 4 | 7 | 10 | 
| 7 | 8 | 15 | 
| 4 | 7 | 10 | 
|---|---|---|
| 7 | 8 | 15 | 
target < 15
| 7 | 8 | 15 | 
|---|---|---|
target > 8
| 7 | 8 | 
|---|---|
已经没有范围缩小到0,可以确认,矩阵中不存在target。
利用新的思想,新的实现代码:
public boolean find2(int target, int[][] array) {
    //rowMax:行坐标最大值 columnMax:列坐标最大值
    int rowMax = array.length - 1;
    int columnMax = array[0].length - 1;
    //空矩阵判断
    if (rowMax < 0 || columnMax < 0) {
        return false;
    }
    //target是否有可能存在于矩阵
    if (target < array[0][0] || target > array[rowMax][columnMax]) {
        return false;
    }
    //(rowPoint,columnPoint)当前检查元素的坐标
    int rowPoint = 0;
    int columnPoint = columnMax;
    while (rowPoint <= rowMax && columnPoint >= 0) {
        if (target == array[rowPoint][columnPoint]) {
            return true;
        } else if (target > array[rowPoint][columnPoint]) {
            //不可能在这一行
            rowPoint++;
        } else {
            //不可能在这一列
            columnPoint--;
        }
    }
    return false;
}
标签:void table binary false 一个 题目 整数 范围 param
原文地址:https://www.cnblogs.com/KenBaiCaiDeMiao/p/12573856.html