스택 및 대기열
스택
2 개의 대기열로 스택 구현
https://leetcode-cn.com/problems/implement-stack-using-queues/
class MyStack {
Queue<Integer> queue1; // 对外输出
Queue<Integer> queue2; // 对内输入
/** Initialize your data structure here. */
public MyStack() {
queue1 = new LinkedList<Integer>();
queue2 = new LinkedList<Integer>();
}
/** Push element x onto stack. */
public void push(int x) {
queue2.offer(x);
while (!queue1.isEmpty()) {
// 核心就是让后入变成先入,最后操作的在offer处插队成为首个,过去插队维护的再输入进来即可
queue2.offer(queue1.poll());
}
Queue<Integer> temp = queue1;
queue1 = queue2;
queue2 = temp;
}
/** Removes the element on top of the stack and returns that element. */
public int pop() {
return queue1.poll();
}
/** Get the top element. */
public int top() {
return queue1.peek();
}
/** Returns whether the stack is empty. */
public boolean empty() {
return queue1.isEmpty();
}
}
439. 삼항식 파서
https://leetcode-cn.com/problems/ternary-expression-parser/
핵심:
- Character.isDigit이 숫자를 판단합니다.
- 판정 처리 (스태킹 및 팝핑)의 표시는 무엇입니까? 그리고 누가 스택에 가고 나중에 스택에서 나 가든 마지막 남은 것은 답입니다.
단 한 번의 순회 만 필요합니다.
71. 경로 단순화
class Solution {
public String simplifyPath(String path) {
String[] strings = path.split("/");
Stack<String> stack = new Stack<>();
for(String str : strings) {
if(str.isEmpty() || str.equalsIgnoreCase(".") || str.equalsIgnoreCase("/")) {
continue;
}
if(str.equalsIgnoreCase("..")) {
if(!stack.isEmpty()) {
stack.pop();
}
continue;
}
stack.push(str);
}
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("/");
for(String str : stack) {
stringBuilder.append(str);
stringBuilder.append("/");
}
if(stringBuilder.toString().length() == 1) {
return stringBuilder.toString();
}
return stringBuilder.toString().substring(0, stringBuilder.length() - 1);
}
}
316. 중복 문자 제거
필수 사항 :
욕심 + 스택
- 욕심 알고리즘에 의해 검증 된 현재 최적의 솔루션이 스택에 저장되어
있으며, 처리 할 캐릭터를 추가해야하는지, 이전에 반복 된 캐릭터를 교체 할 수 있는지 여부를 결정할 필요가있을 때마다
class Solution {
private int[] letterNum = new int[26];
public String removeDuplicateLetters(String s) {
if (s == null || s.isEmpty() || s.length() == 1) {
return s;
}
initArray(s);
Stack<Character> stack = new Stack<>();
for (int i = 0; i < s.length(); i++) {
char sTmp = s.charAt(i);
letterNum[sTmp - 'a']--;
if(stack.isEmpty()) {
stack.push(sTmp);
continue;
}
while (!stack.isEmpty()) {
// 判断当前字符与stack已经入栈字符之间的关系
char stackTmp = stack.peek();
// 已经入栈的字符无需处理
if(stack.contains(sTmp)) {
break;
}
if(stackTmp - sTmp >= 0 && !isLastOne(stackTmp)) {
// 之前入栈的每个字符需要经过新字符的洗练。需要在后续有重复的基础上满足字典序最小
stack.pop();
} else {
// 遇到第一个无法处理的立即终止
break;
}
}
if (!stack.contains(sTmp)) {
// 栈中补充上该字符
stack.push(sTmp);
}
}
StringBuilder stringBuilder = new StringBuilder();
for(Character c :stack) {
stringBuilder.append(c);
}
return stringBuilder.toString();
}
private void initArray(String s) {
for (Character c : s.toCharArray()) {
letterNum[c - 'a']++;
}
}
private boolean isLastOne(char c) {
// 判断是否是最后一个
return letterNum[c - 'a'] == 0;
}
}
열
핵심 포인트 :
- 세 개의 아래 첨자 : 크기, 첫 번째, 마지막
첫 번째와 마지막의 실제 의미에 대해 명확하게 생각하십시오 : 정확한 기존 요소를 나타내는 아래 첨자와 위치의 다음
첫 번째 요소 사이의 관계 는 다음과 같습니다. 하나의 상황 만 겹칠 것입니다. 배열에 요소가 하나만있는 경우.
class MyCircularQueue {
Object[] queue = null;
int first = 0;
int last = 0;
int size = 0;
public MyCircularQueue(int k) {
queue = new Object[k];
first = 0;
last = 0;
size = k;
}
public boolean enQueue(int value) {
if (last + 1 == first || (last + 1 == size && first == 0)) {
return false;
}
if(last == first && queue[last] == null) {
queue[last] = value;
return true;
}
last++;
if (last == size) {
last = 0;
}
queue[last] = value;
return true;
}
public boolean deQueue() {
if (last == first) {
if(queue[first] == null) {
return false;
} else {
queue[first] = null;
return true;
}
}
queue[first] = null;
first ++;
if (first == size) {
first = 0;
}
return true;
}
public int Front() {
if (queue[first] == null) {
return -1;
}
return (int) queue[first];
}
public int Rear() {
if (queue[last] == null) {
return -1;
}
return (int) queue[last];
}
public boolean isEmpty() {
if (last == first && queue[last] == null) {
return true;
}
return false;
}
public boolean isFull() {
int lastIndex = last + 1;
if (lastIndex == first || (lastIndex == size && first == 0)) {
return true;
}
return false;
}
}
/**
* Your MyCircularQueue object will be instantiated and called as such:
* MyCircularQueue obj = new MyCircularQueue(k);
* boolean param_1 = obj.enQueue(value);
* boolean param_2 = obj.deQueue();
* int param_3 = obj.Front();
* int param_4 = obj.Rear();
* boolean param_5 = obj.isEmpty();
* boolean param_6 = obj.isFull();
*/