文章只是總結,便於面試和手寫算法。細節和詳細解釋,請看: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容器使用單獨進程加載(會另外開闢內存空間),這種方案不推薦使用,交互會比較麻煩,網上也有相關的開源例子,可以參考下。