problem 167 & 170 from leetcode;java
https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/node
https://leetcode.com/problems/two-sum-iii-data-structure-design/ 數組
先來看簡單的167:給定一個排好序的數組,以及一個值,找出數組中相加等於該值的兩個數,假設這樣的值始終存在;數據結構
這個只要依次遍歷該數組,假設當前值爲x,那麼只須要在數組中找到value - x;若是存在,直接返回,若是不存在,檢查下一個值;由於數組是sorted,因此第二步查找只須要log N的時間;最壞狀況是 n * log N;this
public int[] twoSum(int[] numbers, int target) { int[] result = new int[2]; for(int i = 1; i <= numbers.length; i++) { int x = numbers[i - 1]; int y = target - x; int j = Arrays.binarySearch(numbers, i, numbers.length, y); if(j >= i) { result[0] = i; result[1] = j + 1; break; } } return result; }
題目170要求設計一種數據結構,支持add和find操做,下面是一個例子:設計
add(1); add(3); add(5); find(4) -> true find(7) -> false
一開始我得想法是使用167的解法,add的時候,把輸入加入到一個數組中,而且排好序;那麼就能夠直接使用167的find;但在輸入很長的時候,不少的add和find,會TLE;簡單的分析一下這種方式,(我使用的是insertion sort), 每次add排序,要O(n), 那麼總的時間就是O(n * n);code
後來我用AVL樹,由於AVL樹支持logN的insert/find操做;正好適合這個問題;如下是最終AC的代碼:排序
public class TwoSum { List<Integer> numbers = new ArrayList<>(); AVL avl = new AVL(); public void add(int number) { avl.add(number); numbers.add(number); } public boolean find(int value) { for (int x : numbers) { int y = value - x; Node node = avl.find(y); if (node == null) { continue; } //when these two numbers equal, need to make sure there at least two numbers added; if (x == y && node.count == 1) { continue; } return true; } return false; } public static void main(String[] args) { TwoSum twoSum = new TwoSum(); twoSum.add(1); twoSum.add(2); System.out.println(twoSum.find(1)); } class AVL { Node root; private int height(Node root) { if (root == null) { return -1; } else { return root.height; } } private Node insert(Node root, int value) { if (root == null) { root = new Node(value); } else if (root.value == value) { root.count += 1; } else if (root.value < value) { //go right; root.right = insert(root.right, value); if (height(root.right) - height(root.left) == 2) { if (value > root.right.value) { root = singleRotateWithRight(root); } else { root = doubleRotateWithRight(root); } } } else { //go left; root.left = insert(root.left, value); if (height(root.left) - height(root.right) == 2) { if (value < root.left.value) { root = singleRotateWithLeft(root); } else { root = doubleRotateWithLeft(root); } } } root.height = Math.max(height(root.left), height(root.right)) + 1; return root; } private Node doubleRotateWithRight(Node k3) { k3.right = singleRotateWithLeft(k3.right); return singleRotateWithRight(k3); } private Node singleRotateWithRight(Node k2) { Node k1 = k2.right; k2.right = k1.left; k1.left = k2; k2.height = Math.max(height(k2.left), height(k2.right)) + 1; k1.height = Math.max(height(k1.left), height(k1.right)) + 1; return k1; } private Node doubleRotateWithLeft(Node k3) { k3.left = singleRotateWithRight(k3.left); return singleRotateWithLeft(k3); } private Node singleRotateWithLeft(Node k2) { Node k1 = k2.left; k2.left = k1.right; k1.right = k2; k2.height = Math.max(height(k2.left), height(k2.right)) + 1; k1.height = Math.max(height(k1.left), height(k1.right)) + 1; return k1; } public void add(int value) { root = insert(root, value); } private Node find(Node root, int value) { if (root == null) { return null; } if (root.value == value && root.count == 0) { return null; } if (root.value == value) { return root; } if (value > root.value) { return find(root.right, value); } else { return find(root.left, value); } } public Node find(int value) { return find(root, value); } public Node getRoot() { return root; } } static class Node { final int value; int count, height; Node left, right; Node(int value) { this.value = value; count = 1; height = 0; } } }
果真這種方法很是的有效,彷佛是Java裏面最快的實現了;leetcode
BTW, AVL的實現是從教科書裏面找出來的,直接去寫,真沒有這樣的本事;get