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)); } }