【LeetCode】Sama的个人记录_15

【Q287】(hd) 柱状图中最大的矩形
 
给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
 
求在该柱状图中,能够勾勒出来的矩形的最大面积。
在这里插入图片描述
以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]。
在这里插入图片描述
图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位。
 
示例:

    输入: [2,1,5,6,2,3] 输出: 10

class Solution {
	/*
	 * 【暴力法——中心扩散】
	 * 
	 * 关键思路:以此时的heights[i]为固定的高h,只要两侧比内部高,宽度w就向外扩散1(w初始值为1)
	 * 
	 * 每次遍历到某个高度,其意义是:完全覆盖第i根柱子(从0开始)的最大矩形面积
	 */
    public int largestRectangleArea(int[] heights) {
    	int len = heights.length;
    	int maxArea = 0;
    	for(int i = 0; i < len; i++) {
    		int h = heights[i];
    		int w = 1;
    		int j = i - 1;
    		int k = i+ 1;
    		while(j >= 0 && heights[j] >= heights[i]) {
    			w++;
    			j--;
    		}
    		while(k < len && heights[k] >= heights[i]) {
    			w++;
    			k++;
    		}
    		maxArea = Math.max(maxArea, w * h);
    	}
    	return maxArea;
    }
    // for的内部有O(n)的while,总的时间复杂度为O(n²)所以称为暴力法
    // ~~其实不是特别暴力~~ 
}
class Solution_84_2 {
	/*
	 * 【单调栈】
	 * 解该题的关键点是不变的:以某个位置的高度为中心,向两边扩散,直到被比它严格小的柱子挡住
	 * 在暴力法中,我们通过时间复杂度为O(n)的while来寻找某个高度,的左边和右边"第一个严格小于它的柱子"
	 * 有没有可能对这个"找左右第一个严格小的柱子"的方法进行优化呢?
	 * 
	 * 下面引入【单调栈】
	 *	1.单调栈分为单调递增栈和单调递减栈
	 *	11. 单调递增栈即栈内元素保持单调递增的栈
	 *	12. 单调递减栈即栈内元素保持单调递减的栈
	 *
	 *	2.操作规则(★☆★)(下面都以单调递增栈为例)
	 *	21. 如果新的元素比栈顶元素大(或等于),就入栈
	 *	22. 如果新的元素较小,那就一直把栈内元素弹出来,直到栈顶比新元素小
	 *
	 *	3.加入这样一个规则之后,会有什么效果(一定要理解!!)
	 *	31. 栈内的元素总是是递增的
	 *	32. 新元素导致出栈时,说明该新元素是出栈元素右边第一个严格小于它的
	 *	33. 新元素导致出栈时,出栈一次后,此时栈顶的元素是刚刚出栈的元素左边第一个严格小于它的
	 *
	 *
	 *【补充细节】
	 * 1.单调栈不是严格单调的,比如[1, 3, 5, 5, 9]
	 * 2.单调栈中存的是下标而不是高度,因为出栈时还要根据下标计算宽度
	 * 3.触发出栈的条件是,此时遍历到的元素严格小于栈顶元素
	 * 4.单调栈需要两个【哨兵】,即在原数组的基础上,左端加0,右端加0:
	 * 		左端加0是为了,划定左边界,因为高度0只能被peek使用到,而不可能被pop掉
	 * 		右端加0是为了,保证栈中所有高度都能被pop掉(除了左右0),毕竟它是0,作为右边界清空掉栈的残余
	 *
	 */
    public int largestRectangleArea(int[] heights) {
    	Deque<Integer> stack = new ArrayDeque<>();
    	int len = heights.length;
    	int[] arr = new int[len + 2];		
    	int maxArea = 0;
    	System.arraycopy(heights, 0, arr, 1, len);		// 数组补0【哨兵】
    	for(int i = 0; i < arr.length; i++) {
    		while(!stack.isEmpty() && arr[i] < arr[stack.peek()]) {
    			int h = arr[stack.pop()];			// 此时栈顶的下标对应的高度,它左边和右边“严格小于”它的柱子,已经确定
    			int w = i - stack.peek() -1;		// i是右边第一个严格小于的柱子,stack.peek()是左边第一个小于的柱子;矩形在它们之间(不包括它们,它们只是"限制")
    			maxArea = Math.max(maxArea, h * w);
    		}
    		stack.push(i);	// 不要忘了包把此时的i入栈(经过上面的出栈,它完全可保证使单调栈是单调增的)
    	}
    	return maxArea;
    }
    // 线性的时间复杂度O(n)
}

【Q101】(ez) 对称二叉树
 
给定一个二叉树,检查它是否是镜像对称的。
 
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

 		1   
  	   / \   
      2   2  
     / \ / \ 
    3  4 4  3  

但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:

	   1    
  	  / \  
     2   2  
      \   \   
       3    3  

进阶: 你可以运用递归和迭代两种方法解决这个问题吗?

class Solution {
	/*
	 * 【递归】
	 * 1.终止条件有两种
	 * 2.返回值表达式有点长
	 */
    public boolean isSymmetric(TreeNode root) {
    	return judge(root, root);	// 这个填入两个根节点的写法太巧妙了
        
    }
    private boolean judge(TreeNode node1, TreeNode node2) {	 //node1和node2永远可以保证是位置对称的两个节点
    	if(node1 == null && node2 == null) {	// 当两个节点都是null时,作为递归终止条件,返回true
    		return true;
    	}
    	if(node1 == null || node2 == null) {	// 接着上一个if的语义,当两个节点的其中一个是null时,递归终止,返回false;
    		return false;						// 其实这一句是为了保证下面的node.left和node.right都存在
    	}
    	return node1.val == node2.val && judge(node1.left, node2.right) && judge(node1.right, node2.left);
    	// 位置对称的节点的值相同 && 位置对称的这两个节点,子节点也满足
    }
}
lass Solution {
	/*
	 * 【迭代】
	 * 1.递归改为迭代的方法,通常就是利用一个辅助队列
	 * 2.每次进队两个节点,这两个节点是位置对称的;取出的时候它们也成对取出(!关键)
	 */
	public boolean isSymmetric(TreeNode root) {
		return judge(root, root);
		// 其实这里写成:
		// if(root == null)	 return false;
		// return judge(root.left, root.right)会更好
	}
	private boolean judge(TreeNode node1, TreeNode node2) {
		Queue<TreeNode> queue = new LinkedList<TreeNode>();
		queue.offer(node1);
		queue.offer(node2);
		while(!queue.isEmpty()) {
			TreeNode p = queue.poll();
			TreeNode q = queue.poll();
			if(p == null && q == null) {
				continue;
			}
			if((p == null || q ==null) || p.val != q.val) {
				return false;
			}
			queue.offer(p.left);
			queue.offer(q.right);
			queue.offer(p.right);
			queue.offer(q.left);
		}
		return true;
	}
}

 
 

Qs from https://leetcode-cn.com
♦ loli suki
♥ end

猜你喜欢

转载自blog.csdn.net/m0_46202073/article/details/106451766
今日推荐