今天在LeetCode上刷题,刷到一道,题目是这样的:
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
结果示例:
示例一:
输入: “()”
输出: true
示例二:
输入: “()[]{}”
输出: true
示例三:
输入: “([)]”
输出: false
使用了自己写的代码:
public static boolean isValid(String s){
Stack<Character> stack = new Stack<>();
for (char ch: s.toCharArray()){
if (ch == '['){
stack.push(']');
}
else if (ch == '('){
stack.push(')');
}
else if (ch == '{') {
stack.push('}');
}
else if(stack.isEmpty()||ch!=stack.pop()){
return false;
}
}
return stack.isEmpty();
}
也能够符合题目的要求,但是当查看别人的解法的时候,流程的代码基本一致,但是用的是LinkedList,而且描述的效率比我的高,于是我跑了一下进行对比:
这时候就有疑惑了,为什么效率会差这么多?
最后在网上找到了答案:
Stack 继承自 Vector,而Vector 是矢量队列,和ArrayList一样,它也是一个动态数组,由数组实现 。但是ArrayList是非线程安全的,而Vector是线程安全的。
而对于LinkedList,我们知道它是一个双向链表。它也可以被当作堆栈、队列或双端队列进行操作。
看到这里,就能够理解为什么效率会低了。Stack 基于数组实现,LinkedList基于链表实现,数组随机访问效率高,但随机插入、随机删除效率低,链表与之相反。
那么对于这道题,要进行一些插入和删除操作,那么我们利用LinkedList实现栈自然比Stack快很多了,效率也提高不少。
最后总结一下:
Stack:基于数组实现,随机访问(查找)效率更高,增删改效率较低
LinkedList:基于链表实现,增删改效率更高,随机访问(查找)效率较低
这道题也给了我启发,当我们追求时间效率的时候,如果有大量插入删除操作,不妨利用 LinkedList 实现栈的相关功能,而不是思维定式般地想到栈就用Stack。
有时候寻找另一种方式去代替原有固定思想的事物,有时候会发现能实现同样的功能,但是带来的效果会更好。