首页 > 试题广场 >

给定如下的n*n的数字矩阵,每行从左到右是严格递增, 每列的

[问答题]

给定如下的n*n的数字矩阵,每行从左到右是严格递增, 每列的数据也是严格递增

1  2  3

3  5  6

4  8  9

现在要求设计一个算法, 给定一个数k 判断出k是否在这个矩阵中。描述算法并且给出时间复杂度(不考虑载入矩阵的消耗)

以题目示例为例
1 2 3
3 5 6
4 8 9   查找4
以row代表当前所比较行,col代表当前所比较列
关键:从矩阵的右上角开始寻找
①先判断它与第一行最后一列即row=0,col=2的大小关系,因为4是大于3的
第一行在3左边的数字都不可能再比3更大,所以row++,row=1
②判断4与row=1,col=2的关系,因为4是小于6的
最后一列6下边的数字都不可能比6更下,所以col--,col=1
③判断4与row=1,col=1的关系,因为4是小于5的
第二列下边的数字都不可能比5更下,所以col--,col=0
④判断4与row=1,col=0的关系,因为4是大于3的
第二行在3左边的数字都不可能比3更大(虽然这里也不存在左边的数字),所以row--,col=0

终止条件:
①找到
②不可能找到,即超出了边界,row<0,row>=所给矩阵行数,col<0,col>所给矩阵列数

菜狗分析,有意见指出,有问题cue我
发表于 2019-09-11 11:02:21 回复(1)
 如何将判断一个数字是否在一个数字集合里
    最老实的办法就是将集合里的数字排序后,根据二分法原则去快速查找,然后比较;
-->现在这个数字集合的数字存在这样的规律:是一个排序后的二维数组
-->问题变为:如何快速判断一个指定的数字是否存在于某个指定数量的(n*n)、有序的二维数组的集合中   
 -->
    二维数组的每一维的数组都是递增
    迭代数组-中轴线上的数, 与指定的数字k比较大小或是否相等
    ==>
    如果大于中轴线上的某一个数字且小于下一个中轴线上的数字,则与这两个数字的左下角及右上角的数字相比较
    ==>如果有相等,则指定的数字存在于数字集合中(二维数组)
    
==>可能的其他情况: 
        (1)迭代完成的, 指定的数字k比集合中的所有数都大。 k不存在指定的数字集合中
        (2)数字k比数字集合中的所有的数都小。 

                    

    
    
    
    

    

发表于 2019-05-30 16:54:15 回复(0)
思想:矩阵行列均为递增,那么矩阵右上角的数则在当前行最大当前列最小。找到矩阵右上角的数,如果比K(需要比较的数)小,说明当前行均小于K,排除该行,行数加一。如果比K大,说明该列均大于K,排除该列,列数减一。
public class FindNumInSortedMatrix {
    public static boolean isContains(int[][] matrix, intk) {
        int row = 0;
        int col = matrix[0].length - 1;
        while(row < matrix.length && col > -1) {
            if(matrix[row][col] == k) {
                return true;
            }elseif(matrix[row][col] > k) {
                col--;
            }else{
                row++;
            }
        }      
    return false;
    }
}
编辑于 2019-06-13 16:16:35 回复(1)
算法实现:根据题目所描述的矩阵特性,那么可以从矩阵的右上角的地方看,即data[0][n-1],以此为根节点,可看成一个二叉排序树,然后根据二叉排序树的特性,左边是小于根节点的,右边是大于根节点的,可以此进行数据的查询。代码如下,
public boolean BinaryTreeSearch(int data[][],int k) {
        if(data==null || data.length==0)return false;
        
        int n=data.length;
        int i=0,j=n-1;
        
        while(i<n && j>=0 && data[i][j]!=k) {
            if(k>data[i][j]) {
                i++;
            }
            else {
                j--;
            }
        }
        
        if(i<n && j>=0 && data[i][j]==k)return true;
        else return false;
}


