有效的括号#20(简单)
class Solution {public boolean isValid(String s) {//法一:哈希表+栈.时间复杂度O(n),空间复杂度O(n)int n = s.length();if (n % 2 == 1) return false;Map<Character, Character> pairs = new HashMap<>();pairs.put(')', '(');pairs.put(']', '[');pairs.put('}', '{');Deque<Character> stack = new LinkedList<>();for (int i = 0; i < n; i++) {char ch = s.charAt(i);if (pairs.containsKey(ch)) {if (stack.isEmpty() || stack.peek() != pairs.get(ch)) {return false;}stack.pop();} else {stack.push(ch);}}return stack.isEmpty();}}//==================================================class Solution {public boolean isValid(String s) {//法二:ASCII码+栈.时间复杂度O(n),空间复杂度O(n)int n = s.length();if (n % 2 == 1) return false;Deque<Character> stack = new LinkedList<>();stack.push(s.charAt(0));for (int i = 1; i < n; i++) {char ch = s.charAt(i);if (stack.isEmpty()) {stack.push(ch);} else if (ch - stack.peek() == 1 || ch - stack.peek() == 2) {stack.pop();} else {stack.push(ch);}}return stack.isEmpty();}}
最长有效括号#32(困难)
class Solution {public int longestValidParentheses(String s) {//法二:栈.时间复杂度O(n),空间复杂度O(n)int maxans = 0;Deque<Integer> stack = new LinkedList<>();stack.push(-1);for (int i = 0; i < s.length(); i++) {if (s.charAt(i) == '(') {stack.push(i);} else {stack.pop();if (stack.isEmpty()) {stack.push(i);} else {maxans = Math.max(maxans, i - stack.peek());}}}return maxans;}}
接雨水#42(困难)
public int trap(int[] height) {//该解法超时了❌//法一:按行求.求出每一行接水量,然后累加//时间复杂度O(m*n),m是最大高度,n是数组长度。约等于n^2所以会超时。//空间复杂度O(1)。//当出现第一个高度大于等于行数的开始更新,//之后高度小于行数则接水量+1,直到高度大于等于行数则加入到总量中。//总共水量sumint sum = 0;//先求出最大高度,也即是行数,也就是最外层循环的次数int maxHeight = 0;for (int i = 0; i < height.length; i++) {maxHeight = maxHeight > height[i] ? maxHeight : height[i];}//最外层循环,求每一层的积水量for (int i = 1; i <= maxHeight; ++i) {//标记是否开始更新tempboolean isStart = false;int temp = 0;for (int j = 0; j < height.length; ++j) {if (isStart && height[j] < i) {temp++;}if (height[j] >= i) {sum += temp;temp = 0;isStart = true;}}}return sum;}public int trap(int[] height) {//法二:按列求。时间复杂度O(n^2),空间复杂度O(1)int sum = 0;//最两边的列是没有办法接到水的for (int i = 1; i < height.length - 1; i++) {//找出左边的最高棒子int maxLeft = 0;for (int j = i - 1; j >= 0; --j) {if (height[j] > maxLeft) {maxLeft = height[j];}}//找出右边最高的棒子int maxRight = 0;for (int j = i + 1; j < height.length; ++j) {//本来想三目运算符一句话写完。但是每一次三目运算符都有赋值运算。还是觉得这样更好if (height[j] > maxRight) {maxRight = height[j];}}//找出两端最小值int minHeight = Math.min(maxLeft, maxRight);if (minHeight > height[i]) {sum = sum + (minHeight - height[i]);}}return sum;}public int trap(int[] height) {//法三:动态规划。利用两个数组记录当前列的左边最高和右边最高。//时间复杂度O(n),空间复杂度O(n)int sum = 0;int n = height.length;int[] maxLeftArray = new int[n];int[] maxRightArray = new int[n];//求出左边最高列数组for (int i = 1; i < n; i++) {maxLeftArray[i] = Math.max(maxLeftArray[i - 1], height[i - 1]);}//求出右边最高列的数组for (int i = n - 2; i > 0; --i) {maxRightArray[i] = Math.max(maxRightArray[i + 1], height[i + 1]);}for (int i = 1; i < n - 1; ++i) {int minHeight = Math.min(maxLeftArray[i], maxRightArray[i]);if (minHeight > height[i]) {sum += minHeight - height[i];}}return sum;}public int trap(int[] height) {//法四:双指针。时间复杂度O(n),空间复杂度O(1)int n = height.length;int sum = 0;int maxLeft = 0;int maxRight = 0;int left = 1;int right = n - 2;//加右指针进去for (int i = 1; i < n - 1; i++) {//对于左边,左边最高是可信的,对于右边,右边最高是可信的//所以左边最高小于右边最高时就可以确定自己能装多少水了if (height[left - 1] < height[right + 1]) {//从左到右更新maxLeft = Math.max(maxLeft, height[left - 1]);int min = maxLeft;if (min > height[left]) {sum = sum + (min - height[left]);}left++;} else {//从右到左更新maxRight = Math.max(maxRight, height[right + 1]);int min = maxRight;if (min > height[right]) {sum = sum + (min - height[right]);}right--;}}return sum;}public int trap(int[] height) {//法五:单调栈。时间复杂度O(n),空间复杂度O(n)int sum = 0;Deque<Integer> stack = new LinkedList<>();int n = height.length;for (int i = 0; i < n; ++i) {while (!stack.isEmpty() && height[i] > height[stack.peek()]) {int top = stack.pop();if (stack.isEmpty()) {break;}int left = stack.peek();int currWidth = i - left - 1;int currHeight = Math.min(height[left], height[i]) - height[top];sum += currWidth * currHeight;}stack.push(i);}return sum;}
简化路径#71(中等)
class Solution {
public String simplifyPath(String path) {
//法一:栈。时间复杂度O(n),空间复杂度O(n)
//注意Deque的push和pop操作都是操作的头,所以只能用queue的api
String[] names = path.split("/");
Deque<String> stack = new ArrayDeque<>();
for (String name : names) {
if ("..".equals(name)) {
if (!stack.isEmpty()) stack.pollLast();
} else if (name.length() > 0 && !".".equals(name)) {
stack.offerLast(name);
}
}
StringBuilder ans = new StringBuilder();
if (stack.isEmpty()) {
ans.append('/');
} else {
while (!stack.isEmpty()) {
ans.append('/');
ans.append(stack.pollFirst());
}
}
return ans.toString();
}
}
柱状图中最大的矩形#84(困难)
https://leetcode.cn/problems/largest-rectangle-in-histogram/
public int largestRectangleArea(int[] heights) {
//该解法超时了❌
//法一:枚举宽度的暴力解法.时间复杂度O(n^2),空间复杂度O(1)
int length = heights.length;
int maxArea = 0;
for (int i = 0; i < length; ++i) {
int minHeight = Integer.MAX_VALUE;
for (int j = i; j < length; ++j) {
minHeight = Math.min(minHeight, heights[j]);
maxArea = Math.max(maxArea, minHeight * (j - i + 1));
}
}
return maxArea;
}
//===============================================================
public int largestRectangleArea(int[] heights) {
//该解法超时了❌
//法二:枚举高度暴力解法.时间复杂度O(n^2),空间复杂度O(1)
int length = heights.length;
int maxArea = 0;
for (int mid = 0; mid < length; mid++) {
int height = heights[mid];
int left = mid;
int right = mid;
while (left - 1 >= 0 && heights[left-1] >= height) {
--left;
}
while (right + 1 < length && heights[right+1] >= height) {
++right;
}
maxArea = Math.max(maxArea, height * (right - left + 1));
}
return maxArea;
}
//===============================================================
class Solution {
public int largestRectangleArea(int[] heights) {
//法三:单调栈+两次遍历.时间复杂度O(n),空间复杂度O(n)
int n = heights.length;
int[] left = new int[n];
int[] right = new int[n];
Deque<Integer> mono_stack = new ArrayDeque<>();
for (int i = 0; i < n; i++) {
while (!mono_stack.isEmpty() && heights[mono_stack.peek()] >= heights[i]) {
mono_stack.pop();
}
left[i] = (mono_stack.isEmpty() ? -1 : mono_stack.peek());
mono_stack.push(i);
}
mono_stack.clear();
for (int i = n - 1; i >= 0; i--) {
while (!mono_stack.isEmpty() && heights[mono_stack.peek()] >= heights[i]) {
mono_stack.pop();
}
right[i] = (mono_stack.isEmpty() ? n : mono_stack.peek());
mono_stack.push(i);
}
int ans = 0;
for (int i = 0; i < n; i++) {
ans = Math.max(ans, (right[i] - left[i] - 1) * heights[i]);
}
return ans;
}
}
//===============================================================
class Solution {
public int largestRectangleArea(int[] heights) {
//法四:单调栈+一次遍历.时间复杂度O(n),空间复杂度O(n)
int n = heights.length;
int[] left = new int[n];
int[] right = new int[n];
Arrays.fill(right, n);
Deque<Integer> mono_stack = new ArrayDeque<>();
for (int i = 0; i < n; i++) {
while (!mono_stack.isEmpty() && heights[mono_stack.peek()] >= heights[i]) {
right[mono_stack.peek()] = i;
mono_stack.pop();
}
left[i] = (mono_stack.isEmpty() ? -1 : mono_stack.peek());
mono_stack.push(i);
}
int ans = 0;
for (int i = 0; i < n; i++) {
ans = Math.max(ans, (right[i] - left[i] - 1) * heights[i]);
}
return ans;
}
}
