面經題

232.Implement Queue Using Stackhtml

class MyQueue {

    /** Initialize your data structure here. */
        Stack<Integer> s1;
        Stack<Integer> s2;
    public MyQueue() {
        s1 = new Stack<>();
        s2 = new Stack<>();
    }
    
    /** Push element x to the back of queue. */
    public void push(int x) {
        s1.push(x);
    }
    
    /** Removes the element from in front of queue and returns that element. */
    public int pop() {
        while (!s2.isEmpty()) {
            return s2.pop();
        }
        while (!s1.isEmpty()) {
            s2.push(s1.pop());
        }
        if (!s2.isEmpty()) {
            return s2.pop();
        }
        return -1;
    }
    
    //優化代碼邏輯 先check s2是否爲空
    public int pop() {
        if (s2.isEmpty()) {
            while (!s1.isEmpty()) {
                s2.push(s1.pop());   
            }
        }
        return s2.pop();
    }
    
    /** Get the front element. */
    public int peek() {
        if (!s2.isEmpty()) {
            return s2.peek();
        }
        while (!s1.isEmpty()) {
            s2.push(s1.pop());
        }
        if (s2.isEmpty()) {
            return -1;
        }
        return s2.peek();
    }
    
    /** Returns whether the queue is empty. */
    public boolean empty() {
        return (s2.isEmpty() && s1.isEmpty());
    }
}

/** * Your MyQueue object will be instantiated and called as such: * MyQueue obj = new MyQueue(); * obj.push(x); * int param_2 = obj.pop(); * int param_3 = obj.peek(); * boolean param_4 = obj.empty(); */
複製代碼

155.Min Stackjava

  • 題目: 實現一個包含返回棧中最小元素的方法的棧
  • 思路1: 兩個棧來實現 -> 一個棧s1來存全部的元素, 另外一個棧s2記錄當前最小元素,
    • push(): s1全都壓入, s2在比較以後壓入
    • pop(): 若是彈出的是最小元素,那麼兩個棧同時彈出,若是彈出的不是最小元素,那麼只有第一個棧彈出,最小棧不作操做
    • getMin(): 直接返回s2的peek便可 最小棧中可能有重複值
  • 思路2: 一個棧來實現,至關於把最小元素這個信息記錄在了當前棧中
    • push(): 先判斷新加入的元素是否比當前的元素小, 若是小的話,將上一個最小值push進棧,則上一個最小值有效的範圍是兩個值之間 [-2,0,-3]的輸入會生成一個 [-3, -2, 0, -2, MAX] 的棧,-2是在[-2,0,-2]範圍內有效的
class MinStack {
    int min = Integer.MAX_VALUE;
    private Stack<Integer> stack = new Stack<Integer>();
    
    public void push(int x) {
        // only push the old minimum value when the current 
        // minimum value changes after pushing the new value x
        if(x <= min){          
            this.stack.push(min);
            min=x;
        }
        this.stack.push(x);
    }

    public void pop() {
        // if pop operation could result in the changing of the current minimum value, 
        // pop twice and change the current minimum value to the last minimum value.
        if(stack.pop() == min) {
            min = this.stack.pop();
        }
    }

    public int top() {
        return this.stack.peek();
    }

    public int getMin() {
        return min;
    }
}
複製代碼

Tree

Binary Tree Preorder Traversalnode

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if (root == null) {
            return res;
        }
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode node = stack.pop();
            res.add(node.val);
            if (node.right != null) {
                stack.push(node.right);
            }
            if (node.left != null) {
                stack.push(node.left);
            }
        }
        
        return res;
    }
}
複製代碼

Inorder Traversalapp

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if (root == null) {
            return res;
        }
        Stack<TreeNode> stack = new Stack<>();
        while (!stack.isEmpty() || root != null) {
            // 先遍歷全部的左子樹節點
            while (root != null) {
                stack.push(root);
                root = root.left;
            }
            // 到了最左邊以後再pop而後將根節點從棧中彈出, 遍歷右子節點
            root = stack.pop();
            res.add(root.val);
            root = root.right;
        }
        
        return res;
    }
}
複製代碼

Postorder Traversal優化

二叉樹的最長路徑ui

543. Diameter of Binary Treethis

  • 題目:找出一個二叉樹中的最長路徑
  • 思路: 兩種狀況 1.通過root節點 left深度 + right深度 2.不通過root節點 直接max(left, right) + 1
class Solution {    
    public int diameterOfBinaryTree(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int diameter = 0;
        helper(root, diameter);
        return diameter;
    }
    
    private int helper(TreeNode root, int diameter) {
        if (root == null) {
            return 0;
        }
        int left = helper(root.left, diameter);
        int right = helper(root.right, diameter);
        diameter = Math.max(diameter, left + right);
        return Math.max(left, right) + 1; // 不過root節點
    }
}
複製代碼

