首页 > 代码库 > 新手算法学习之路----二分法SmallestRectangle

新手算法学习之路----二分法SmallestRectangle

题目:一个二维数组里面是由1和0构成的,里面所有的1都是相互关联的,有且只有一块由连续1构成的区域,请找出来最小能包括所有1的矩形,

前提:给出一个任意二维数组以及其中的一个1的元素的x和y坐标。

                             0,1,1,0

例如:int [2][3]a={{0,0,1,0},     1   这一行含有1,映射到行边上为1

                            {0,1,1,0},      1   同上

                            {0,1,0,0}}      1   同上

解题思想:如上面的例子里面,如果一列里面有1就映射到第一行对应的位置   如上面二维数组将所有含有1的列映射到第一行就形成了蓝色字体的0110,那么矩形的宽就出来,同理到长;

                 由给定的点来将长宽分为四部分来求,二维数组中红1为给定的点,那么就可以将长宽分为点左,右,上,下边的四部分。如:先求点左边第一个 1的位置,将问题转化为蓝色部分的数组,利用二分法来求,low = 0,high = y =1;下面代码中第一个while语句。

解题中遇到的问题:1,我TMD连java二维数组申明都不会用了。

                                2,while里面是low<=high 还是low<high&&(low+1)!=high,

                                3,left right up down四个变量最后该赋予那个值是 low还是high

解决的办法:如果用low<high&&(low+1)!=high,就必须在每个while语句后判断最终的low 与high哪一个为1,然后赋值给left这样会增加空间复杂度。

                     如果是low<=high 则直接可以将left = low;

public class SmallestRectangle {

           public static void main(String[] args) {
             char[][]array = {{‘0‘,‘1‘,‘1‘,‘0‘},
                              {‘0‘,‘1‘,‘1‘,‘0‘},
                              {‘0‘,‘1‘,‘1‘,‘0‘},
                              {‘0‘,‘1‘,‘1‘,‘0‘}};
             int x = minArea(array,0,1);
             System.out.println(x);
            }    
 
            static int minArea(char[][] image, int x, int y) { 
            int left,right,up,down;     //这四个变量分别表示点的左,右部分第一个含有‘1’的列的列号,以及上,下第一个含有‘1’的行的行号
            int low,high;               //这两个变量分别表示在while里面用来寻找中点的两端
            low = 0;
            high = y;
            int mid;
            
            //第一部分 while的功能是点的左边部分
            while(low<=high){                     //此while用来找点(x,y)右边的哥一个里面没有‘1’的列号
                boolean found = false;
                mid = low + (high- low)/2;
                for(int i =0;i<image.length;i++){  //image.length是二维数组的行号,用来对比一整列里面是否含有‘1’
                    if(image[i][mid]==‘1‘){
                        found = true;
                        break;
                    }
                }
                if(found)
                    high = mid-1;                  
                else
                    low = mid+1;                    
            }
            left= low;   //
            
            //第二部分while功能是点的右部分。
            low = y;
            high = image[x].length-1;                // image[x].length 为二维数组列的长度。
            while(low<high){
                boolean found_right = false;
                mid = low+(high-low)/2;
                for(int i = 0;i<image.length;i++){
                    if(image[i][mid]==‘1‘){
                        found_right = true;
                        break;
                    }
                }
                if(found_right) low = mid+1;
                else high = mid-1;
            }
            right = low;
            
            //第三个while的作用是找到点0到x所有的含有‘1’的行的行号
            low = 0;
            high = x;
            
            while(low<=high){
                boolean found_up = false;
                mid = low+ (high-low)/2;
                for(int i =0;i<image[x].length;i++){
                    if(image[mid][i]==‘1‘){
                        found_up = true;
                        break;
                    }
                }
                if(found_up)  high = mid-1;
                else low = mid+1;                
            }
            up = low;            
            
            //第四个while的作用是找到点0到x所有的含有‘1’的行的行号
            low = x;
            high = image.length-1;            
            while(low<=high){
                boolean found_down = false;
                mid = low+ (high-low)/2;
                for(int i =0;i<image[x].length;i++){
                    if(image[mid][i]==‘1‘){
                        found_down = true;
                        break;
                    }
                }
                if(found_down)  low = mid+1;
                else high = mid-1;                
            }
            down = low;
            return (right-left)*(down-up);         
            
            
        
    }

 

新手算法学习之路----二分法SmallestRectangle