持续更新中................
232. 用栈实现队列
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):①void push(int x) 将元素 x 推到队列的末尾;②int pop() 从队列的开头移除并返回元素;③int peek() 返回队列开头的元素;④boolean empty() 如果队列为空,返回 true ;否则,返回 false
class MyQueue {
Stack<Integer> stackIn;
Stack<Integer> stackOut;
public MyQueue() {
stackIn = new Stack<>();
stackOut = new Stack<>();
}
public void push(int x) {
stackIn.push(x);
}
public int pop() {
if(stackOut.isEmpty()){
while(!stackIn.isEmpty()){
stackOut.push(stackIn.pop());
}
}
return stackOut.pop();
}
public int peek() {
if(stackOut.isEmpty()){
while(!stackIn.isEmpty()){
stackOut.push(stackIn.pop());
}
}
return stackOut.peek();
}
public boolean empty() {
return stackIn.isEmpty() && stackOut.isEmpty();
}
}
225. 用队列实现栈
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty):①void push(int x) 将元素 x 压入栈顶;②int pop() 移除并返回栈顶元素。
③int top() 返回栈顶元素;④boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
//使用两个Queue
class MyStack {
Queue<Integer> queue1;
Queue<Integer> queue2;
public MyStack() {
queue1 = new LinkedList<>();
queue2 = new LinkedList<>();
}
public void push(int x) {
queue2.offer(x); // 先放在辅助队列中
while (!queue1.isEmpty()){
queue2.offer(queue1.poll());
}
Queue<Integer> queueTemp;
queueTemp = queue1;
queue1 = queue2; //将元素都放到queue1中
queue2 = queueTemp;
}
public int pop() {
return queue1.poll();
}
public int top() {
return queue1.peek();
}
public boolean empty() {
return queue1.isEmpty();
}
}
//使用一个Queue
class MyStack {
Queue<Integer> queue;
public MyStack() {
queue = new LinkedList<>();
}
public void push(int x) {
queue.offer(x);
int size = queue.size();
while(size > 1){
queue.offer(queue.poll());
size--;
}
}
public int pop() {
return queue.poll();
}
public int top() {
return queue.peek();
}
public boolean empty() {
return queue.isEmpty();
}
}
20. 有效的括号
给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。有效字符串需满足:①左括号必须用相同类型的右括号闭合;②左括号必须以正确的顺序闭合;③每个右括号都有一个对应的相同类型的左括号。
示例1:输入:s = "([]{})" 输出:true
示例2:输入:s = "([)]" 输出:false
class Solution {
public boolean isValid(String s) {
Deque<Character> deque = new LinkedList<>();
for(int i = 0; i < s.length(); i++){
char c = s.charAt(i);
if(c == '('){
deque.push(')');
}else if(c == '['){
deque.push(']');
}else if(c == '{'){
deque.push('}');
}else if(deque.isEmpty() || deque.pop() != c){
return false;
}
}
return deque.isEmpty();
}
}
1047. 删除字符串中的所有相邻重复项
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。在 S 上反复执行重复项删除操作,直到无法继续删除。在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例1:输入:"abbaca" 输出:"ca"
//执行用时141ms
class Solution {
public String removeDuplicates(String s) {
Deque<Character> deque = new ArrayDeque<>();
for(int i = 0; i < s.length(); i++){
char c = s.charAt(i);
if(deque.isEmpty() || deque.peek() != c){
deque.push(c);
}else{
deque.pop();
}
}
String result = "";
while(!deque.isEmpty()){
result = deque.pop() + result;
}
return result;
}
}
//执行用时10ms
class Solution {
public String removeDuplicates(String s) {
StringBuilder sb = new StringBuilder();
int top = -1;
for(int i = 0; i < s.length(); i++){
char c = s.charAt(i);
if(top == -1 || sb.charAt(top) != c){
sb.append(c);
top++;
}else{
sb.deleteCharAt(top);
top--;
}
}
return sb.toString();
}
}
//执行用时3ms
class Solution {
public String removeDuplicates(String s) {
char[] chars = s.toCharArray();
int slow = 0;
for(int fast = 0; fast < chars.length; fast++){
chars[slow] = chars[fast];
if(slow > 0 && chars[slow] == chars[slow - 1]){
slow--;
}else{
slow++;
}
}
return new String(chars, 0, slow);
}
}
150. 逆波兰表达式求值
据 逆波兰表示法,求表达式的值。有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。注意 两个整数之间的除法只保留整数部分。
示例1:输入:tokens = ["2","1","+","3","*"] 输出:9 解释:((2 + 1) * 3) = 9
示例2:输入:tokens = ["4","13","5","/","+"] 输出:6 解释:(4 + (13 / 5)) = 6
class Solution {
public int evalRPN(String[] tokens) {
Deque<Integer> deque = new LinkedList<>();
for(String s : tokens){
if("+".equals(s)){
deque.push(deque.pop() + deque.pop());
}else if("-".equals(s)){
deque.push(-deque.pop() + deque.pop());
}else if("*".equals(s)){
deque.push(deque.pop() * deque.pop());
}else if("/".equals(s)){
int temp1 = deque.pop();
int temp2 = deque.pop();
deque.push(temp2 / temp1);
}else{
deque.push(Integer.valueOf(s));
}
}
return deque.pop();
}
}
239. 滑动窗口最大值
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回 滑动窗口中的最大值 。
示例1:输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7]
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int[] result = new int[nums.length - k + 1];
int index = 0;
Deque<Integer> deque = new ArrayDeque<>(); //使用队列存储下标
for(int i = 0; i < nums.length; i++){
//在[i - k + 1, i] 中选到最大值
while(!deque.isEmpty() && deque.peek() < i - k + 1){
deque.poll();
}
//保证最大的数字一直在队列的第一个
while(!deque.isEmpty() && nums[deque.peekLast()] < nums[i]){
deque.pollLast();
}
deque.offer(i);
if(i >= k - 1){
result[index++] = nums[deque.peek()];
}
}
return result;
}
}
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int[] array = new int[nums.length - k + 1];
PriorityQueue<int[]> pq = new PriorityQueue<>((pari1, pari2) -> pari2[0] - pari1[0]);
for(int i = 0; i < k; i++){
pq.offer(new int[]{nums[i], i});
}
array[0] = pq.peek()[0];
for(int i = k; i < nums.length; i++){
pq.offer(new int[]{nums[i], i});
while(pq.peek()[1] < i - k + 1){
pq.poll();
}
array[i - k + 1] = pq.peek()[0];
}
return array;
}
}
347. 前K个高频元素
给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
示例1:输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2]
//大顶堆
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
for(int num : nums){
map.put(num, map.getOrDefault(num, 0) + 1);
}
//在优先队列中存储二元组(num,cnt),cnt表示元素值num在数组中的出现次数
//大顶堆在加入元素时需要对所有元素进行排序
PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2) -> pair2[1]-pair1[1]);
for(Map.Entry<Integer, Integer> entry : map.entrySet()){
pq.add(new int[]{entry.getKey(), entry.getValue()});
}
int[] result = new int[k];
for(int i = 0; i < k; i++){
result[i] = pq.poll()[0];
}
return result;
}
}
//小顶堆
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
for(int num : nums){
map.put(num, map.getOrDefault(num, 0) + 1);
}
//在优先队列中存储二元组(num,cnt),cnt表示元素值num在数组中的出现次数
//小顶堆只需要维持k个元素有序
PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2) -> pair1[1]-pair2[1]);
for(Map.Entry<Integer, Integer> entry : map.entrySet()){
if(pq.size() < k){
pq.add(new int[]{entry.getKey(), entry.getValue()});
}else{
if(entry.getValue() > pq.peek()[1]){
pq.poll();
pq.add(new int[]{entry.getKey(), entry.getValue()});
}
}
}
int[] result = new int[k];
for(int i = k-1; i >= 0; i--){
result[i] = pq.poll()[0];
}
return result;
}
}
用栈来实现LRU
public class LRU {
private int capacity;
private Stack<Integer> stack;
public LRU(int capacity) {
this.capacity = capacity;
stack = new Stack<>();
}
public int get(int key) {
if(stack.contains(key)) {
stack.removeElement(key);
stack.push(key);
return key;
}
return -1;
}
public void put(int key) {
if(stack.contains(key)) {
stack.removeElement(key);
}else if(stack.size() == capacity) {
stack.remove(0);
}
stack.push(key);
}
}