判斷一棵二叉樹是否爲徹底二叉樹spa

  • 思路: 四種節點 1.左右子樹都存在 2.只存在左子樹 3.只存在右子樹 4.左右子樹都不存在 如
    • 直接放入queue中
    • 能夠是最後一層的靠左的節點
    • 不符合要求,若是發現這樣的節點直接return false
    • 能夠是倒數第二層的葉節點
import java.util.*;
class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;
    }
}
public class CheckCompletion {
    public boolean checking(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        boolean leaf = false; // 葉子結點
        TreeNode left;
        TreeNode right;
        queue.add(root);
        while (!queue.isEmpty()) {
            root = queue.poll();
            left = root.left;
            right = root.right;
            if ((leaf&&(left!=null||right!=null)) || (left==null&&right!=null)) {
                // 若是以前層遍歷的結點沒有右孩子,且當前的結點有左或右孩子,直接返回false
                // 若是當前結點有右孩子卻沒有左孩子,直接返回false
                return false;
            }
            if (left != null) {
                queue.offer(root.left);
            }
            if (right != null) {
                queue.offer(root.right);
            }else {
                leaf = false; // 若是當前結點沒有右孩子,那麼以後層遍歷到的結點必須爲葉子結點
            }
        }
        return true;
    }
}
複製代碼

124.Binary Tree Maximum Path Sum 問題: 返回一個非空二叉樹中路徑和最大的路徑指針

public class Solution {
    int maxValue;
    
    public int maxPathSum(TreeNode root) {
        maxValue = Integer.MIN_VALUE;
        maxPathDown(root);
        return maxValue;
    }
    
    private int maxPathDown(TreeNode node) {
        if (node == null) return 0;
        int left = Math.max(0, maxPathDown(node.left));
        int right = Math.max(0, maxPathDown(node.right));
        maxValue = Math.max(maxValue, left + right + node.val);
        return Math.max(left, right) + node.val;
    }
}
複製代碼

String

415. Add Stringscode

  • 題目: 給出兩個非負的字符串,求兩個字符串向相加以後的結果
  • 思路: 兩個字符串從後向前遍歷,逐一相加,注意進位和遍歷越界的狀況
public class Solution {
    public String addStrings(String num1, String num2) {
        StringBuilder sb = new StringBuilder();
        int carry = 0;
        // 從後向前遍歷
        for (int i = num1.length() - 1, j = num2.length() - 1; i >= 0 || j >= 0 || carry == 1; i--, j--) {
            int x = i < 0 ? 0 : num1.charAt(i) - '0';
            int y = j < 0 ? 0 : num2.charAt(j) - '0';
            sb.append((x + y + carry) % 10); // 對10取模獲得餘數
            carry = (x + y + carry) / 10; // 除10獲得倍數
        }
        return sb.reverse().toString();
    }
}
複製代碼

43. Multiply Strings

  • 題目: 給出兩個非負的字符串,求兩個字符串相乘的結果
  • 思路: 乘法變加法? 乘數拆解 num * 121 = num * 100 + num * 20 + num 豎位計算,先將全部的乘法計算的結果保留,而後與以前的結果進行加和,分別保留進位和餘位
class Solution {
    public String multiply(String num1, String num2) {
        if (num1.equals("0") || num2.equals("0")) {
            return "0";
        }
        
        int n1 = num1.length();
        int n2 = num2.length();
        int[] res = new int[n1 + n2];
        for (int i = n1 - 1; i >= 0; i--) {
            for (int j = n2 - 1; j >= 0; j--) {
                // num1[i] * num2[j] 的結果必定是一個兩位數,分別對應res中的第i + j 和 第i + j + 1位
                int mul = (num1.charAt(i) - '0') * (num2.charAt(j) - '0');
                int sum = mul + res[i + j + 1];
                // [i + j] 是高位 [i + j + 1]是低位
                res[i + j] += sum / 10; 
                res[i + j + 1] = sum % 10;
            }
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < res.length; i++) {
            if (i == 0 && res[i] == 0) {
                continue;
            }
            sb.append(res[i]);
        }
        
        return sb.toString();
    }
}
複製代碼

Linked List

328. Odd Even Linked List

  • 問題: 將奇偶鏈表分開 要求O(1)空間複雜度
  • 思路: 快慢指針
複製代碼

奇偶鏈表排序

329. Longest Increasing Path in a Matrix

class Solution {
    private final int[] dx = {1, -1, 0, 0};
    private final int[] dy = {0, 0, 1, -1};
    
