diff --git a/src/main/java/heap/FindKthLargest.java b/src/main/java/heap/FindKthLargest.java new file mode 100644 index 0000000..1e352f8 --- /dev/null +++ b/src/main/java/heap/FindKthLargest.java @@ -0,0 +1,50 @@ +package heap; + +import java.util.Comparator; +import java.util.PriorityQueue; + +/** + * 题目: 215. 数组中的第K个最大元素 (floodFill) + * 描述:给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。 + * 请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 + * 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 + + * 示例 1: + 输入: [3,2,1,5,6,4], k = 2 + 输出: 5 + + * 链接:https://leetcode.cn/problems/kth-largest-element-in-an-array/ + */ +public class FindKthLargest { + //完全填满堆再删除元素 最大堆 + public int findKthLargest1(int[] nums, int k) { + PriorityQueuemaxheap=new PriorityQueue<>(Comparator.reverseOrder()); + for (int num : nums) { + maxheap.add(num); + } + for (int i = 0; i < k-1; i++) { + maxheap.poll(); + } + return maxheap.peek(); + } + //使用最小堆来存储前 k 个最大的元素。堆顶元素是 k 个最大元素中的最小值。这样,堆的大小始终保持为 k。当堆的大小大于 k 时,弹出堆顶元素。最终堆顶元素就是第 k 大的元素。不需要完全填满堆再删除元素: + public int findKthLargest(int[] nums, int k) { + // 使用最小堆 + PriorityQueue minHeap = new PriorityQueue<>(); + + // 遍历数组 + for (int num : nums) { + // 如果堆的大小小于 k,直接加入元素 + if (minHeap.size() < k) { + minHeap.add(num); + } else if (num > minHeap.peek()) { + // 如果堆的大小已达到 k,且当前元素大于堆顶元素,则替换堆顶 + minHeap.poll(); + minHeap.add(num); + } + } + + // 返回堆顶元素,即为第 k 大的元素 + return minHeap.peek(); + } +} diff --git a/src/main/java/stack/Calculate2.java b/src/main/java/stack/Calculate2.java index e4a2dce..288bc7e 100644 --- a/src/main/java/stack/Calculate2.java +++ b/src/main/java/stack/Calculate2.java @@ -65,7 +65,7 @@ public class Calculate2 { Calculate2 calculator = new Calculate2(); // 测试用例 1 - String expression1 = "3+5/2"; + String expression1 = "3/2"; System.out.println("输入: " + expression1); System.out.println("输出: " + calculator.calculate(expression1)); // 期望输出 5 diff --git a/src/main/java/stack/EvalRPN.java b/src/main/java/stack/EvalRPN.java new file mode 100644 index 0000000..aff72b5 --- /dev/null +++ b/src/main/java/stack/EvalRPN.java @@ -0,0 +1,58 @@ +package stack; + +import java.util.ArrayDeque; +import java.util.Deque; + +/** + * 题目: 150. 逆波兰表达式求值 (evalRPN) + * 描述:给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。 + * 请你计算该表达式。返回一个表示表达式值的整数。 + * 注意: + * 有效的算符为 '+'、'-'、'*' 和 '/' 。 + * 每个操作数(运算对象)都可以是一个整数或者另一个表达式。 + * 两个整数之间的除法总是 向零截断 。 + * 表达式中不含除零运算。 + * 输入是一个根据逆波兰表示法表示的算术表达式。 + * + * 示例 1: + 输入:tokens = ["2","1","+","3","*"] + 输出:9 + 解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9 + + * 链接:https://leetcode.cn/problems/evaluate-reverse-polish-notation/ + */ +public class EvalRPN { + public int evalRPN(String[] tokens) { + Deque stack = new ArrayDeque<>(); + + for (String token : tokens) { + if (token.equals("+") || token.equals("-") || token.equals("*") || token.equals("/")) { + // 如果是运算符,出栈两个操作数进行运算 + int b = stack.pop(); + int a = stack.pop(); + int result = 0; + switch (token) { + case "+": + result = a + b; + break; + case "-": + result = a - b; + break; + case "*": + result = a * b; + break; + case "/": + result = a / b; // 除法自动向零取整 + break; + } + stack.push(result); + } else { + // 否则是数字,直接入栈 + stack.push(Integer.parseInt(token)); + } + } + + // 最后栈中只剩下一个数字,就是计算结果 + return stack.pop(); + } +} diff --git a/src/main/java/stack/LargestRectangleArea.java b/src/main/java/stack/LargestRectangleArea.java new file mode 100644 index 0000000..e61bdcc --- /dev/null +++ b/src/main/java/stack/LargestRectangleArea.java @@ -0,0 +1,109 @@ +package stack; + +import java.util.ArrayDeque; +import java.util.Deque; + +/** + * 题目: 84. 柱状图中最大的矩形 + * 描述:给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。 + * 求在该柱状图中,能够勾勒出来的矩形的最大面积。 + + * 示例 1: + 输入:heights = [2,1,5,6,2,3] + 输出:10 + 解释:最大的矩形为图中红色区域,面积为 10 + * + * 链接:https://leetcode.cn/problems/largest-rectangle-in-histogram/ + */ +//初见不会 +public class LargestRectangleArea { + //暴力法 依次遍历柱形的高度,对于每一个高度分别向两边扩散,求出以当前高度为矩形的最大宽度多少。 + public int largestRectangleArea1(int[] heights) { + int len = heights.length; + // 特判 + if (len == 0) { + return 0; + } + + int res = 0; + for (int i = 0; i < len; i++) { + + // 找左边最后 1 个大于等于 heights[i] 的下标 + int left = i; + int curHeight = heights[i]; + while (left > 0 && heights[left - 1] >= curHeight) { + left--; + } + + // 找右边最后 1 个大于等于 heights[i] 的索引 + int right = i; + while (right < len - 1 && heights[right + 1] >= curHeight) { + right++; + } + + int width = right - left + 1; + res = Math.max(res, width * curHeight); + } + return res; + } + //动态规划 暴力解优化 + public int largestRectangleArea2(int[] heights) { + int size = heights.length; + int[] minLeftIndex = new int[size]; + int[] minRightIndex = new int[size]; + + // 记录每个柱子左边第一个小于该柱子的下标 + minLeftIndex[0] = -1; // 初始化,防止死循环 + for (int i = 1; i < size; i++) { + int t = i - 1; + // 不断向左寻找,直到找到第一个小于当前柱子的柱子 + while (t >= 0 && heights[t] >= heights[i]) { + t = minLeftIndex[t]; // 更新为左边第一个小于当前柱子的下标 + } + minLeftIndex[i] = t; + } + + // 记录每个柱子右边第一个小于该柱子的下标 + minRightIndex[size - 1] = size; // 初始化,防止死循环 + for (int i = size - 2; i >= 0; i--) { + int t = i + 1; + // 不断向右寻找,直到找到第一个小于当前柱子的柱子 + while (t < size && heights[t] >= heights[i]) { + t = minRightIndex[t]; // 更新为右边第一个小于当前柱子的下标 + } + minRightIndex[i] = t; + } + + // 计算最大矩形面积 + int result = 0; + for (int i = 0; i < size; i++) { + int width = minRightIndex[i] - minLeftIndex[i] - 1; + int area = heights[i] * width; + result = Math.max(result, area); + } + + return result; + } + //单调栈 + public int largestRectangleArea(int[] heights) { + Dequestack=new ArrayDeque<>(); + int max=Integer.MIN_VALUE; + stack.push(-1); + for (int i = 0; i < heights.length; i++) { + while(stack.size()>=2 && heights[i]=2){ + int cur=stack.pop(); + int width=heights.length-stack.peek()-1; + if(maxstack=new ArrayDeque<>(); + HashMapmap=new HashMap<>(); + int[] res=new int[nums1.length]; + for (int cur : nums2) { + while (!stack.isEmpty()) { + int curtop = stack.peek(); + if (cur > curtop) { + stack.pop(); + map.put(curtop, cur); + }else break; + } + stack.push(cur); + } + while (!stack.isEmpty()) { + map.put(stack.pop(),-1); + } + for (int i = 0; i < nums1.length; i++) { + res[i]=map.get(nums1[i]); + } + return res; + } +} diff --git a/src/main/java/stack/NextGreaterElements.java b/src/main/java/stack/NextGreaterElements.java new file mode 100644 index 0000000..8375d61 --- /dev/null +++ b/src/main/java/stack/NextGreaterElements.java @@ -0,0 +1,48 @@ +package stack; + +import java.util.ArrayDeque; +import java.util.Deque; + +/** + * 题目: 503. 下一个更大元素 II (nextGreaterElements) + * 描述:给定一个循环数组 nums ( nums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素 。 + * 数字 x 的 下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1 。 + *

+ * 示例 1: + * 输入: nums = [1,2,1] + * 输出: [2,-1,2] + * 解释: 第一个 1 的下一个更大的数是 2; + * 数字 2 找不到下一个更大的数; + * 第二个 1 的下一个最大的数需要循环搜索,结果也是 2。 + *

+ * 链接:https://leetcode.cn/problems/next-greater-element-ii/description/ + */ +//不会,学习! +public class NextGreaterElements { + public int[] nextGreaterElements(int[] nums) { + int n = nums.length; + int[] result = new int[n]; + Deque stack = new ArrayDeque<>(); + + // 初始化结果数组为 -1,表示如果没有更大元素则为 -1 + for (int i = 0; i < n; i++) { + result[i] = -1; + } + + // 遍历数组两倍的长度,以模拟循环 + for (int i = 0; i < 2 * n; i++) { + int currentIndex = i % n; // 当前元素的下标,模拟循环 + // 当栈不为空且当前元素大于栈顶对应的元素时,更新结果 + while (!stack.isEmpty() && nums[currentIndex] > nums[stack.peek()]) { + int prevIndex = stack.pop(); + result[prevIndex] = nums[currentIndex]; + } + // 只在前 n 个元素时将索引加入栈中 + if (i < n) { + stack.push(currentIndex); + } + } + + return result; + } +} diff --git a/src/main/java/stack/Trap.java b/src/main/java/stack/Trap.java new file mode 100644 index 0000000..9a8933b --- /dev/null +++ b/src/main/java/stack/Trap.java @@ -0,0 +1,101 @@ +package stack; + +import java.util.Deque; +import java.util.LinkedList; + +/** + * 题目: 42. 接雨水 (trap) + * 描述:给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 + + * 示例 1: + * 输入:height = [0,1,0,2,1,0,1,3,2,1,2,1] + * 输出:6 + * 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 + * + * 链接:https://leetcode.cn/problems/trapping-rain-water/ + */ +//困难题 不会 +public class Trap { + //暴力解法 + public int trap1(int[] height) { + int sum = 0; + for (int i = 0; i < height.length; i++) { + // 第一个柱子和最后一个柱子不接雨水 + if (i == 0 || i == height.length - 1) { + continue; + } + + int rHeight = height[i]; // 记录右边柱子的最高高度 + int lHeight = height[i]; // 记录左边柱子的最高高度 + + for (int r = i + 1; r < height.length; r++) { + if (height[r] > rHeight) { + rHeight = height[r]; + } + } + for (int l = i - 1; l >= 0; l--) { + if (height[l] > lHeight) { + lHeight = height[l]; + } + } + + int h = Math.min(lHeight, rHeight) - height[i]; + if (h > 0) { + sum += h; + } + } + return sum; + } + //动态规划 + public int trap2(int[] height) { + if (height.length <= 2) return 0; + int n = height.length; + int[] maxLeft = new int[n]; + int[] maxRight = new int[n]; + + // 记录每个柱子左边柱子最大高度 + maxLeft[0] = height[0]; + for (int i = 1; i < n; i++) { + maxLeft[i] = Math.max(height[i], maxLeft[i - 1]); + } + + // 记录每个柱子右边柱子最大高度 + maxRight[n - 1] = height[n - 1]; + for (int i = n - 2; i >= 0; i--) { + maxRight[i] = Math.max(height[i], maxRight[i + 1]); + } + + // 求和 + int sum = 0; + for (int i = 1; i < n-1; i++) { + int count = Math.min(maxLeft[i-1], maxRight[i+1]) - height[i]; + if (count > 0) { + sum += count; + } + } + return sum; + } + + //单调栈 + public int trap(int[] height) { + int sum = 0; + Deque stack = new LinkedList<>(); + + for (int i = 0; i < height.length; i++) { + // 当栈不为空且当前柱子的高度大于栈顶柱子的高度时 + while (!stack.isEmpty() && height[i] > height[stack.peek()]) { + int top = stack.pop(); + // 如果栈为空,则没有左边的柱子来接雨水 + if (stack.isEmpty()) break; + // 计算当前柱子与栈顶柱子之间的距离 + int distance = i - stack.peek() - 1; + // 计算可以接的雨水高度:两边较低的高度减去中间柱子的高度 + int boundedHeight = Math.min(height[i], height[stack.peek()]) - height[top]; + sum += distance * boundedHeight; + } + // 将当前索引入栈 + stack.push(i); + } + return sum; + } +} diff --git a/src/test/java/stack/EvalRPNTest.java b/src/test/java/stack/EvalRPNTest.java new file mode 100644 index 0000000..94ba3b8 --- /dev/null +++ b/src/test/java/stack/EvalRPNTest.java @@ -0,0 +1,16 @@ +package stack; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class EvalRPNTest { + + @Test + public void evalRPN() { + String[] tokens = {"4","-2","/","2","-3","-","-"}; + EvalRPN solution = new EvalRPN(); + int res=solution.evalRPN(tokens); + System.out.println(res); + } +} \ No newline at end of file diff --git a/src/test/java/stack/LargestRectangleAreaTest.java b/src/test/java/stack/LargestRectangleAreaTest.java new file mode 100644 index 0000000..c73bd24 --- /dev/null +++ b/src/test/java/stack/LargestRectangleAreaTest.java @@ -0,0 +1,16 @@ +package stack; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class LargestRectangleAreaTest { + + @Test + public void largestRectangleArea() { + LargestRectangleArea solution = new LargestRectangleArea(); + int[] heights = {2,1,5,6,2,3}; + int res=solution.largestRectangleArea(heights); + System.out.println(res); + } +} \ No newline at end of file diff --git a/src/test/java/stack/NextGreaterElementTest.java b/src/test/java/stack/NextGreaterElementTest.java new file mode 100644 index 0000000..c834913 --- /dev/null +++ b/src/test/java/stack/NextGreaterElementTest.java @@ -0,0 +1,19 @@ +package stack; + +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.*; + +public class NextGreaterElementTest { + + @Test + public void nextGreaterElement() { + NextGreaterElement solution = new NextGreaterElement(); + int[] nums1 = {4,1,2}; + int[] nums2 = {1,3,4,2}; + int[] res=solution.nextGreaterElement(nums1,nums2); + System.out.println(Arrays.toString(res)); + } +} \ No newline at end of file diff --git a/src/test/java/stack/NextGreaterElementsTest.java b/src/test/java/stack/NextGreaterElementsTest.java new file mode 100644 index 0000000..ff08512 --- /dev/null +++ b/src/test/java/stack/NextGreaterElementsTest.java @@ -0,0 +1,18 @@ +package stack; + +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.*; + +public class NextGreaterElementsTest { + + @Test + public void nextGreaterElements() { + NextGreaterElements solution = new NextGreaterElements(); + int[] nums = {1,2,3,2,1}; + int []res=solution.nextGreaterElements(nums); + System.out.println(Arrays.toString(res)); + } +} \ No newline at end of file