有效的括号#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,直到高度大于等于行数则加入到总量中。
//总共水量sum
int 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) {
//标记是否开始更新temp
boolean 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;
}
}