栈
先进后出,后进先出。只有一个口。
例子:浏览器的页面前进后退操作。
判断数据结构的好坏要对比四个操作
1、访问Access
时间复杂度是O(1),只能访问栈顶的元素。
2、搜索Search
时间复杂度是O(N)。需要遍历才能找到对应的元素。
3、插入Insert
时间复杂度是O(1)。只能在栈顶插入元素。
4、删除Delete
时间复杂度为O(1)。只能在栈顶删除元素。
Java栈常用操作
1、创建栈
Stack<Integer>
stack = new Stack<>();
2、添加元素
stack.push(1);
stack.push(2);
stack.push(3);
时间复杂度是O(1),只能在栈顶添加元素。
3、获取栈顶元素
int top = stack.peek();
时间复杂度是O(1)。
4、删除栈顶元素
int top = stack.pop();
时间复杂度是O(1)。
5、获取栈的长度
int length = stack.size();
时间复杂度为O(1)。创建栈时会定义一个变量来记录栈的长度,增删时会随之改变,获取长度即直接返回这个变量,不用遍历栈。
6、判断栈是否为空
boolean isEmpty = stack.isEmpty();
7、栈的遍历
while(!stack.isEmpty()) {
int top = stack.pop();
}
8、栈相关leetcode
No.20 有效的括号
思路:
如果字符串为空,直接返回true。
创建栈,遍历字符串的字符数组,如果是左括号就入栈;否则即右括号,先判断栈是否为空,是则说明栈内没有左括号可以与之匹配,直接返回false。栈不为空则判断是哪种类型的右括号,取出栈顶元素将其匹配,如果匹配不上,则返回false。
遍历结束后,判断栈是否为空,不为空则说明栈中还有剩余的左括号,没有右括号与之匹配,返回false。
最后返回true。
class Solution {
public boolean isValid(String s) {
if(s.length() == 0)
return true;
Stack<Character> stack = new Stack<>();
for(char c : s.toCharArray()) {
if(c == '(' || c == '[' || c == '{') {
stack.push(c);
} else {
if(stack.isEmpty())
return false;
if(c == ')') {
char top = stack.pop();
if(top != '(')
return false;
}
if(c == ']') {
char top = stack.pop();
if(top != '[')
return false;
}
if(c == '}') {
char top = stack.pop();
if(top != '{')
return false;
}
}
}
if(!stack.isEmpty())
return false;
return true;
}
}
No.496 下一个更大的元素
思路一:使用两个栈,先将数组2的元素放进stack中,然后遍历数组1的元素,每轮遍历创建临时变量max记录比当前元素大的元素,初始化为-1,表示还没找到,将其加入result中。临时变量isFound表示是否已经到达了相同元素的位置,因为我们只关心元素之后大于它的元素,所以到达了相同元素的位置后就不用再继续遍历栈了。while判断stack不为空且isFound为false,遍历stack,将删除的元素放入栈temp中。如果栈顶元素大于当前元素,将栈顶元素赋值给max;如果栈顶元素等于当前元素,将isFound设置为true,则退出栈的遍历。栈遍历结束后,如果isFound为true,就将result中的位置i设置为max。然后将temp中的元素还给stack。
class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
ArrayList<Integer> result = new ArrayList<>();
Stack<Integer> stack = new Stack<>();
Stack<Integer> temp = new Stack<>();
for(int i = 0; i < nums2.length; i++) {
stack.push(nums2[i]);
}
for(int i = 0; i < nums1.length; i++) {
int max = -1;
boolean isFound = false;
result.add(-1);
while(!stack.isEmpty() && !isFound) {
int top = stack.pop();
temp.push(top);
if(top > nums1[i])
max = top;
if(top == nums1[i]) {
isFound = true;
}
}
if(isFound)
result.set(i, max);
while(!temp.isEmpty()) {
int top = temp.pop();
stack.push(top);
}
}
return result.stream().mapToInt(k->k).toArray();
}
}
思路二:不使用栈。遍历数组1,每轮遍历创建变量max,加入result,变量isFound,嵌套遍历数组2,数组2是反向遍历的,如果数组1的元素等于数组2的元素,将isFound设为true,表示已经遍历完了目标元素的后面所有元素;如果数组2的元素大于数组1的元素,将数组2的元素赋值给max,数组2每遍历完一轮,判断isFound是否为true,是则将result的位置i设置为max。
class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
ArrayList<Integer> result = new ArrayList<>();
if(nums1 == null || nums1.length == 0)
return nums1;
for(int i = 0; i < nums1.length; i++) {
int max = -1;
result.add(max);
boolean isFound = false;
for(int j = nums2.length - 1; j >= 0 && !isFound; j--) {
if(nums2[j] == nums1[i]) {
isFound = true;
}
if(nums2[j] > nums1[i])
max = nums2[j];
}
if(isFound)
result.set(i, max);
}
return result.stream().mapToInt(k->k).toArray();
}
}