文章只是总结,便于面试和手写算法。细节和详细解释,请看:https://leetcode-cn.com/
1. 题目
算法题:
1. 有效的括号:https://leetcode-cn.com/problems/valid-parentheses/
2. 用栈实现队列:https://leetcode-cn.com/problems/implement-queue-using-stacks/
3. 数据流中的第K大元素:https://leetcode-cn.com/problems/kth-largest-element-in-a-stream/
面试题:
1. WebView如何解决内存泄漏。
2. 基本知识
2.1 栈
先入后出的数据结构。
- 查询时间复杂度:O(n)
- 插入、删除时间复杂度:O(1)
2.2 队列
先进先出的数据结构。
- 查询:O(n)
- 插入、删除:O(1)
2.3 优先队列
正常进,按优先级出。一般由堆实现或者二叉搜索树实现,斐波拉契堆是效率最好的一种。
3. 算法题解题
3.1 有效的括号
使用栈来把所有括号入栈
该题解,时间复杂度O(n),空间复杂度O(n)
class Solution {
private HashMap<Character, Character> mappings;
public Solution() {
this.mappings = new HashMap<Character, Character>();
this.mappings.put(')', '(');
this.mappings.put('}', '{');
this.mappings.put(']', '[');
}
public boolean isValid(String s) {
Stack<Character> stack = new Stack<Character>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (this.mappings.containsKey(c)) {
char topElement = stack.pop();
return false.
if (this.mappings.get(c).equals(String.valueOf(topElement))) {
return false;
}
} else {
stack.push(c);
}
}
return stack.isEmpty();
}
}
3.2 用栈实现队列
栈是先入后出,队列是先入先出,新写一个类,使用栈辅助达到先入先出的效果即可。使用一个栈存储存入数据,在执行
pop()
和peek
的时候,将存储栈内容遍历pop
并入栈输出栈,然后调用输出栈的pop
和peek
即可。是否为空需要判断存储栈和输出栈都为空才为空。
该题解时间复杂度O(n),空间复杂度O(n)
class MyQueue {
Stack stack1 = new Stack();
Stack stack2 = new Stack();
/** Initialize your data structure here. */
public MyQueue() {
}
/** Push element x to the back of queue. */
public void push(int x) {
stack1.push(x);
}
/** Removes the element from in front of queue and returns that element. */
public int pop() {
while(!stack1.isEmpty()){
stack2.push(stack1.pop());
}
return (Integer) stack2.pop();
}
/** Get the front element. */
public int peek() {
while(!stack1.isEmpty()){
stack2.push(stack1.pop());
}
return (Integer) stack2.peek();
}
/** Returns whether the queue is empty. */
public boolean empty() {
if (stack1.isEmpty() && stack2.isEmpty()) {
return true;
}
return false;
}
}
3.3 数据流中的第K大元素
利用优先队列
PriorityQueue
的特性,存储最大的k个数,然后最后返回k个中最小的数即可,也就是PriorityQueue
中读取出来的第一个。在添加过程中如果不到K个,按顺序入队,如果超过,判断最后一个元素大小,决定取舍。
class KthLargest {
private PriorityQueue<Integer> priorityQueue;
private int k;
public KthLargest(int k, int[] nums) {
priorityQueue = new PriorityQueue<Integer>();
this.k = k;
for (int i = 0; i < nums.length; i++) {
add(nums[i]);
}
}
public int add(int val) {
if (priorityQueue.size() <k) {
priorityQueue.offer(val);
}else if (priorityQueue.peek() < val) {
priorityQueue.poll();
priorityQueue.offer(val);
}
return priorityQueue.peek();
}
}
4. 面试题解题
4.1 WebView如何解决内存泄漏
在Android 5.1以上,安卓系统会在
onAttachedToWinodw
和onDettachedFromWindow
方法中注册和反注册:component callbacks
,而onDettachedFromWindow
方法第一行会判断是否被销毁,如果被销毁了,那么就不会去反注册,导致内存泄漏if (isDestroyed()) return;
所以解决方案就是,先执行removeView的方法,让onDettachedFromWindow
方法先走,反注册代码能够继续执行:
@Override
protected void onDestroy() {
if( mWebView!=null) {
// 如果先调用destroy()方法,则会命中if (isDestroyed()) return;这一行代码,需要先onDetachedFromWindow(),再
// destory()
ViewParent parent = mWebView.getParent();
if (parent != null) {
((ViewGroup) parent).removeView(mWebView);
}
mWebView.stopLoading();
// 退出时调用此方法,移除绑定的服务,否则某些特定系统会报错
mWebView.getSettings().setJavaScriptEnabled(false);
mWebView.clearHistory();
mWebView.clearView();
mWebView.removeAllViews();
mWebView.destroy();
}
super.on Destroy();
}
解决方法二:WebView容器使用单独进程加载(会另外开辟内存空间),这种方案不推荐使用,交互会比较麻烦,网上也有相关的开源例子,可以参考下。