题目:一个二维数组里面是由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); }
时间: 2024-10-29 13:57:06