    public int longestIncreasingPath(int[][] matrix) {
        if (matrix == null || matrix.length == 0) {
            return 0;
        }
        int longest = 0;
        int rows = matrix.length;
        int cols = matrix[0].length;
        int[][] memo = new int[rows][cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                int curr = dfs(matrix, i, j, rows, cols, memo);
                if (curr > longest) {
                    longest = curr;
                }
            }
        }
        return longest;
    }
    
    public int dfs(int[][] matrix, int x, int y, int rows, int cols, int[][] memo) {
        if (memo[x][y] != 0) {
            return memo[x][y];
        }
        int max = 1;
        for (int i = 0 ; i < 4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];
            if (nx < 0 || nx >= rows || ny < 0 || ny >= cols || matrix[nx][ny] <= matrix[x][y]) continue;
            int len = 1 + dfs(matrix, nx, ny, rows, cols, memo);
            max = Math.max(max, len);
        }
        memo[x][y] = max;
        return max;
    }
}
複製代碼

Remove Duplicates From Sorted List

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if (head == null) {
            return null;
        }
        ListNode prev = head;
        ListNode curr = head.next;

        while (curr != null) {
            if (prev.val == curr.val) {
                prev.next = curr.next;
            } else {
                prev = prev.next;
            }
            curr = curr.next;
        }
        
        return head;
    }
}
複製代碼

82. Remove Duplicates from Sorted List II

  • 問題: 重複元素不保留,直接所有刪除
  • 思路: 須要設定一個dummy指針做爲上一個元素的起點,去比較下一個指針和下下個指針的值是否相等,若是不相等,直接前進,若是相等,前進下下個,直到不相等的時候直接跳過

Array

295. Find Median from Data Stream

  • 問題: 找到一個數據流中的中位數
  • 思路1: Brute Force維持一個sorted array, 每次將新值插入到特定的順序 O(n^2)時間複雜度
  • 思路2: 直接
class MedianFinder {
    private PriorityQueue<Integer> lowers;
    PriorityQueue<Integer> highers;
    private boolean even;
    /** initialize your data structure here. */
    public MedianFinder() {
        lowers = new PriorityQueue<>(new Comparator<Integer> () {
            public int compare(Integer a, Integer b) {
                return -1 * a.compareTo(b);
            }
        });
        highers = new PriorityQueue<Integer>();
        even = true;
    }
    
    public void addNum(int num) {
        if (even) {
            highers.offer(num);
            lowers.offer(highers.poll());
        } else {
            lowers.offer(num);
            highers.offer(lowers.poll());
        }
        even = !even;
    }
    
    public double findMedian() {
        if (even) {
            return (lowers.peek() + highers.peek()) / 2.0;
        } else {
            return lowers.peek();
        }
    }
}
複製代碼
//02.24 九章參考解法
class MedianFinder {
    public PriorityQueue<Integer> minheap, maxheap;
    public MedianFinder() {
        maxheap = new PriorityQueue<Integer>(Collections.reverseOrder());
        minheap = new PriorityQueue<Integer>();
    }
    
    // Adds a number into the data structure.
    public void addNum(int num) {
        maxheap.add(num);
        minheap.add(maxheap.poll());
        if (maxheap.size() < minheap.size()) {
            maxheap.add(minheap.poll());
        }
    }

    // Returns the median of current data stream
    public double findMedian() {
        if (maxheap.size() == minheap.size()) {
            return (maxheap.peek() + minheap.peek()) * 0.5;
        } else {
            return maxheap.peek();
        }
    }
};
複製代碼

en.wikipedia.org/wiki/Median… cs.stackexchange.com/questions/1… www.cnblogs.com/shizhh/p/57…

Design HashMap

class MyHashMap {
    class ListNode {
        int key, val;
        ListNode next;
        
        ListNode(int key, int val) {
            this.key = key;
            this.val = val;
        }
    }
    final ListNode[] nodes = new ListNode[1000];

    /** Initialize your data structure here. */
    public MyHashMap() {
        
    }
    
    /** value will always be non-negative. */
    public void put(int key, int value) {
        int i = idx(key);
        if (nodes[i] == null) {
            nodes[i] = new ListNode(-1, -1);
        }
        ListNode prev = find(nodes[i], key);
        if (prev.next == null) {
            prev.next = new ListNode(key, value);
        } else {
            prev.next.val = value;
        }
    }
    
    /** Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key */
    public int get(int key) {
        int i = idx(key);
        if (nodes[i] == null) {
            return -1;
        }
        ListNode node = find(nodes[i], key);
        return node.next == null ? -1 : node.next.val;
    }
    
    /** Removes the mapping of the specified value key if this map contains a mapping for the key */
    public void remove(int key) {
        int i = idx(key);
        if (nodes[i] == null) return;
        ListNode prev = find(nodes[i], key);
        if (prev.next == null) return;
        prev.next = prev.next.next;
    }
    
    int idx(int key) {
        return Integer.hashCode(key) % nodes.length;
    }
    
    // find the value map to the key
    ListNode find(ListNode bucket, int key) {
        ListNode node = bucket;
        ListNode prev = null;
        while (node != null && node.key != key) {
            prev = node;
            node = node.next;
        }
        return prev;
    }
}

複製代碼
相關文章
相關標籤/搜索