发表于 2020-08-16 17:51:14 回复(0)
可以用二分查找法,因为该矩阵的行和列都是有序的,也就是说下一行的所有元素必然都大于上一行,首先递归找到目标数字所在的数组,以该数字在数组最小值和最大值之间为依据,之后对目标数组进行二分搜索得到结果,复杂度为O(2log2n)
public class Main2 {
        public static void main(String [] args){
            //假设n为8
            int n=8;
            int k=64;
            int content=0;
            Integer[] [] nums=new Integer[8][8];
            for (int i = 0; i <n; i++) {
                for (int j = 0; j < n; j++) {
                    nums[i][j]=content++;
                }
            }
            Integer [] first=first(nums,k);
            if(first==null){
                System.out.println(false);
            }else if(first.length==1){
                System.out.println(true);
            }else{
                System.out.println(second(first,k));
            }

        }

        public static Integer [] first(Integer [][] nums,int k){
            if(nums.length==1){
                Integer max=nums[0][nums[0].length-1];
                Integer min=nums[0][0];
                if(k>min&&k<max)
                    return nums[0].clone();
                else
                    return null;
            }
            int mid=nums.length/2;
            Integer[] midNums=nums[mid];
            if(k<midNums[midNums.length-1]){
                return first(Arrays.copyOfRange(nums,0,mid),k);
            }else if(k>midNums[midNums.length-1]){
                return first(Arrays.copyOfRange(nums,mid,nums.length),k);
            }else{
                return new Integer[]{k};
            }
        }

        public static boolean second(Integer[] first,int k){
            if(first.length==1){
                return first[0]==k;
            }
            int mid=first.length/2;
            if(k<first[mid]){
                return second(Arrays.copyOfRange(first,0,mid),k);
            }else if(k>first[mid]){
                return second(Arrays.copyOfRange(first,mid,first.length),k);
            }else{
                return true;
            }
    }
}


发表于 2020-03-07 23:08:26 回复(0)
package Interview;

import java.util.Scanner;

public class FindKinAMatrix {
    public static void main(String[] args) {
        int[][] myArr = inputMatrix();
        System.out.println(find(5, myArr));
    }

    static boolean find(int k, int[][] arr) {
        // 以矩阵的最左下角的元素为基准,若k大于基准值,则往右边走,若k小于基准值,则往上边走
        // 先求出矩阵的大小
        int row = arr.length;
        int row_pivot = row - 1;
        int column_pivot = 0;
        // 则基准数值为arr[row_pivot][column_pivot]
        boolean flag = true; //表示在矩阵中没有找到k
        while (flag && (row_pivot >= 0) && (column_pivot < row)) {
            if (k > arr[row_pivot][column_pivot]) {
                column_pivot++;
            } else if (k < arr[row_pivot][column_pivot]) {
                row_pivot--;
            } else {
                flag = false; // 表示找到了k,退出循环
                //System.out.print("k的行数为"+(row_pivot+1)+",列数为"+(column_pivot+1));
                break;
            }
        }
        return (!flag);
    }

