二叉樹的前序遍歷
題目:給定一個二叉樹,返回它的 前序 遍歷。
思路:這個題也沒啥思路可說的,一個遞歸一個迭代,我都寫一遍就行了。然后之前做過一個中序排列。剛剛還看到下一道題是后續排列。一起做了得了,我去寫代碼了。
首先是遞歸實現:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
List<Integer> res;
public List<Integer> preorderTraversal(TreeNode root) {
res = new ArrayList<Integer>();
pre(root);
return res;
}
public void pre(TreeNode root){
if(root==null) return;
res.add(root.val);
pre(root.left);
pre(root.right);
}
}
迭代實現:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if(root == null) return res;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
while(root!=null || !stack.isEmpty()){
if(root!=null){
res.add(root.val);
if(root.left != null)stack.push(root.left);
root = root.left;
}else{
root = stack.pop();
if(root.right != null)stack.push(root.right);
root = root.right;
}
}
return res;
}
}
不得不說反正我這兩個代碼還是遞歸性能比較高。不過我看了人家的迭代實現,比我要好看多了。。。我直接貼代碼了:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if(root == null) return res;
LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
stack.add(root);
while(!stack.isEmpty()){
root = stack.pollLast();
res.add(root.val);
if(root.right != null){
stack.add(root.right);
}
if(root.left != null){
stack.add(root.left);
}
}
return res;
}
}
emmmm....事實證明這段代碼人家提交超過百分百,我提交好幾次也都只超過百分之五十八。。和我之前的一樣的。。。行了行了,就這樣了,下一題是后續遍歷。
二叉樹的后序遍歷
題目:給定一個二叉樹,返回它的 后序 遍歷。進階: 遞歸算法很簡單,你可以通過迭代算法完成嗎?
思路:題目截圖就不截圖了,知道是后序遍歷就行了,我直接貼代碼了。
遞歸版本:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
List<Integer> res;
public List<Integer> postorderTraversal(TreeNode root) {
res = new ArrayList<Integer>();
post(root);
return res;
}
public void post(TreeNode root){
if(root == null) return;
post(root.left);
post(root.right);
res.add(root.val);
}
}
迭代版本:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
LinkedList<Integer> res = new LinkedList<Integer>();
if(root == null) return res;
LinkedList<TreeNode> stack = new LinkedList<TreeNode>();
stack.add(root);
while(!stack.isEmpty()){
root = stack.poll();
if(root.left !=null ) stack.push(root.left);
if(root.right != null) stack.push(root.right);
res.addFirst(root.val);
}
return res;
}
}
其實這個題就是上題的逆思路。遞歸就不說了,迭代的話如果是前序是 當前 + 左 +右。后續是 左 + 右 +當前。
其實左右是一樣的,但是當前要去后面。 換個思路 如果實現了 當前 +右 +左 則倒過來直接就是后序遍歷了。就這個思路。然后每次add都是添加到第一個,還有先放左再放右。
感覺也沒啥說的,剛剛做才發現后序遍歷是困難的,哈哈,突然對自己有信心了呢~~下一題了啊
LRU緩存機制
題目:運用你所掌握的數據結構,設計和實現一個 LRU (最近最少使用) 緩存機制。它應該支持以下操作: 獲取數據 get 和 寫入數據 put 。
獲取數據 get(key) - 如果密鑰 (key) 存在于緩存中,則獲取密鑰的值(總是正數),否則返回 -1。
寫入數據 put(key, value) - 如果密鑰不存在,則寫入其數據值。當緩存容量達到上限時,它應該在寫入新數據之前刪除最久未使用的數據值,從而為新的數據值留出空間。
進階:你是否可以在 O(1) 時間復雜度內完成這兩種操作?
示例:
LRUCache cache = new LRUCache( 2 /* 緩存容量 */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 該操作會使得密鑰 2 作廢
cache.get(2); // 返回 -1 (未找到)
cache.put(4, 4); // 該操作會使得密鑰 1 作廢
cache.get(1); // 返回 -1 (未找到)
cache.get(3); // 返回 3
cache.get(4); // 返回 4
思路:這個題怎么說呢,我覺得實現起來還是很簡單的,尤其是進階要求只要求了時間復雜度而沒有空間復雜度。。我目前的想法是用LinkedHashMap。然后put判斷下size,達到容量了則把第一個刪了,然后后一個加上。沒達到直接加。 然后get的時候先把這個key-value獲取了,然后把這個key刪除了,重新添加,保證用過的在最后,第一個的永遠是最不活躍的那個。。差不多就這樣,我去代碼實現下。
尷尬了,我發現LinkedHashMap自帶訪問順序,就是訪問完移到最后,,,哈哈。其實這個類我早就知道,但是工作中幾乎沒用到過,只知道是Linked(鏈表)+HashMap的合體,本來我以為只是有序的map呢。。。剛剛要用了去百度了下api才發現不太多。。我用這個數據結構是不是太取巧了啊?不管了,反正第一版本先實現再說。
好了,在前人的肩膀上直接實現了:
class LRUCache {
LinkedHashMap<Integer,Integer> map;
public LRUCache(int capacity) {
this.map = new LinkedHashMap<Integer, Integer>(capacity, 0.75f, true) {
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return map.size() > capacity;
}
};
}
public int get(int key) {
return map.get(key)==null?-1:map.get(key);
}
public void put(int key, int value) {
map.put(key,value);
}
}
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/
我僅剩不多的自尊心告訴我這道題不是考對Linked Hash Map的熟悉程度的。。。我這是取巧了啊,我自己實現試試。
其實我覺得用LinkedList和HashMap也是可以實現的。鏈表存key,map的key還是key,value是value。然后鏈表就按照我剛剛說的,超了再放則刪除第一個。重復訪問則刪除再添加保證訪問的在最后。我去實現下看看。
自己手寫出來了,效率啥的賊辣眼睛。。。我先貼出來:
class LRUCache {
int cap;
HashMap<Integer,Integer> map;
LinkedList<Integer> list;
public LRUCache(int capacity) {
this.cap = capacity;
map = new HashMap<Integer,Integer>();
list = new LinkedList<Integer>();
}
public int get(int key) {
if(map.get(key) != null){
list.remove(Integer.valueOf(key));
list.add(key);
return map.get(key);
}
return -1;
}
public void put(int key, int value) {
if(list.size()==cap && !list.contains(key)){
Integer r = list.get(0);
list.remove(0);
map.remove(r);
list.add(key);
map.put(key,value);
}else if(list.contains(key)){//說明key已經存在,是更改值
list.remove(Integer.valueOf(key));
list.add(key);
map.put(key,value);
}else{
list.add(key);
map.put(key,value);
}
}
}
/**
* Your LRUCache object will be instantiated and called as such:
* LRUCache obj = new LRUCache(capacity);
* int param_1 = obj.get(key);
* obj.put(key,value);
*/
就是linkedList 來排序, map來存值。難道是不難,就是很墨跡。這個題就這樣了。
今天的筆記就記到這里,如果稍微幫到你了記得點個喜歡點個關注,順便祝大家工作順順利利,生活平平安安,周末愉快!