3.29 二分查找+栈
This commit is contained in:
parent
a41a72c55b
commit
282edf97ec
53
src/main/java/binary_search/FindMin.java
Normal file
53
src/main/java/binary_search/FindMin.java
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package binary_search;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 题目: 153. 寻找旋转排序数组中的最小值 (findMin)
|
||||||
|
* 描述:已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
|
||||||
|
* 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
|
||||||
|
* 若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
|
||||||
|
* 注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。
|
||||||
|
* 给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
|
||||||
|
* 你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。
|
||||||
|
* <p>
|
||||||
|
* 示例 1:
|
||||||
|
* 输入:nums = [3,4,5,1,2]
|
||||||
|
* 输出:1
|
||||||
|
* 解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。
|
||||||
|
* <p>
|
||||||
|
* 链接:https://leetcode.cn/problems/find-minimum-in-rotated-sorted-array/
|
||||||
|
*/
|
||||||
|
public class FindMin {
|
||||||
|
/**
|
||||||
|
* 判断区间是否已经有序
|
||||||
|
*
|
||||||
|
* 如果当前区间(由 left 到 right)是有序的(即 nums[left] < nums[right]),说明这个区间没有发生旋转,最小值一定是区间的第一个元素 nums[left],所以直接返回它。
|
||||||
|
* 计算中间索引
|
||||||
|
*
|
||||||
|
* 使用 int mid = left + (right - left) / 2; 计算中间索引,避免直接相加可能造成的溢出问题。
|
||||||
|
* 判断最小值在哪个区间
|
||||||
|
*
|
||||||
|
* 左侧有序情况:如果 nums[mid] >= nums[left],说明从 left 到 mid 是有序的,此时最小值不可能出现在有序部分,所以最小值一定在右半部分,因此更新 left = mid + 1。
|
||||||
|
* 旋转点在左侧情况:如果 nums[mid] < nums[left],说明中间部分处于旋转状态,即最小值可能出现在左半部分或就是 nums[mid],因此将 right 更新为 mid。
|
||||||
|
* 退出条件
|
||||||
|
*
|
||||||
|
* 循环在 left == right 时退出,此时 nums[left] 就是整个数组的最小值。
|
||||||
|
* @param nums
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int findMin(int[] nums) {
|
||||||
|
int left = 0, right = nums.length - 1;
|
||||||
|
while (left < right) {
|
||||||
|
if (nums[left] < nums[right]) {
|
||||||
|
return nums[left];
|
||||||
|
}
|
||||||
|
int mid = left + (right - left) / 2;
|
||||||
|
if (nums[mid] >= nums[left]) {
|
||||||
|
left = mid + 1;
|
||||||
|
} else {
|
||||||
|
right = mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nums[left];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
package binary_search;
|
package binary_search;
|
||||||
/**
|
/**
|
||||||
* 题目: 33. 搜索旋转排序数组 (searchRange)
|
* 题目: 33. 搜索旋转排序数组 (search)
|
||||||
* 描述:整数数组 nums 按升序排列,数组中的值 互不相同 。
|
* 描述:整数数组 nums 按升序排列,数组中的值 互不相同 。
|
||||||
* 在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
|
* 在传递给函数之前,nums 在预先未知的某个下标 k(0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。
|
||||||
* 给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。
|
* 给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。
|
||||||
|
19
src/main/java/stack/DecodeString.java
Normal file
19
src/main/java/stack/DecodeString.java
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package stack;
|
||||||
|
/**
|
||||||
|
* 题目: 394. 字符串解码 (decodeString)
|
||||||
|
* 描述:给定一个经过编码的字符串,返回它解码后的字符串。
|
||||||
|
* 编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
|
||||||
|
* 你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
|
||||||
|
* 此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
|
||||||
|
|
||||||
|
* 示例 1:
|
||||||
|
输入:s = "3[a]2[bc]"
|
||||||
|
输出:"aaabcbc"
|
||||||
|
|
||||||
|
* 链接:https://leetcode.cn/problems/search-in-rotated-sorted-array/
|
||||||
|
*/
|
||||||
|
public class DecodeString {
|
||||||
|
public String decodeString(String s) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
51
src/main/java/stack/IsValid.java
Normal file
51
src/main/java/stack/IsValid.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package stack;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Deque;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 题目: 20. 有效的括号 (isValid)
|
||||||
|
* 描述:给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
|
||||||
|
*
|
||||||
|
* 有效字符串需满足:
|
||||||
|
*
|
||||||
|
* 左括号必须用相同类型的右括号闭合。
|
||||||
|
* 左括号必须以正确的顺序闭合。
|
||||||
|
* 每个右括号都有一个对应的相同类型的左括号。
|
||||||
|
*
|
||||||
|
* 链接:https://leetcode.cn/problems/valid-parentheses/
|
||||||
|
*/
|
||||||
|
public class IsValid {
|
||||||
|
public boolean isValid(String s) {
|
||||||
|
// 如果长度为奇数,直接返回 false
|
||||||
|
int sz = s.length();
|
||||||
|
if (sz % 2 == 1) return false;
|
||||||
|
|
||||||
|
// 映射括号
|
||||||
|
HashMap<Character, Character> map = new HashMap<>();
|
||||||
|
map.put('(', ')');
|
||||||
|
map.put('[', ']');
|
||||||
|
map.put('{', '}');
|
||||||
|
|
||||||
|
Deque<Character> stack = new ArrayDeque<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < sz; i++) {
|
||||||
|
char cur = s.charAt(i);
|
||||||
|
|
||||||
|
// 如果是左括号,压入栈
|
||||||
|
if (map.containsKey(cur)) {
|
||||||
|
stack.push(cur);
|
||||||
|
}
|
||||||
|
// 如果是右括号,检查栈顶是否是匹配的左括号
|
||||||
|
else {
|
||||||
|
if (stack.isEmpty() || map.get(stack.pop()) != cur) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最后栈应为空
|
||||||
|
return stack.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
56
src/main/java/stack/MinStack.java
Normal file
56
src/main/java/stack/MinStack.java
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package stack;
|
||||||
|
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 题目: 155. 最小栈 (MinStack)
|
||||||
|
* 描述:设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
|
||||||
|
*
|
||||||
|
* 实现 MinStack 类:
|
||||||
|
* MinStack() 初始化堆栈对象。
|
||||||
|
* void push(int val) 将元素val推入堆栈。
|
||||||
|
* void pop() 删除堆栈顶部的元素。
|
||||||
|
* int top() 获取堆栈顶部的元素。
|
||||||
|
* int getMin() 获取堆栈中的最小元素。
|
||||||
|
*
|
||||||
|
* 链接:https://leetcode.cn/problems/min-stack/description/
|
||||||
|
*/
|
||||||
|
public class MinStack {
|
||||||
|
|
||||||
|
private Stack<Integer> stack; // 主栈
|
||||||
|
private Stack<Integer> minStack; // 辅助栈,存储每个阶段的最小值
|
||||||
|
|
||||||
|
public MinStack() {
|
||||||
|
stack = new Stack<>();
|
||||||
|
minStack = new Stack<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 向栈中压入一个值
|
||||||
|
public void push(int val) {
|
||||||
|
stack.push(val);
|
||||||
|
// 如果辅助栈为空,或者当前值比辅助栈的栈顶元素还小,压入辅助栈
|
||||||
|
if (minStack.isEmpty() || val <= minStack.peek()) {
|
||||||
|
minStack.push(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 弹出栈顶元素
|
||||||
|
public void pop() {
|
||||||
|
// 弹出主栈的栈顶元素
|
||||||
|
int poppedValue = stack.pop();
|
||||||
|
// 如果弹出的元素是当前最小值,则同时弹出辅助栈的栈顶元素
|
||||||
|
if (poppedValue == minStack.peek()) {
|
||||||
|
minStack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取栈顶元素
|
||||||
|
public int top() {
|
||||||
|
return stack.peek();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前栈中的最小值
|
||||||
|
public int getMin() {
|
||||||
|
return minStack.peek();
|
||||||
|
}
|
||||||
|
}
|
16
src/test/java/stack/DecodeStringTest.java
Normal file
16
src/test/java/stack/DecodeStringTest.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package stack;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class DecodeStringTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void decodeString() {
|
||||||
|
String s = "3[a]2[bc]";
|
||||||
|
DecodeString solution = new DecodeString();
|
||||||
|
String res=solution.decodeString(s);
|
||||||
|
System.out.println(res);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user