    static int[][] inputMatrix() {
        // 输入矩阵
        Scanner sc = new Scanner(System.in);
        // 输入第一行数据
        String[] firstline = sc.nextLine().split(" ");
        // 判断矩阵的大小
        int n = firstline.length;
        // 创建一个二位数组,存储输入的数据
        int[][] arr = new int[n][n];
        for (int i = 0; i < n; i++) {
            arr[0][i] = Integer.valueOf(firstline[i]);
        }
        // 矩阵的第一行数据存储完毕
        // 现在输入矩阵的其他行数据
        for (int i = 1; i < n; i++) {
            String[] inputStr = (new Scanner(System.in)).nextLine().split(" ");
            for (int j = 0; j < n; j++) {
                arr[i][j] = Integer.valueOf(inputStr[j]);
            }
        }
        return arr;
    }
}
发表于 2019-09-03 00:47:20 回复(0)
for(int i = 0 ;i < arr[0].length;i++)
    if(arr[i][0] < = k && arr[i][arr.length]>=k){
    for(int j = 0;j<arr[].length ;j++){
    if(arr[i][j] == k){
    return true;
else return false;
}
}
}
n2
发表于 2019-08-20 19:40:32 回复(0)
x为第几行,y为第几列
让数组的 x=0,y=n-1 元素和数k比较,如果该元素比数k大,x++;;如果该元素比数k小,y--;
一直循环,直到找到这个元素,则k在这个矩阵。如果x>=n 获取 y<0则代表矩阵中没有这个元素。
也可以选择左下角的一个元素,比较有特色。
发表于 2019-08-20 09:13:29 回复(0)
可以使用二分法
由于每一行每一列都是递增
所以每一次都循环可以去比较矩阵的中心点的值x
如果k==x,可判断k在这个矩阵中,跳出循环
如果k>x,如果k存在于矩阵中,k一定在矩阵的右下角,更新矩阵为原来矩阵的右下角
如果k<x,如果k存在于矩阵中,k一定在矩阵的左上角,更新矩阵为原来矩阵的左上角
当矩阵为二维矩阵时,跳出循环
遍历二维矩阵,可判断k是否存在于矩阵中
书剑复杂度为O(lgn)
发表于 2019-07-16 23:22:22 回复(0)
YL,头像 YL,
先每行的第一个数通过二分法确定K在哪一行,然后每行由于是递增的,同时N可以过长,通过二分法确定K所在的位置,
时间复杂度为O(logN)
发表于 2019-07-10 10:26:50 回复(0)
方法一:
可以暴力循环查找,时间复杂度O(n^2)
方法二:
取a[n/2][n/2],比较其和k的大小,若k>a[n/2][n/2], 则将k依次比较a[n/2][n/2]所在行的右侧数字和所在列的下侧数字。如果没找到,则递归,在a[n/2][n/2]的右上,左下,右下三个区继续相同方法寻找a[n/2][n/2]。
若k<a[n/2][n/2],同理。时间复杂度为O(n)+O(nlogn)=O(nlogn)
发表于 2019-07-09 22:21:13 回复(0)
以二分查找法的方式查找 k,先判断是在哪一行,再判断是改行的哪一列。复杂度o(log2n)
发表于 2019-07-09 19:39:06 回复(0)
public class test{
    int[] arr;
    private boolean find(int target,int capacity){
         arr = new int[capacity * capacity];
         for( int n = 0 ; n < capacity ; n ++ )
                arr[n] = n + 1;

            return findImpl(arr,target);
          
    }
   //二分查找
    private boolean findImpl(int[] arr,int target){
            int higth = arr.length;
            int low = 0;              int mid = (higth + low)/2
            while(low < higth){
                if(arr[mid] > target){
                    low = mid + 1;
                }

                if(arr[mid] < target){
                    rigth = mid - 1;
                }
                
                if(arr[mid] == target)
                    return true;                

                mid = (higth + low)/2
            }

            return false;
    }

    public stati void main(String[] args){
        int num = 0;
        int capacity = 0;
        Scanner in = new Scanner(System.in);
        System.out.println("输入目标数值:");
        num = in.nextInt();
    System.out.println("输入容量:");
capacity = in,nextInt();

System.out.println(find(num,capacity));
}

}

发表于 2019-06-13 16:27:51 回复(0)
public class Test5 {     public static void main(String[] args) {         int[][] data = {{1,2,3,4,5},                         {2,3,4,5,6},                         {4,6,7,9,11},                         {6,7,11,12,14},                         {8,10,12,13,15}};         int number = 16;         searchKey(data, number);     }          private static void searchKey(int[][] arr,int number) {         int m = arr.length;         int n = arr[0].length;         for(int i=m-1,j=0;i>=0 && j<n;) {             if(arr[i][j] == number) {                 System.out.println(true);                 return;             }else if(arr[i][j] < number) {                 j++;             }else {                 i--;             }         }         System.out.println(false);     }
}

发表于 2019-06-10 11:38:17 回复(0)