package y2019.Algorithm.array.hard; /** * @ProjectName: cutter-point * @Package: y2019.Algorithm.array.hard * @ClassName: MaximalRectangle * @Author: xiaof * @Description: TODO 85. Maximal Rectangle * Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area. * * Input: * [ * ["1","0","1","0","0"], * ["1","0","1","1","1"], * ["1","1","1","1","1"], * ["1","0","0","1","0"] * ] * Output: 6 * * 给定一个仅包含 0 和 1 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。 * * 若是是只包含的话,那么就须要计算面积 * * @Date: 2019/7/26 16:54 * @Version: 1.0 */ public class MaximalRectangle { public int solution(char[][] matrix){ //这里就是一行不一行的遍历,而后经过每一行的数据的 if(matrix == null || matrix.length <= 0) { return 0; } int rowLen = matrix.length; int colLen = matrix[0].length; // 行 int left[] = new int[colLen], right[] = new int[colLen], height[] = new int[colLen]; //初始化 for(int j = 0; j < colLen; ++j) { right[j] = colLen; } //初始化right,用来标识这个直方图的右边坐标位置 int maxA = 0; //最大面积 for(int i = 0; i < rowLen; ++i) { int curLeft = 0, curRight = colLen; //循环遍历没一行 for(int j = 0; j < colLen; ++j) { if(matrix[i][j] == '1') { //若是是1,那么就是++高度 height[j]++; } else { height[j] = 0;//不然这个直方图的高度目前为0 } } //计算左边坐标,从0开始,由于每当出现1的时候,咱们就累加进去,若是没有出现1,是0,那么咱们要把坐标起始位置向右边移动一位 //若是是1,那么以最大值为准,由于上一层的为1 的低位在这一层为0,那么就断掉了,再也不这个直方图中 for(int j = 0; j < colLen; ++j) { if(matrix[i][j] == '1') { left[j] = Math.max(curLeft, left[j]); } else { //若是这个位置不是1,那么就要移动起始坐标 left[j] = 0; curLeft = j + 1; } } //计算直方图右边坐标,这个应该从1开始,计算右边一直在矩阵内的坐标 for(int j = colLen - 1; j >= 0; --j) { if(matrix[i][j] == '1') { //这边取最小值,由于上一层有,这一层没有,那么就往左边缩 right[j] = Math.min(curRight, right[j]); } else { //若是这个位置不是1,那么就要移动起始坐标 right[j] = colLen; curRight = j; } } //计算最大面积 for(int j = 0; j < colLen; ++j) { maxA = Math.max(maxA, (right[j] - left[j]) * height[j]); } } return maxA; } public static void main(String args[]) { char data[][] = {{'1'}}; char data2[][] = { {'1','0','1','0','0'}, {'1','0','1','1','1'}, {'1','1','1','1','1'}, {'1','0','0','1','0'} }; MaximalRectangle fuc = new MaximalRectangle(); System.out.println(fuc.solution(data2)); } }
package y2019.Algorithm.array.hard; /** * @ClassName FindMedianSortedArrays * @Description TODO 4. Median of Two Sorted Arrays * * There are two sorted arrays nums1 and nums2 of size m and n respectively. * Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)). * You may assume nums1 and nums2 cannot be both empty. * * nums1 = [1, 3] * nums2 = [2] * * The median is 2.0 * * 参考:https://www.youtube.com/watch?v=LPFhl65R7ww * @Author xiaof * @Date 2019/7/28 16:32 * @Version 1.0 **/ public class FindMedianSortedArrays { public double solution(int[] nums1, int[] nums2) { if(nums1.length > nums2.length) { return solution(nums2, nums1); //咱们须要根据长度小的中间位置计算另一个长的位置的分割点 } //获取总长 int x = nums1.length; int y = nums2.length; //计算区间 int low = 0, hight = x; //根据第一个数组进行分割 while (low <= hight) { //只要瞒住条件,就一直循环,核心思想仍是二分查找 //开始分割 int partitionx = (low +hight) / 2; int partitiony = (x + y + 1) / 2 - partitionx; //计算第二个数组的分割点,对于和是奇数的状况+1,能够向右边移动一位保证中间数据在左边,这样就不用判断左右了 //计算两个数组中被分割的临近中间位置的数据,若是分割位置是0,那也就左边没有元素不用比较计算,直接设置最小值 int maxLeftx = partitionx == 0 ? Integer.MIN_VALUE : nums1[partitionx - 1]; int minRightx = partitionx == x ? Integer.MAX_VALUE : nums1[partitionx]; //右边最小位置 int maxLefty = partitiony == 0 ? Integer.MIN_VALUE : nums2[partitiony - 1]; int minRighty = partitiony == y ? Integer.MAX_VALUE : nums2[partitiony]; //分三种状况,第一张找到了 if(maxLeftx <= minRighty && maxLefty <= minRightx) { //由于自己已经排好顺序,那么只要瞒住这个条件,那么就能够说这2个集合正好被分红了2块 //判断一共是奇数个仍是偶数个 if((x + y) % 2 == 0) { //偶数求平均值 return ((double) Math.max(maxLeftx, maxLefty) + Math.min(minRightx, minRighty)) / 2; } else { return (double) Math.max(maxLeftx, maxLefty); } } else if (maxLeftx > minRighty) { //若是左边的第一个序列的最大值比第二个序列右边最小值大,说明不是中分的数据,说明第一个序列分割的位置太大了,咱们把这个元素划归到右边去 hight = partitionx - 1; } else { //maxLefty 》 minRightx 右边第一个序列的最小值比下面的序列的最大值小,说明高位给低了 low = partitionx + 1; } } //最后出现异常状况,那就是若是序列没排序,那就GG return -1; } public static void main(String args[]) { int input1[] = {1,3}; int input2[] = {2}; FindMedianSortedArrays fuc = new FindMedianSortedArrays(); System.out.println(fuc.solution(input1, input2)); } }
package y2019.Algorithm.array.hard; /** * @ClassName LargestRectangleArea * @Description TODO 84. Largest Rectangle in Histogram * Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram. * @Author xiaof * @Date 2019/7/28 21:44 * @Version 1.0 **/ public class LargestRectangleArea { public int solution(int[] heights) { if(heights == null || heights.length <= 0) { return 0; } //求最大面积,参考85. Maximal Rectangle ,能够用一样的思路求解 //一样咱们须要找到这个直方图的左边界,右边界,而后整合全部直方图的最大值 int left[] = new int[heights.length], right[] = new int[heights.length]; //遍历全部直方图,并根据当前直方图获取左右两边的位置 left left[0] = -1; for(int i = 1; i < heights.length; ++i) { int p = i - 1; while (p >= 0 && heights[p] >= heights[i]) { // --p; //这里不用每次都遍历,直接使用上次的结果就能够了 p = left[p]; } //设置这个最左边的坐标 left[i] = p; } //设置右边 right[heights.length - 1] = heights.length; for(int i = heights.length - 2; i >= 0; --i) { int p = i + 1; while (p < heights.length && heights[p] >= heights[i]) { // ++p; //这里不用每次都遍历,直接使用上次的结果就能够了 p = right[p]; } right[i] = p; } //求面积maxa = Math.max{maxa, heights[i] * (right[i] - left[i] - 1)} int maxa = 0; for(int i = 0; i < heights.length; ++i) { maxa = Math.max(maxa, heights[i] * (right[i] - left[i] - 1)); } return maxa; } public static void main(String args[]) { int data[] = {2,1,5,6,2,3}; LargestRectangleArea fuc = new LargestRectangleArea(); System.out.println(fuc.solution(data)); } }