leetcode

¡Supera tus tareas y exámenes ahora con Quizwiz!

278. First Bad Version You are a product manager and currently leading a team to develop a new product. Unfortunately, the latest version of your product fails the quality check. Since each version is developed based on the previous version, all the versions after a bad version are also bad. Suppose you have n versions [1, 2, ..., n] and you want to find out the first bad one, which causes all the following ones to be bad. You are given an API bool isBadVersion(version) which will return whether version is bad. Implement a function to find the first bad version. You should minimize the number of calls to the API.

/* The isBadVersion API is defined in the parent class VersionControl. boolean isBadVersion(int version); */ public class Solution extends VersionControl { public int firstBadVersion(int n) { if (n == 0) { return 1; } int ans = 0; int left = 1, right = n; while (left < right) { int mid = left + (right - left) / 2; if (isBadVersion(mid)) { right = mid; } else { left = mid + 1; } } return left; } } time: log n space: o(1)

257. Binary Tree Paths Given a binary tree, return all root-to-leaf paths.

/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ class Solution { private List<String> list; public List<String> binaryTreePaths(TreeNode root) { if (root == null) return new ArrayList<>(); list = new ArrayList<>(); String s = String.valueOf(root.val); helper(root, s); return list; } private void helper(TreeNode root, String s) { if (root.left == null && root.right == null) { list.add(s); return; } if (root.left != null) helper(root.left, s + "->" +root.left.val); if (root.right != null)helper(root.right, s + "->" + root.right.val); } } 時間複雜度O(n)

56. Merge Intervals Given a collection of intervals, merge all overlapping intervals. Example 1: Input: [[1,3],[2,6],[8,10],[15,18]] Output: [[1,6],[8,10],[15,18]] Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].

/** * Definition for an interval. * public class Interval { * int start; * int end; * Interval() { start = 0; end = 0; } * Interval(int s, int e) { start = s; end = e; } * } */ public List<Interval> merge(List<Interval> intervals) { List<Interval> result = new ArrayList<>(); for (int i = 0; i < intervals.size(); i++) { insert(result, intervals.get(i)); } return result; } private static List<Interval> insert(List<Interval> intervals,Interval newInterval) { for (int i = 0; i < intervals.size();) { final Interval cur = intervals.get(i); if (newInterval.end < cur.start) { intervals.add(i, newInterval); return intervals; } else if (newInterval.start > cur.end) { ++i; continue; } else { newInterval.start = Math.min(newInterval.start, cur.start); newInterval.end = Math.max(newInterval.end, cur.end); intervals.remove(i); } } intervals.add(newInterval); return intervals; } time, space: log n 除了用priority queue, 用insert的更快 如果新的end比start小, 就插在前面 如果新的start比end大, 就continue 不然就merge

141. Linked List Cycle Given a linked list, determine if it has a cycle in it. To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list. Example 1: Input: head = [3,2,0,-4], pos = 1 Output: true Explanation: There is a cycle in the linked list, where tail connects to the second node.

/** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public boolean hasCycle(ListNode head) { if (head == null) return false; ListNode slow = head; ListNode fast = head; while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; if (slow == fast) return true; } return false; } } time: o(n) space: o(1)

237. Delete Node in a Linked List Write a function to delete a node (except the tail) in a singly linked list, given only access to that node. 只給要刪除的那個node, 不是給head

/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public void deleteNode(ListNode node) { node.val = node.next.val; node.next =node.next.next; } }

225. Implement Stack using Queues Implement the following operations of a stack using queues. push(x) -- Push element x onto stack. pop() -- Removes the element on top of the stack. top() -- Get the top element. empty() -- Return whether the stack is empty.

/** Initialize your data structure here. */ Queue<Integer> q; public MyStack() { q = new LinkedList<>(); } /** Push element x onto stack. */ public void push(int x) { Queue<Integer> temp = new LinkedList<>(); temp.offer(x); while (!q.isEmpty()) { temp.offer(q.poll()); } q = temp; } /** Removes the element on top of the stack and returns that element. */ public int pop() { return q.poll(); } /** Get the top element. */ public int top() { return q.peek(); } /** Returns whether the stack is empty. */ public boolean empty() { return q.isEmpty(); }

348. Design Tic-Tac-Toe Design a Tic-tac-toe game that is played between two players on a n x n grid. You may assume the following rules: A move is guaranteed to be valid and is placed on an empty block. Once a winning condition is reached, no more moves is allowed. A player who succeeds in placing n of their marks in a horizontal, vertical, or diagonal row wins the game.

/** Initialize your data structure here. */ int[] cols; int[] rows; int dig; int antiDig; public TicTacToe(int n) { cols = new int[n]; rows = new int[n]; dig = 0; antiDig = 0; } /** Player {player} makes a move at ({row}, {col}). @param row The row of the board. @param col The column of the board. @param player The player, can be either 1 or 2. @return The current winning condition, can be either: 0: No one wins. 1: Player 1 wins. 2: Player 2 wins. */ public int move(int row, int col, int player) { int add = player == 1? 1: -1; cols[col] += add; rows[row] += add; if (col == row) { dig += add; } int size = cols.length; if (col + row == size - 1) { antiDig += add; } if (Math.abs(cols[col]) == size || Math.abs(rows[row]) == size || Math.abs(dig) == size || Math.abs(antiDig) == size) { return player; } return 0; } time: o(n) space: o(1)

428. Serialize and Deserialize N-ary Tree

// Encodes a tree to a single string. public String serialize(Node root) { List<String> list = new ArrayList<>(); shelper(root, list); return String.join(",", list); } private void shelper(Node root, List<String> list) { if (root == null) return; list.add(String.valueOf(root.val)); list.add(String.valueOf(root.children.size())); for (Node n: root.children) { shelper(n, list); } } // Decodes your encoded data to tree. public Node deserialize(String data) { if (data == null || data.length() == 0) { return null; } String[] strs = data.split(","); Queue<String> q = new LinkedList<>(); for (String s: strs) { q.offer(s); } return dhelper(q); } private Node dhelper(Queue<String> q) { Node root = new Node(); root.val = Integer.valueOf(q.poll()); int size = Integer.valueOf(q.poll()); root.children = new ArrayList<>(); for (int i = 0; i < size; i++) { root.children.add(dhelper(q)); } return root; }

297. Serialize and Deserialize Binary Tree Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment. Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.

// Encodes a tree to a single string. public String serialize(TreeNode root) { if (root == null) { return "{}"; } StringBuilder sb = new StringBuilder(); Queue<TreeNode> q = new LinkedList<>(); List<String> list = new ArrayList<>(); q.offer(root); sb.append("{"); while (!q.isEmpty()) { TreeNode temp = q.poll(); if (temp == null) { list.add("null"); } else { list.add(String.valueOf(temp.val)); q.offer(temp.left); q.offer(temp.right); } } while (list.get(list.size() - 1).equals("null")) { list.remove(list.size() - 1); } for (int i = 0; i < list.size(); i++) { if (i == 0) { sb.append(list.get(i)); } else { sb.append(","); sb.append(list.get(i)); } } sb.append("}"); // System.out.println(sb.toString()); return sb.toString(); } // Decodes your encoded data to tree. public TreeNode deserialize(String data) { if (data.equals("{}")) { return null; } StringBuilder sb = new StringBuilder(data); sb.deleteCharAt(0); sb.setLength(sb.length() - 1); String[] nodes = sb.toString().split(","); TreeNode head = new TreeNode(Integer.valueOf(nodes[0])); int i = 1; Queue<TreeNode> q = new LinkedList<>(); q.offer(head); while (!q.isEmpty()) { TreeNode temp = q.poll(); if (i < nodes.length && !nodes[i].equals("null")) { temp.left = new TreeNode(Integer.valueOf(nodes[i])); q.offer(temp.left); } i++; if (i < nodes.length && !nodes[i].equals("null")) { temp.right = new TreeNode(Integer.valueOf(nodes[i])); q.offer(temp.right); } i++; } return head } 記得如果有null的話不要再跑node.left, node.right 第二個method也要確認null的情況 i記得加兩次

171. Excel Sheet Column Number Given a column title as appear in an Excel sheet, return its corresponding column number. For example: A -> 1 B -> 2 C -> 3 ... Z -> 26 AA -> 27 AB -> 28

public int titleToNumber(String s) { if (s == null || s.length() == 0) { return 0; } int pos = 0; int ans = 0; for (int i = s.length() - 1; i >= 0; i--) { ans += Math.pow(26, pos) * (s.charAt(i) - 'A' + 1); pos++; } return ans; } time: o(n) space: o(1) 記得加一

172. Factorial Trailing Zeroes Given an integer n, return the number of trailing zeroes in n!. Example 1: Input: 3 Output: 0 Explanation: 3! = 6, no trailing zero.

public int trailingZeroes(int n) { return n == 0? 0 : n / 5 + trailingZeroes(n / 5); } 解釋:找2*5的倍數, 因為2有很多個,所以其實就是找五的倍數,所以n / 5, 之後n/5進去recursion, 因為e.g 25是兩個5的倍數

283. Move Zeroes Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements. Example: Input: [0,1,0,3,12] Output: [1,3,12,0,0]

public void moveZeroes(int[] nums) { if (nums == null || nums.length == 0) { return; } int j = 0; for (int i = 0; i < nums.length; i++) { if (nums[i] != 0) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; j++; } } } time: o(n) space: o(1)

350. Intersection of Two Arrays II Given two arrays, write a function to compute their intersection. Example 1: Input: nums1 = [1,2,2,1], nums2 = [2,2] Output: [2,2]

What if the given array is already sorted? How would you optimize your algorithm? ==>two pointers What if nums1's size is small compared to nums2's size? Which algorithm is better? ==>hash map What if elements of nums2 are stored on disk, and the memory is limited such that you cannot load all elements into the memory at once? ==> binary search Given two arrays, write a function to compute their intersection. Example 1: Input: nums1 = [1,2,2,1], nums2 = [2,2] Output: [2,2] 不是two pointer的方法要用map存count

173. Binary Search Tree Iterator Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the root node of a BST. Calling next() will return the next smallest number in the BST.

class BSTIterator { private Stack<TreeNode> stack; public BSTIterator(TreeNode root) { stack = new Stack<>(); while (root != null) { stack.push(root); root = root.left; } } /** @return the next smallest number */ public int next() { TreeNode cur = stack.pop(); TreeNode node = cur; if (cur.right != null) { cur = cur.right; while(cur != null){ stack.push(cur); cur = cur.left; } } return node.val; } /** @return whether we have a next smallest number */ public boolean hasNext() { return !stack.isEmpty(); } }

Find local minimum An efficient solution is based on Binary Search. We compare middle element with its neighbors. If middle element is not greater than any of its neighbors, then we return it. If the middle element is greater than its left neighbor, then there is always a local minima in left half (Why? take few examples). If the middle element is greater than its right neighbor, then there is always a local minima in right half (due to same reason as left half).

class GFG { public static int localMinUtil(int[] arr, int low, int high, int n) { int mid = low + (high - low) / 2; if(mid == 0 || arr[mid - 1] > arr[mid] && mid == n - 1 || arr[mid] < arr[mid + 1]) return mid; else if(mid > 0 && arr[mid - 1] < arr[mid]) return localMinUtil(arr, low, mid - 1, n); return localMinUtil(arr, mid + 1, high, n); }

146. LRU Cache Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put. get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1. put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item. Follow up: Could you do both operations in O(1) time complexity?

class LRUCache { class Node { int key, value; Node next; Node(int key, int value) { this.key = key; this.value = value; next = null; } } private int capacity, size; private Node dummy, tail; private Map<Integer, Node> map; public LRUCache(int capacity) { this.capacity = capacity; size = 0; map = new HashMap<>(); dummy = new Node(0,0); tail = dummy; } public int get(int key) { if (!map.containsKey(key)) { return -1; } toTail(key); return tail.value; } public void put(int key, int value) { if (get(key) != -1) { map.get(key).next.value = value; } else { if (size < capacity) { Node node = new Node(key, value); map.put(key, tail); tail.next = node; tail = tail.next; size++; } else { Node first = dummy.next; map.remove(first.key); first.key = key; first.value = value; map.put(key, dummy); toTail(key); } } } private void toTail(int key) { Node pre = map.get(key); Node cur = pre.next; if (cur == tail) { return; } pre.next = cur.next; tail.next = cur; cur.next = null; map.put(key, tail); map.put(pre.next.key, pre); tail = tail.next; } } /** * 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<cur, previous node>

232. Implement Queue using Stacks Implement the following operations of a queue using stacks. push(x) -- Push element x to the back of queue. pop() -- Removes the element from in front of queue. peek() -- Get the front element. empty() -- Return whether the queue is empty. Example: MyQueue queue = new MyQueue(); queue.push(1); queue.push(2); queue.peek(); // returns 1 queue.pop(); // returns 1 queue.empty(); // returns false

class MyQueue { /** Initialize your data structure here. */ private Stack<Integer> stack; public MyQueue() { stack = new Stack<>(); } /** Push element x to the back of queue. */ public void push(int x) { Stack<Integer> temp = new Stack<>(); while (!stack.isEmpty()) { temp.push(stack.pop()); } stack.push(x); while (!temp.isEmpty()) { stack.push(temp.pop()); } } /** Removes the element from in front of queue and returns that element. */ public int pop() { return stack.pop(); } /** Get the front element. */ public int peek() { return stack.peek(); } /** Returns whether the queue is empty. */ public boolean empty() { return stack.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(); */ time: o(n) space: o(n)

304. Range Sum Query 2D - Immutable Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2). Given matrix = [ [3, 0, 1, 4, 2], [5, 6, 3, 2, 1], [1, 2, 0, 1, 5], [4, 1, 0, 1, 7], [1, 0, 3, 0, 5] ] sumRegion(2, 1, 4, 3) -> 8 sumRegion(1, 1, 2, 2) -> 11 sumRegion(1, 2, 2, 4) -> 12 不要每次都重跑的方法?

class NumMatrix { private int[][] dp; public NumMatrix(int[][] matrix) { if (matrix == null || matrix.length == 0) { return; } dp = new int[matrix.length + 1][matrix[0].length + 1]; for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[0].length; j++) { dp[i + 1][j + 1] = dp[i][j + 1] + dp[i + 1][j] - dp[i][j] + matrix[i][j]; } } } public int sumRegion(int row1, int col1, int row2, int col2) { return dp[row2 + 1][col2 + 1] - dp[row1][col2+1] - dp[row2 + 1][col1] + dp[row1][col1]; } }

973. K Closest Points to Origin We have a list of points on the plane. Find the K closest points to the origin (0, 0). (Here, the distance between two points on a plane is the Euclidean distance.) You may return the answer in any order. The answer is guaranteed to be unique (except for the order that it is in.)

class Point { int[] point; int distance; Point(int[] point) { this.point = point; distance = point[0] * point[0] + point[1] * point[1]; } } public int[][] kClosest(int[][] points, int K) { int[][] ans = new int[K][2]; if (points == null || points.length == 0 || points[0] == null || points[0].length == 0) { return ans; } PriorityQueue<Point> pq = new PriorityQueue<>(new Comparator<Point>() { public int compare(Point p1, Point p2) { return p1.distance - p2.distance; } }); for (int[] point : points) { Point newP = new Point(point); pq.offer(newP); } int i = 0; while (!pq.isEmpty()) { ans[i] = pq.poll().point; i++; if (i >= K) break; } return ans; } 存到pq裡面, 但要寫comparator

314. Binary Tree Vertical Order Traversal Given a binary tree, return the vertical order traversal of its nodes' values. (ie, from top to bottom, column by column). If two nodes are in the same row and column, the order should be from left to right. /** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */

class Solution { class NodeAndNum { TreeNode node; int n; NodeAndNum(TreeNode node, int n) { this.node = node; this.n = n; } } public List<List<Integer>> verticalOrder(TreeNode root) { if (root == null) { return new ArrayList<>(); } Queue<NodeAndNum> q = new LinkedList<>(); q.offer(new NodeAndNum(root, 0)); Map<Integer, List<Integer>> map = new TreeMap<>(); while (!q.isEmpty()) { NodeAndNum cur = q.poll(); TreeNode curNode = cur.node; int curNum = cur.n; if (map.containsKey(curNum)) { map.get(curNum).add(curNode.val); } else { map.put(curNum, new ArrayList<Integer>()); map.get(curNum).add(curNode.val); } if (curNode.left != null) { q.offer(new NodeAndNum(curNode.left, curNum-1)); } if (curNode.right != null) { q.offer(new NodeAndNum(curNode.right, curNum+1)); } } List<List<Integer>> ans = new ArrayList<>(); for (List<Integer> list : map.values()) { ans.add(list); } return ans; } } 不要用treemap的方法, 記得min, max (num的range), 之後map.get(i)就可以 不要用class的方法: 存另一個Queue存num, 跟原本的queue同步offer, poll

332. Reconstruct Itinerary Given a list of airline tickets represented by pairs of departure and arrival airports [from, to], reconstruct the itinerary in order. All of the tickets belong to a man who departs from JFK. Thus, the itinerary must begin with JFK. Example 1: Input: [["MUC", "LHR"], ["JFK", "MUC"], ["SFO", "SJC"], ["LHR", "SFO"]] Output: ["JFK", "MUC", "LHR", "SFO", "SJC"]

class Solution { private LinkedList<String> list; private Map<String, PriorityQueue<String>> map; public List<String> findItinerary(String[][] tickets) { if (tickets == null || tickets.length == 0) { return new ArrayList<>(); } map = new HashMap<>(); list = new LinkedList<>(); for (String[] flight : tickets) { String start = flight[0]; String end = flight[1]; if (!map.containsKey(start)) { map.put(start, new PriorityQueue<String>()); } map.get(start).offer(end); } dfs("JFK"); return list; } private void dfs(String str) { PriorityQueue<String> pq = map.get(str); while (pq != null && !pq.isEmpty()) { dfs(pq.poll()); } list.addFirst(str); } } 用linkedlist, addfirst 最後面想不到用背的

114. Flatten Binary Tree to Linked List Given a binary tree, flatten it to a linked list in-place. For example, given the following tree: 1 / \ 2 5 / \ \ 3 4 6 look like: 1 -> 2 -> 3 -> 4 -> 5 -> 6

class Solution { private TreeNode last; public void flatten(TreeNode root) { if (root == null) { return; } if (last != null) { last.right = root; last.left = null; } last = root; TreeNode right = root.right; flatten(root.left); flatten(right); } } time: o(n) space: o(log n)

Convert a non-negative integer to its english words representation. Given input is guaranteed to be less than 231 - 1. Example 1: Input: 123 Output: "One Hundred Twenty Three"

class Solution { private final String[] LESS20 = {"", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight" , "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen" , "Seventeen", "Eighteen", "Nineteen"}; private final String[] TENS = {"", "","Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"}; private final String[] THOUSAND = {"", "Thousand", "Million", "Billion"}; public String numberToWords(int num) { if (num == 0) { return "Zero"; } String ans = ""; int i = 0; while (num > 0) { if (num % 1000 != 0) { ans = helper(num % 1000).trim() + " " + THOUSAND[i] + " " + ans; // System.out.println(ans); } num /= 1000; i++; } return ans.trim(); } private String helper(int num) { if (num < 20) { return LESS20[num] + " "; } else if (num < 100) { return TENS[num / 10] +" "+ LESS20[num % 10] + " "; } else { return LESS20[num / 100] + " Hundred " + helper(num % 100); } } }

336 Palindrome Pairs Given a list of unique words, find all pairs of distinct indices (i, j) in the given list, so that the concatenation of the two words, i.e. words[i] + words[j] is a palindrome. Example 1: Input: ["abcd","dcba","lls","s","sssll"] Output: [[0,1],[1,0],[3,2],[2,4]] Explanation: The palindromes are ["dcbaabcd","abcddcba","slls","llssssll"]

class Solution { public List<List<Integer>> palindromePairs(String[] words) { if (words == null || words.length <= 1) { return new ArrayList<>(); } Map<String, Integer> map = new HashMap<>(); List<List<Integer>> ans = new ArrayList<>(); for (int i = 0; i < words.length; i++) { map.put(words[i], i); } for (int i = 0; i < words.length; i++) { for (int j = 0; j <= words[i].length(); j++) { String s1 = words[i].substring(0, j); String s2 = words[i].substring(j); if (isPalindrome(s1)) { String s2Reverse = new StringBuilder(s2).reverse().toString(); if (map.containsKey(s2Reverse) && map.get(s2Reverse) != i) { List<Integer> list = new ArrayList<>(); list.add(map.get(s2Reverse)); list.add(i); ans.add(list); } } if (isPalindrome(s2)) { String s1Reverse = new StringBuilder(s1).reverse().toString(); if (map.containsKey(s1Reverse) && map.get(s1Reverse) != i && s2.length() != 0) { List<Integer> list = new ArrayList<>(); list.add(i); list.add(map.get(s1Reverse)); ans.add(list); } } } } return ans; } private boolean isPalindrome(String s) { if (s.length() <= 1) { return true; } int left = 0; int right = s.length() - 1; while (left < right) { if (s.charAt(left) != s.charAt(right)) { return false; } else { left++; right--; } } return true; } }

78. Subsets Given a set of distinct integers, nums, return all possible subsets (the power set). Note: The solution set must not contain duplicate subsets.

class Solution { public List<List<Integer>> subsets(int[] nums) { if (nums == null || nums.length == 0) { return new ArrayList<>(); } Arrays.sort(nums); List<List<Integer>> ans = new ArrayList<>(); backtrack(nums, new ArrayList<Integer>(), ans, 0); return ans; } private void backtrack(int[] nums, List<Integer> list, List<List<Integer>> ans, int index) { ans.add(new ArrayList<>(list)); for (int i = index; i < nums.length; i++) { list.add(nums[i]); backtrack(nums, list, ans, i + 1); list.remove(list.size() - 1); } } } 一種是用arraylist一種是Backtracking 這題沒有重複沒有sort也沒差 因為是sub set, 進入backtrack就直接add to ans time: o(2^n) space: o(n)

269. Alien Dictionary There is a new alien language which uses the latin alphabet. However, the order among letters are unknown to you. You receive a list of non-empty words from the dictionary, where words are sorted lexicographically by the rules of this new language. Derive the order of letters in this language. Example 1: Input: [ "wrt", "wrf", "er", "ett", "rftt" ] Output: "wertf"

class Solution { public String alienOrder(String[] words) { if (words == null || words.length == 0) { return ""; } Map<Character, Integer> degree = new HashMap<>(); Map<Character, Set<Character>> map = new HashMap<>(); for (String s : words) { for (char c : s.toCharArray()) { degree.put(c, 0); } } for (int i = 0; i < words.length - 1; i++) { String s1 = words[i]; String s2 = words[i + 1]; int len = Math.min(s1.length(), s2.length()); for (int j = 0; j < len; j++) { char c1 = s1.charAt(j); char c2 = s2.charAt(j); if (c1 != c2) { Set<Character> set = new HashSet<>(); if (map.containsKey(c1)) { set = map.get(c1); } if (!set.contains(c2)) { set.add(c2); degree.put(c2, degree.getOrDefault(c2, 0) + 1); map.put(c1, set); } break; } } } String ans = ""; Queue<Character> q = new LinkedList<>(); for (char c : degree.keySet()) { if (degree.get(c) == 0) { q.offer(c); } } while (!q.isEmpty()) { char c = q.poll(); ans += c; if (map.containsKey(c)) { Set<Character> set = map.get(c); for (char c1 : set) { degree.put(c1, degree.get(c1) - 1); if (degree.get(c1) == 0) { q.offer(c1); } } } } return ans.length() == degree.size()? ans : ""; } }

523. Continuous Subarray Sum Given a list of non-negative numbers and a target integer k, write a function to check if the array has a continuous subarray of size at least 2 that sums up to the multiple of k, that is, sums up to n*k where n is also an integer. Example 1: Input: [23, 2, 4, 6, 7], k=6 Output: True Explanation: Because [2, 4] is a continuous subarray of size 2 and sums up to 6.

class Solution { public boolean checkSubarraySum(int[] nums, int k) { if (nums == null || nums.length <= 1) { return false; } Map<Integer, Integer> map = new HashMap<>(); map.put(0, -1); int sum = 0; for (int i = 0; i < nums.length; i++) { sum += nums[i]; if (k != 0) sum %= k; if (map.containsKey(sum)) { int ind = map.get(sum); if (i - ind > 1) { return true; } } else { map.put(sum, i); } } return false; } } 記得map要先put(0, 1) 是找sum, 不是k - sum 確認index > 1 寫在裡面 注意所有細節 time: o(n) space: o(k)

896. Monotonic Array An array is monotonic if it is either monotone increasing or monotone decreasing. An array A is monotone increasing if for all i <= j, A[i] <= A[j]. An array A is monotone decreasing if for all i <= j, A[i] >= A[j]. Return true if and only if the given array A is monotonic. Input: [1,2,2,3] Output: true

class Solution { public boolean isMonotonic(int[] A) { if (A == null || A.length <= 2) { return true; } int increase = 1; int decrease = 1; for (int i = 1; i < A.length; i++) { if (A[i] > A[i - 1]) { increase++; } else if (A[i] < A[i - 1]) { decrease++; } else { increase++; decrease++; } } return increase == A.length || decrease == A.length; } } time : o(n) space: o(1)

215. Kth Largest Element in an Array (quick sort) Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element. Example 1: Input: [3,2,1,5,6,4] and k = 2 Output: 5

class Solution { public int findKthLargest(int[] nums, int k) { if (nums == null || nums.length == 0) { return -1; } quicksort(nums, 0, nums.length - 1); return nums[nums.length - k]; } private void quicksort(int[] nums, int start, int end) { if (start >= end) return; 這句要記得 int pivot = partition(nums, start, end); quicksort(nums, start, pivot - 1); quicksort(nums, pivot + 1, end); } private int partition(int[] nums, int start, int end) { int pivot = nums[end]; int left = start; int right = end - 1; while (left <= right) { while (left <= right && nums[left] < pivot) { left ++; } while (left <= right && nums[right] > pivot) { right--; } if (left <= right) { int temp = nums[left]; nums[left] = nums[right]; nums[right] = temp; left++; right--; } } nums[end] = nums[left]; nums[left] = pivot; return left; } }

378. Kth Smallest Element in a Sorted Matrix Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth smallest element in the matrix. Note that it is the kth smallest element in the sorted order, not the kth distinct element. matrix = [ [ 1, 5, 9], [10, 11, 13], [12, 13, 15] ], k = 8, return 13.

class Solution { public int kthSmallest(int[][] matrix, int k) { if (matrix == null || matrix.length == 0 || matrix[0].length == 0) { return -1; } PriorityQueue<Integer> pq = new PriorityQueue<>(new Comparator<Integer>() { public int compare(Integer i1, Integer i2) { return i2 - i1; } }); for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[0].length; j++) { if (pq.size() < k) { pq.offer(matrix[i][j]); } else { if (pq.peek() > matrix[i][j]) { pq.poll(); pq.offer(matrix[i][j]); } } } } return pq.peek(); } }

621. Task Scheduler Given a char array representing tasks CPU need to do. It contains capital letters A to Z where different letters represent different tasks. Tasks could be done without original order. Each task could be done in one interval. For each interval, CPU could finish one task or just be idle. However, there is a non-negative cooling interval n that means between two same tasks, there must be at least n intervals that CPU are doing different tasks or just be idle. You need to return the least number of intervals the CPU will take to finish all the given tasks. Input: tasks = ["A","A","A","B","B","B"], n = 2 Output: 8 Explanation: A -> B -> idle -> A -> B -> idle -> A -> B.

class Solution { public int leastInterval(char[] tasks, int n) { if (tasks == null || tasks.length == 0) { return 0; } int max = Integer.MIN_VALUE; int[] arr = new int[26]; for (char c : tasks) { arr[c - 'A']++; max = Math.max(max, arr[c - 'A']); } int ans = n * (max - 1) + max - 1; for (int a : arr) { if (a >= max) { ans++; } } return Math.max(tasks.length, ans); } } 先找出 出現過最多次的char, 可以計算出目前最少要的number(記得減1), 之後檢查是否有其他char也有一樣的長度, 有的話++, 最後回傳max(計算出的長度, task長度) 記得可以用int[26]的方法 記得減1 time: O(n) space: O(26)

91. Decode Ways A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 Given a non-empty string containing only digits, determine the total number of ways to decode it. Example 1: Input: "12" Output: 2 Explanation: It could be decoded as "AB" (1 2) or "L" (12).

class Solution { public int numDecodings(String s) { if (s == null || s.length() == 0) { return 0; } int n = s.length(); int[] dp = new int[n + 1]; dp[n] = 1; if (s.charAt(n - 1) != '0') { dp[n - 1] = 1; } for (int i = s.length() - 2; i >= 0; i--) { if (Integer.valueOf(s.charAt(i)) == '0') { continue; } if (Integer.valueOf(s.substring(i, i + 2)) <= 26) { dp[i] = dp[i + 1] + dp[i + 2]; } else { dp[i] = dp[i + 1]; } } return dp[0]; } } 記得dp的array長度不一樣,之後都要很注意 time: o(n) space: o(1) 我们维护的量res[i]是表示前i个数字有多少种解析的方式,接下来来想想递归式,有两种方式:第一种新加进来的数字不然就是自己比较表示一个字符,那么解析的方式有res[i-1]种,第二种就是新加进来的数字和前一个数字凑成一个字符,解析的方式有res[i-2]种(因为上一个字符和自己凑成了一个)。当然这里要判断前面说的两种情况能否凑成一个字符,也就是范围的判断,如果可以才有对应的解析方式,如果不行,那么就是0。最终结果就是把这两种情况对应的解析方式相加。这里可以把范围分成几个区间: (1)00:res[i]=0(无法解析,没有可行解析方式); (2)10, 20:res[i]=res[i-2](只有第二种情况成立); (3)11-19, 21-26:res[i]=res[i-1]+res[i-2](两种情况都可行); (4)01-09, 27-99:res[i]=res[i-1](只有第一种情况可行);

28. Implement strStr() Implement strStr(). Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack. Example 1: Input: haystack = "hello", needle = "ll" Output: 2

class Solution { public int strStr(String haystack, String needle) { if (needle.equals("")) return 0; if (needle.length() > haystack.length()) return -1; int len = needle.length(); int ans = -1; for (int i = 0; i <= haystack.length() - len; i++) { String cur = haystack.substring(i, i + len); if (cur.equals(needle)) { ans = i; break; } } return ans; } }

560. Subarray Sum Equals K Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k. Example 1: Input:nums = [1,1,1], k = 2 Output: 2 簡化版:只要返回存不存在subarray的sum为k就行

class Solution { public int subarraySum(int[] nums, int k) { if (nums == null || nums.length == 0) { return 0; } int ans = 0; int sum = 0; Map<Integer, Integer> map = new HashMap<>(); map.put(0, 1); for (int n : nums) { sum += n; if (map.containsKey(sum - k)) { ans += map.get(sum - k); } map.put(sum, map.getOrDefault(sum, 0) + 1); } return ans; } } 記得map.put(0,1) first 然後sum - k 這邊要小心不要寫反

34. Find First and Last Position of Element in Sorted Array

class Solution { public int[] searchRange(int[] nums, int target) { if (nums == null || nums.length == 0) { return new int[]{-1, -1}; } int left = 0, right = nums.length - 1; int first = -1, second = -1; while (left < right) { int mid = left + (right - left) / 2; if (nums[mid] < target) { left = mid + 1; } else { right = mid; } } first = nums[left] == target? left : -1; left = 0; right = nums.length - 1; while (left + 1 < right) { int mid = left + (right - left) / 2; if (nums[mid] > target) { right = mid - 1; (其實可以不減一) } else { left = mid; } } if (nums[right] == target) { second = right; } else if (nums[left] == target) { second = left; } return new int[] {first, second}; } } time: log n space O(1) 記得寫的時候多用一些例子來確定大於小於 尤其兩個數字的版本

251. Flatten 2D Vector Design and implement an iterator to flatten a 2d vector. It should support the following operations: next and hasNext.

class Vector2D { int vi, i; int[][] v; public Vector2D(int[][] v) { this.v = v; vi= i = 0; } public int next() { if (hasNext()) { int ret = v[vi][i]; i++; return ret; } return Integer.MIN_VALUE; } public boolean hasNext() { if (vi >= v.length) return false; if (i >= v[vi].length) { i = 0; vi++; return hasNext(); } return true; } } 用Queue會有extra space 用pointer不會 time: o(n) space: o(1)

211. Add and Search Word - Data structure design Design a data structure that supports the following two operations: void addWord(word) bool search(word) search(word) can search a literal word or a regular expression string containing only letters a-z or .. A . means it can represent any one letter.

class WordDictionary { class TrieNode { TrieNode[] node; boolean isEnd; TrieNode () { node = new TrieNode[26]; isEnd = false; } } private TrieNode root; /** Initialize your data structure here. */ public WordDictionary() { root = new TrieNode(); } /** Adds a word into the data structure. */ public void addWord(String word) { if (word == null) return; TrieNode node = root; for (int i = 0; i < word.length(); i++) { if (node.node[word.charAt(i) - 'a'] == null) { node.node[word.charAt(i) - 'a'] = new TrieNode(); } node = node.node[word.charAt(i) - 'a']; if (i == word.length() - 1) { node.isEnd = true; } } } /** Returns if the word is in the data structure. A word could contain the dot character '.' to represent any one letter. */ public boolean search(String word) { return backtrack(word, 0, root); } private boolean backtrack(String word, int index, TrieNode node) { if (index == word.length()) { return node.isEnd; } char c = word.charAt(index); if (c == '.') { for (int i = 0; i < 26; i++) { if (node.node[i] != null && backtrack(word, index + 1, node.node[i])) { return true; } } return false; } else { return node.node[c - 'a'] != null && backtrack(word, index + 1, node.node[c - 'a']); } } } /** * Your WordDictionary object will be instantiated and called as such: * WordDictionary obj = new WordDictionary(); * obj.addWord(word); * boolean param_2 = obj.search(word); */ 新增一個trieNode,裡面有array of TrieNode 和boolean 跑search的時候要用recursion, 記得要check array裡的值是不是null isEnd是改在最後一個index的下一個node的isEnd, 所以 recursion base case: index == word.length()不用減1, 上面add也是等node = next node才改isEnd

45. Jump Game II Given an array of non-negative integers, you are initially positioned at the first index of the array. Each element in the array represents your maximum jump length at that position. Your goal is to reach the last index in the minimum number of jumps. 要到達最後一個index要走幾步 Input: [2,3,1,1,4] Output: 2 Explanation: The minimum number of jumps to reach the last index is 2. Jump 1 step from index 0 to 1, then 3 steps to the last index.

if (nums == null || nums.length == 0) { return 0; } int count = 0; int start = 0; int end = 0; while (end < nums.length - 1) { count++; int far = end; for (int i = start; i <= end; i++) { if (nums[i] + i > far) { far = nums[i] + i; } } start = end + 1; end = far; } return count; } time: o(n) space:o(1)

413. Arithmetic Slices A sequence of number is called arithmetic if it consists of at least three elements and if the difference between any two consecutive elements is the same For example, these are arithmetic sequence: 1, 3, 5, 7, 9 7, 7, 7, 7 3, -1, -5, -9 A zero-indexed array A consisting of N numbers is given. A slice of that array is any pair of integers (P, Q) such that 0 <= P < Q < N. A slice (P, Q) of array A is called arithmetic if the sequence: A[P], A[p + 1], ..., A[Q - 1], A[Q] is arithmetic. In particular, this means that P + 1 < Q. The function should return the number of arithmetic slices in the array A.

method 1: class Solution { private int ans; public int numberOfArithmeticSlices(int[] A) { if (A == null || A.length == 0) { return 0; } ans = 0; for (int i = 1; i <= A.length - 2; i++) { int diff = A[i] - A[i -1]; helper(A, i, 1, diff); } return ans; } private void helper(int[]A, int start, int len, int diff) { if (len >= 3) { ans++; } if (start > A.length - 1) { return; } if (A[start] - A[start - 1] != diff) { return; } helper(A, start + 1, len + 1, diff); } } method 2: public int numberOfArithmeticSlices(int[] A) { if (A == null || A.length == 0) { return 0; } int cur = 0, ans = 0; for (int i = 2; i < A.length; i++) { if (A[i] - A[i-1] == A[i - 1] - A[i - 2]) { cur++; ans += cur; } else { cur = 0; } } return ans; } 我自己是用recursion 解, 但其實可以不用

113. Path Sum II Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given sum. Note: A leaf is a node with no children. 給target sum, 回傳List<List<Integer>>, 裡面的list是滿足path sum = target的 list, 要從root->leaf

private List<List<Integer>> ans; private int target; public List<List<Integer>> pathSum(TreeNode root, int sum) { if (root == null) return new ArrayList<>(); ans = new ArrayList<>(); target = sum; List<Integer> list = new ArrayList<>(); list.add(root.val); helper(root, list, root.val); return ans; } public void helper(TreeNode node, List<Integer> list, int curSum) { if (node.left == null && node.right == null) { if (curSum == target) { ans.add(new ArrayList<>(list)); } return; } if (node.left != null) { list.add(node.left.val); helper(node.left, list, curSum + node.left.val); list.remove(list.size() - 1); } if (node.right != null) { list.add(node.right.val); helper(node.right, list, curSum + node.right.val); list.remove(list.size() - 1); } } 切記: list要remove

332. Reconstruct Itinerary Given a list of airline tickets represented by pairs of departure and arrival airports [from, to], reconstruct the itinerary in order. All of the tickets belong to a man who departs from JFK. Thus, the itinerary must begin with JFK. Note: If there are multiple valid itineraries, you should return the itinerary that has the smallest lexical order when read as a single string. For example, the itinerary ["JFK", "LGA"] has a smaller lexical order than ["JFK", "LGB"]. All airports are represented by three capital letters (IATA code). You may assume all tickets form at least one valid itinerary.

private LinkedList<String> list; Map<String, PriorityQueue<String>> map; public List<String> findItinerary(String[][] tickets) { if (tickets == null || tickets.length == 0) { return new ArrayList<>(); } map = new HashMap<>(); for (String[] flight : tickets) { String start = flight[0]; String end = flight[1]; if (map.containsKey(start)) { map.get(start).offer(flight[1]); } else { map.put(start, new PriorityQueue<String>()); map.get(start).offer(flight[1]); } } list = new LinkedList<>(); dfs("JFK"); return list; } private void dfs (String str) { PriorityQueue<String> pq = map.get(str); while (pq != null && !pq.isEmpty()) { dfs(pq.poll()); } list.addFirst(str); }

54. Spiral Matrix Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order. Example 1: Input: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] Output: [1,2,3,6,9,8,7,4,5]

private List<Integer> ans; private int top, bottom, left, right; public List<Integer> spiralOrder(int[][] matrix) { if (matrix == null || matrix.length == 0) return new ArrayList<>(); ans = new ArrayList<>(); top = 0; bottom = matrix.length - 1; left = 0; right = matrix[0].length - 1; while (ans.size() < matrix.length * matrix[0].length) { right(matrix, top, left); down(matrix, top, right); left(matrix, bottom, right); up(matrix, bottom, left); } return ans; } private void right(int[][]matrix, int i, int j) { if (left > right || bottom < top) return; for (int ind = j; ind <= right; ind++) { ans.add(matrix[i][ind]); } top++; } private void down(int[][]matrix, int i, int j) { if (left > right || bottom < top) return; for (int ind = i; ind <= bottom; ind++) { ans.add(matrix[ind][j]); } right--; } private void left(int[][]matrix, int i, int j) { if (left > right || bottom < top) return; for (int ind = j; ind >= left; ind--) { ans.add(matrix[i][ind]); } bottom--; } private void up(int[][]matrix, int i, int j) { if (left > right || bottom < top) return; for (int ind = i; ind >= top; ind--) { ans.add(matrix[ind][j]); } left++; } time: o(mn) space: o(1)

545. Boundary of Binary Tree Given a binary tree, return the values of its boundary in anti-clockwise direction starting from root. Boundary includes left boundary, leaves, and right boundary in order without duplicate nodes. Left boundary is defined as the path from root to the left-most node. Right boundary is defined as the path from root to the right-most node. If the root doesn't have left subtree or right subtree, then the root itself is left boundary or right boundary. Note this definition only applies to the input binary tree, and not applies to any subtrees. The left-most node is defined as a leaf node you could reach when you always firstly travel to the left subtree if exists. If not, travel to the right subtree. Repeat until you reach a leaf node. The right-most node is also defined by the same way with left and right exchanged.

private List<Integer> ans; public List<Integer> boundaryOfBinaryTree(TreeNode root) { if (root == null) return new ArrayList<>(); ans = new ArrayList<>(); ans.add(root.val); left(root.left); bottom(root.left); bottom(root.right); right(root.right); return ans; } private void left(TreeNode node) { if (node == null || (node.left == null && node.right == null)) { return; } ans.add(node.val); if (node.left == null) { left(node.right); } else { left(node.left); } } private void bottom (TreeNode node) { if (node == null) return; if (node.left == null && node.right == null) { ans.add(node.val); return; } bottom(node.left); bottom(node.right); } private void right (TreeNode node) { if (node == null || (node.left == null && node.right == null)) { return; } if (node.right == null) { right(node.left); } else { right(node.right); } ans.add(node.val); } 每個method time: o(n) space: o(log n)

39. Combination Sum Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target. The same repeated number may be chosen from candidates unlimited number of times. Note: All numbers (including target) will be positive integers. The solution set must not contain duplicate combinations. Example 1: Input: candidates = [2,3,6,7], target = 7, A solution set is: [ [7], [2,2,3] ]

private List<List<Integer>> ans; private int tar; public List<List<Integer>> combinationSum(int[] nums, int target) { if (nums == null || nums.length == 0) { return new ArrayList<>(); } ans = new ArrayList<>(); tar = target; Arrays.sort(nums); backtrack(nums, 0, 0, new ArrayList<>()); return ans; } private void backtrack(int[] nums, int curSum, int start, List<Integer> list) { if (curSum > tar) return; if (curSum == tar) { ans.add(new ArrayList<>(list)); } for (int i = start; i < nums.length; i++) { list.add(nums[i]); backtrack(nums, curSum + nums[i], i, list); list.remove(list.size() - 1); } } time: o(n!) space: o(n)

40. Combination Sum II Given a collection of candidate numbers (candidates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target. Each number in candidates may only be used once in the combination. Note: All numbers (including target) will be positive integers. The solution set must not contain duplicate combinations. Input: candidates = [2,5,2,1,2], target = 5, A solution set is: [ [1,2,2], [5] ]

private List<List<Integer>> ans; private int tar; public List<List<Integer>> combinationSum2(int[] nums, int target) { if (nums == null || nums.length == 0) { return new ArrayList<>(); } Arrays.sort(nums); ans = new ArrayList<>(); tar = target; backtrack(nums, 0, 0, new ArrayList<>()); return ans; } private void backtrack(int[] nums, int start, int curSum, List<Integer> list) { if (curSum > tar) return; if (curSum == tar) { ans.add(new ArrayList<>(list)); return; } for (int i = start; i < nums.length; i++) { if (i > start && nums[i] == nums[i - 1]) continue; list.add(nums[i]); backtrack(nums, i+1, curSum + nums[i], list); list.remove(list.size() - 1); } } 要考慮重複 time: o(n!) space: o(n)

285. Inorder Successor in BST Given a binary search tree and a node in it, find the in-order successor of that node in the BST. The successor of a node p is the node with the smallest key greater than p.val.

public TreeNode inorderSuccessor(TreeNode root, TreeNode p) { if (root == null) return null; if (root.val <= p.val) { return inorderSuccessor(root.right, p); } else { TreeNode left = inorderSuccessor(root.left, p); return left == null? root: left; } } time: o(h) space: o(h)

47. Permutations II Given a collection of numbers that might contain duplicates, return all possible unique permutations. Example: Input: [1,1,2] Output: [ [1,1,2], [1,2,1], [2,1,1] ]

private List<List<Integer>> ans; public List<List<Integer>> permuteUnique(int[] nums) { ans = new ArrayList<>(); if (nums == null || nums.length == 0) { return ans; } Arrays.sort(nums); boolean[] used = new boolean[nums.length]; helper(nums, used, new ArrayList<>()); return ans; } private void helper(int[]nums, boolean[] used, List<Integer> list) { if (list.size() == nums.length) { ans.add(new ArrayList<>(list)); return; } for (int i = 0; i < nums.length; i++) { if (!used[i]) { if (i > 0 && nums[i] == nums[i - 1]) { if (!used[i - 1]) { continue; } } used[i] = true; list.add(nums[i]); helper(nums, used, list); list.remove(list.size() - 1); used[i] = false; } } } time: O(n! * n) space: o(n)

17. Letter Combinations of a Phone Number Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent. A mapping of digit to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters.

private List<String> list; public List<String> letterCombinations(String digits) { if (digits == null || digits.length() == 0) { return new ArrayList<>(); } String[] strs = new String[]{"", "*", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; list = new ArrayList<>(); helper(digits, 0, strs, ""); return list; } private void helper(String digits, int start, String[] strs, String num) { if (digits.length() == num.length()) { list.add(num); return; } int ind = digits.charAt(start) - '0'; String s = strs[ind]; for (int i = 0; i < s.length(); i++) { helper(digits, start + 1, strs, num + s.charAt(i)); } } backtrack應用

301. Remove Invalid Parentheses Remove the minimum number of invalid parentheses in order to make the input string valid. Return all possible results. Note: The input string may contain letters other than the parentheses ( and ).

private List<String> list; public List<String> removeInvalidParentheses(String s) { // count how many l, r should be removed // dfs(string s, int l, int r, int start) (consider duplicate) // isValid method list = new ArrayList<>(); int l = 0, r = 0; for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == '(') { l++; } else if (s.charAt(i) == ')') { if (l > 0) { l--; } else { r++; } } } dfs(s, l, r, 0); return list; } private void dfs(String s, int l, int r, int start) { if (l == 0 && r == 0) { if (isValid(s)) { list.add(s); } return; } for (int i = start; i < s.length(); i++) { if (i != start && s.charAt(i) == s.charAt(i - 1)) continue; if (s.charAt(i) == ')') { if (r > 0) { String newS = s.substring(0, i) + s.substring(i + 1); dfs(newS, l, r-1, i); } } if (s.charAt(i) == '(') { if (l > 0) { String newS = s.substring(0, i) + s.substring(i + 1); dfs(newS, l-1, r, i); } } } } private boolean isValid(String s) { int count = 0; for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == '(') { count++; } else if (s.charAt(i) == ')') { count--; } if (count < 0) return false; } return count == 0; } 三步驟, 先計算l, r, 之後dfs, 然後寫 isValid 記得計算重複

295. Find Median from Data Stream Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value. For example, [2,3,4], the median is 3 [2,3], the median is (2 + 3) / 2 = 2.5 Design a data structure that supports the following two operations: void addNum(int num) - Add a integer number from the data stream to the data structure. double findMedian() - Return the median of all elements so far.

private PriorityQueue<Integer> left, right; private int curSize; public MedianFinder() { left = new PriorityQueue<>(new Comparator<Integer>() { public int compare(Integer n1, Integer n2) { return n2 - n1; } }); right = new PriorityQueue<>(); curSize = 0; } public void addNum(int num) { left.offer(num); if (curSize % 2 == 0) { if (right.isEmpty()) { curSize++; return; } else { if (right.peek() < left.peek()) { int tempL = left.poll(); int tempR = right.poll(); left.offer(tempR); right.offer(tempL); } curSize++; } } else { right.offer(left.poll()); curSize++; } } public double findMedian() { if (curSize % 2 == 1) { return left.peek(); } return Double.valueOf((left.peek() + right.peek()) * 0.5); } 用兩個priorityQueue 一個左 一個右來存 左邊的要override Comparator time: o(n) space: o(1)

703. Kth Largest Element in a Stream Design a class to find the kth largest element in a stream. Note that it is the kth largest element in the sorted order, not the kth distinct element. Your KthLargest class will have a constructor which accepts an integer k and an integer array nums, which contains initial elements from the stream. For each call to the method KthLargest.add, return the element representing the kth largest element in the stream.

private PriorityQueue<Integer> pq; private int size; public KthLargest(int k, int[] nums) { if (nums == null) return; pq = new PriorityQueue<>(); size = k; for (int i = 0; i < nums.length; i++) { add(nums[i]); } } public int add(int val) { if (pq.size() < size) { pq.offer(val); } else { if (val > pq.peek()) { pq.poll(); pq.offer(val); } } return pq.peek(); } time: n log k space: k

341. Flatten Nested List Iterator Given a nested list of integers, implement an iterator to flatten it. Each element is either an integer, or a list -- whose elements may also be integers or other lists.

private Stack<NestedInteger> stack; public NestedIterator(List<NestedInteger> nestedList) { stack = new Stack<>(); for (int i = nestedList.size() - 1; i >= 0; i--) { stack.push(nestedList.get(i)); } } @Override public Integer next() { return stack.pop().getInteger(); } @Override public boolean hasNext() { while (!stack.isEmpty()) { NestedInteger cur = stack.peek(); if (cur.isInteger()) { return true; } stack.pop(); for (int i = cur.getList().size() - 1; i >= 0; i--) { stack.push(cur.getList().get(i)); } } return false; } 用stack來解 time: O(element n) spack: O(element n)

230. Kth Smallest Element in a BST Given a binary search tree, write a function kthSmallest to find the kth smallest element in it.

private Stack<TreeNode> stack; public int kthSmallest(TreeNode root, int k) { if ((root.left == null && root.right == null)) { return root.val; } stack = new Stack<>(); TreeNode cur = root; while (cur != null) { stack.push(cur); cur = cur.left; } int ans = 0; for (int i = 0; i < k; i++) { ans = next(); } return ans; } private int next() { TreeNode cur = stack.pop(); int ans = cur.val; if (cur.right != null) { cur = cur.right; while (cur != null) { stack.push(cur); cur = cur.left; } } return ans; } time: O(n) space: O(h) tree height

226. Invert Binary Tree

public TreeNode invertTree(TreeNode root) { if (root == null) return null; TreeNode temp = root.right; root.right = root.left; root.left = temp; invertTree(root.left); invertTree(root.right); return root; } time: o(n) space: o(h) 記得要return root

60. Permutation Sequence The set [1,2,3,...,n] contains a total of n! unique permutations. By listing and labeling all of the permutations in order, we get the following sequence for n = 3: "123" "132" "213" "231" "312" "321" Given n and k, return the kth permutation sequence. 很難==

private String ans; private int cur; public String getPermutation(int n, int k) { if (n == 0 || k == 0) { return ""; } StringBuilder sb = new StringBuilder(); boolean[] used = new boolean[n]; int[] nums = new int[n]; for (int i = 0; i < n; i++) { nums[i] = i + 1; } cur = 0; backtrack(sb, nums, k, used); return ans; } private void backtrack(StringBuilder sb, int[] nums, int target, boolean[] used) { if (cur == target) { return; } if (sb.length() == nums.length) { cur ++; if (cur == target) { ans = sb.toString(); } sb = new StringBuilder(); return; } for (int i = 0; i < nums.length; i++) { if (!used[i]) { sb.append(nums[i]); used[i] = true; backtrack(sb, nums, target, used); sb.setLength(sb.length() - 1); used[i] = false; } } }

79. Word Search Given a 2D board and a word, find if the word exists in the grid. The word can be constructed from letters of sequentially adjacent cell, where "adjacent" cells are those horizontally or vertically neighboring. The same letter cell may not be used more than once. Example: board = [ ['A','B','C','E'], ['S','F','C','S'], ['A','D','E','E'] ] Given word = "ABCCED", return true. Given word = "SEE", return true. Given word = "ABCB", return false.

private String tar; private boolean ans; public boolean exist(char[][] board, String word) { if (word.equals("")) return true; if (board == null || board[0] == null || board.length == 0 || board[0].length == 0) { return false; } tar = word; boolean[][] visited = new boolean[board.length][board[0].length]; ans = false; for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[i].length; j++) { helper(board, visited, i, j, 0, ""); if (ans) return ans; } } return ans; } private void helper(char[][] chars, boolean[][] visited, int i, int j, int start, String s) { if (ans) return; if (s.length() == tar.length()) { if (s.equals(tar)) { ans = true; } return; } if (i < 0 || i >= chars.length || j < 0 || j >= chars[0].length) return; if (visited[i][j]) return; if (chars[i][j] != tar.charAt(start)) return; visited[i][j] = true; helper(chars, visited, i - 1, j, start + 1, s + chars[i][j]); helper(chars, visited, i + 1, j, start + 1, s + chars[i][j]); helper(chars, visited, i, j - 1, start + 1, s + chars[i][j]); helper(chars, visited, i, j + 1, start + 1, s + chars[i][j]); visited[i][j] = false; } time: o((mn)^2) space: o(mn) -> boolean

112. Path Sum Given a binary tree and a sum, determine if the tree has a root-to-leaf path such that adding up all the values along the path equals the given sum. Note: A leaf is a node with no children. root到leaf

private boolean sumEqual; private int target; public boolean hasPathSum(TreeNode root, int sum) { if (root == null) return false; sumEqual = false; target = sum; helper(root, 0); return sumEqual; } private void helper(TreeNode root, int curSum) { curSum += root.val; if (root.left == null && root.right == null) { if (curSum == target) { sumEqual = true; return; } } if (root.left != null) { helper(root.left, curSum); } if (root.right != null) { helper(root.right, curSum); } } time: o(n) space: o(h)

48. Rotate Image You are given an n x n 2D matrix representing an image. Rotate the image by 90 degrees (clockwise). Given input matrix = [ [1,2,3], [4,5,6], [7,8,9] ], rotate the input matrix in-place such that it becomes: [ [7,4,1], [8,5,2], [9,6,3] ]

private boolean[][] visited; public void rotate(int[][] matrix) { if (matrix == null || matrix.length == 0) { return; } visited = new boolean[matrix.length][matrix.length]; for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[0].length; j++) { helper(matrix, i, j, matrix[i][j]); } } } private void helper(int[][] matrix, int i, int j, int value) { if (visited[i][j]) { return; } int i2 = j; int j2 = matrix.length - 1 - i; visited[i][j] = true; int temp = matrix[i2][j2]; matrix[i2][j2] = value; helper(matrix, i2, j2, temp); } 也有reverse, transpose的方法 public void rotate(int[][] matrix) { if (matrix == null || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) { return; } //transpose for (int i = 0; i < matrix.length; i++) { for (int j = i; j < matrix[i].length; j++) { int temp = matrix[i][j]; matrix[i][j] = matrix[j][i]; matrix[j][i] = temp; } } //reverse for (int i = 0; i < matrix.length; i++) { int start = 0; int end = matrix[i].length - 1; while (start < end) { int temp = matrix[i][start]; matrix[i][start] = matrix[i][end]; matrix[i][end] = temp; start++; end--; } } } time: o(n) space: o(1) tanspose記得不要重複交換, so j start from i

333. Largest BST Subtree Given a binary tree, find the largest subtree which is a Binary Search Tree (BST), where largest means subtree with largest number of nodes in it. Note: A subtree must include all of its descendants.

private int ans ; private int curSum; public int largestBSTSubtree(TreeNode root) { if (root == null) return 0; ans = 0; helper(root); return ans; } private void helper(TreeNode root) { if (root == null) return; curSum = 0; boolean isB = isBST(root, Integer.MIN_VALUE, Integer.MAX_VALUE); if (isB) { ans = Math.max(ans, curSum); return; } helper(root.left); helper(root.right); } private boolean isBST(TreeNode root, int min, int max) { if (root == null) return true; curSum++; if (root.val <= min || root.val >= max) { return false; } return isBST(root.left, min, Math.min(root.val, max)) && isBST(root.right, Math.max(min, root.val), max); } time: o(n) space: o(n)?

250. Count Univalue Subtrees Given a binary tree, count the number of uni-value subtrees. A Uni-value subtree means all nodes of the subtree have the same value.

private int count; public int countUnivalSubtrees(TreeNode root) { if (root == null) { return 0; } count = 0; helper(root); return count; } private boolean helper(TreeNode root) { if (root == null) { reutrn true; } boolean left = helper(root.left); boolean right = hlper(root.right); if (left && right && (root.left == null || root.val == left.val) && (root.right == null || root.val == right.val)) { count++; return true; } return false; } time: o(n) space: o(log n)

364. Nested List Weight Sum II Given a nested list of integers, return the sum of all integers in the list weighted by their depth. Each element is either an integer, or a list -- whose elements may also be integers or other lists. Different from the previous question where weight is increasing from root to leaf, now the weight is defined from bottom up. i.e., the leaf level integers have weight 1, and the root level integers have the largest weight. 倒過來, 最裡面的depth = 1

private int max = 0; public int depthSumInverse(List<NestedInteger> list) { if (list == null || list.size() == 0) { return 0; } getDepth(list, 1); return getSum(list, max, 0); } private void getDepth(List<NestedInteger> list, int depth) { if (list == null || list.size() == 0) { return; } max = Math.max(max, depth); for (NestedInteger i: list) { if (! i.isInteger()) { getDepth(i.getList(), depth + 1); } } } private int getSum(List<NestedInteger> list, int depth, int sum) { if (list == null || list.size() == 0) { return sum; } for (NestedInteger i : list) { if (i.isInteger()) { sum += i.getInteger() * depth; } else { sum += getSum(i.getList(), depth - 1, 0); } } return sum; } time: o(n) n = size of list space: o(1) 用recursion

124. Binary Tree Maximum Path Sum Given a non-empty binary tree, find the maximum path sum. For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The path must contain at least one node and does not need to go through the root.

private int max; public int maxPathSum(TreeNode root) { if (root == null) return 0; max = Integer.MIN_VALUE; helper(root); return max; } private int helper(TreeNode root) { if (root == null) return 0; int left = Math.max(helper(root.left), 0); int right = Math.max(helper(root.right), 0); int sum = root.val + left + right; max = Math.max(sum, max); return Math.max(left, right) + root.val; } 每個node都可以選擇左邊or右邊走, 但如果今天左右都<0, 乾脆停在自己

155. Min Stack Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. push(x) -- Push element x onto stack. pop() -- Removes the element on top of the stack. top() -- Get the top element. getMin() -- Retrieve the minimum element in the stack.

private int min; private Stack<Integer> stack; public MinStack() { min = Integer.MAX_VALUE; stack = new Stack<>(); } public void push(int x) { if (x <= min) { stack.push(min); min = x; } stack.push(x); } public void pop() { if (stack.pop() == min) { min = stack.pop(); } } public int top() { return stack.peek(); } public int getMin() { return min; } 當push的數字比min小的時候, push min再push 數字, 同時update min, 這樣可以確保下次pop()的時候知道下一次的min是誰 當pop的數字==min的時候, pop兩次並update min 記得 push是小於"等於"min time: o(1) space: o(n) (stack)

129. Sum Root to Leaf Numbers Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number. An example is the root-to-leaf path 1->2->3 which represents the number 123. Find the total sum of all root-to-leaf numbers. Note: A leaf is a node with no children. Example: Input: [1,2,3] 1 / \ 2 3 Output: 25 (12 + 13 = 25)

private int sum; public int sumNumbers(TreeNode root) { if (root == null) return 0; sum = 0; helper(root, root.val); return sum; } private void helper(TreeNode node, int singleSum) { if (node.left == null && node.right == null) { sum += singleSum; return; } if (node.left != null) { helper(node.left, 10 * singleSum + node.left.val); } if (node.right != null) { helper(node.right, 10 * singleSum + node.right.val); } } global var sum記得要initiate, helper 是void, 下面變數是node.left.val (不是cur node.val因為已經加過了)

437. Path Sum III You are given a binary tree in which each node contains an integer value. Find the number of paths that sum to a given value. The path does not need to start or end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes). The tree has no more than 1,000 nodes and the values are in the range -1,000,000 to 1,000,000.

private int target, ans; public int pathSum(TreeNode root, int sum) { if (root == null) return 0; target = sum; ans = 0; helper(root); return ans; } private void helper(TreeNode node) { if (node == null) return; helper2(node, node.val); helper(node.left); helper(node.right); } private void helper2(TreeNode node, int curSum) { if (curSum == target) { ans++; } if (node.left == null && node.right == null) return; if (node.left != null) helper2(node.left, curSum + node.left.val); if (node.right != null) helper2(node.right, curSum + node.right.val); } 因為path是可以隨時從任何的node開始,所以使用兩個helper function,一個是node會一直跑, 一個是計算sum 等於是每一個node都會當作起點, 去計算所有可能性 space: O(n) time: 看樹的形狀 balanced tree: O(n log n)

438. Find All Anagrams in a String Given a string s and a non-empty string p, find all the start indices of p's anagrams in s. Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100.

public List<Integer> findAnagrams(String s, String t) { List<Integer> result = new LinkedList<>(); if(t.length()> s.length()) return result; Map<Character, Integer> map = new HashMap<>(); for(char c : t.toCharArray()){ map.put(c, map.getOrDefault(c, 0) + 1); } int counter = map.size(); int begin = 0, end = 0; while(end < s.length()){ char c = s.charAt(end); if( map.containsKey(c) ){ map.put(c, map.get(c)-1); if(map.get(c) == 0) counter--; } end++; while(counter == 0){ char tempc = s.charAt(begin); if(map.containsKey(tempc)){ map.put(tempc, map.get(tempc) + 1); if(map.get(tempc) > 0){ counter++; } } if(end-begin == t.length()){ result.add(begin); } begin++; } } return result; } 用sliding window, 有end, begin, counter(map.size()), map存char, count, end每次都會+1, 如果遇到p有的char, map--, 如果counter變成0的時候進去start, 把map加回來, check長度相減=len(p)

674. Longest Continuous Increasing Subsequence

public int findLengthOfLCIS(int[] nums) { if (nums == null || nums.length == 0) { return 0; } int max = 1; int cur = 1; for (int i = 1; i < nums.length; i++) { if (nums[i] > nums[i - 1]) { cur++; } else { cur = 1; } max = Math.max(max, cur); } return max; } time: o(n) space: o(1)

94. Binary Tree Inorder Traversal Given a binary tree, return the inorder traversal of its nodes' values. Example: Input: [1,null,2,3] 1 \ 2 / 3 Output: [1,3,2]

public List<Integer> inorderTraversal(TreeNode root) { List<Integer> list = new ArrayList<>(); if (root == null) return list; List<Integer> left = inorderTraversal(root.left); List<Integer> right = inorderTraversal(root.right); list.addAll(left); list.add(root.val); list.addAll(right); return list; } stack: public List<Integer> inorderTraversal(TreeNode root) { if (root == null) { return new ArrayList<>(); } List<Integer> list = new ArrayList<>(); Stack<TreeNode> stack = new Stack(); stack.push(root); while (!stack.isEmpty()) { TreeNode tmp = stack.pop(); System.out.println(tmp.val); if (tmp.left != null) { stack.push(tmp); stack.push(tmp.left); tmp.left = null; } else { list.add(tmp.val); if (tmp.right != null) { stack.push(tmp.right); } } } return list; }

145. Binary Tree Postorder Traversal Given a binary tree, return the postorder traversal of its nodes' values. Example: Input: [1,null,2,3] 1 \ 2 / 3 Output: [3,2,1]

public List<Integer> postorderTraversal(TreeNode root) { if (root == null) { return new ArrayList<>(); } List<Integer> list = new ArrayList<>(); List<Integer> left = postorderTraversal(root.left); List<Integer> right = postorderTraversal(root.right); list.addAll(left); list.addAll(right); list.add(root.val); return list; }

144. Binary Tree Preorder Traversal Given a binary tree, return the preorder traversal of its nodes' values. return List<Integer>

public List<Integer> preorderTraversal(TreeNode root) { List<Integer> list = new ArrayList<>(); if (root == null) return list; list.add(root.val); List<Integer> left = preorderTraversal(root.left); List<Integer> right = preorderTraversal(root.right); list.addAll(left); list.addAll(right); return list; } stack方法: public List<Integer> preorderTraversal(TreeNode root) { List<Integer> list = new ArrayList<>(); Stack<TreeNode> stack = new Stack<>(); if (root == null) { return list; } stack.push(root); while (!stack.isEmpty()) { TreeNode cur = stack.pop(); list.add(cur.val); if(cur.right != null) { stack.push(cur.right); } if(cur.left != null) { stack.push(cur.left); } } return list; }

199. Binary Tree Right Side View Given a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom.

public List<Integer> rightSideView(TreeNode root) { if (root == null) { return new ArrayList<>(); } List<Integer> list = new ArrayList<>(); Queue<TreeNode> q = new LinkedList<>(); q.offer(root); while (!q.isEmpty()) { int size = q.size(); for (int i = 0; i < size; i++) { TreeNode temp = q.poll(); if (i == 0) { list.add(temp.val); } if (temp.right != null) { q.offer(temp.right); } if (temp.left != null) { q.offer(temp.left); } } } return list; } time: o(n) space: o(n)

57. Insert Interval Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary). You may assume that the intervals were initially sorted according to their start times. /** * Definition for an interval. * public class Interval { * int start; * int end; * Interval() { start = 0; end = 0; } * Interval(int s, int e) { start = s; end = e; } * } */

public List<Interval> insert(List<Interval> intervals, Interval newInterval) { // 1. separate: a) i.end < new.start -> add i b) new.end < i.start -> add new, i // 2. merge -> min(i.start, new.start) max(i.end, new.end) List<Interval> ans = new ArrayList<>(); for (Interval i : intervals) { if (newInterval == null || i.end < newInterval.start) { ans.add(i); } else if (newInterval.end < i.start) { ans.add(newInterval); ans.add(i); newInterval = null; } else { newInterval.start = Math.min(i.start, newInterval.start); newInterval.end = Math.max(i.end, newInterval.end); } } if (newInterval != null) { ans.add(newInterval); } return ans; } 考慮什麼時候要insert newInterval, 注意如果可以merge, merge之後再去重跑loop而不是直接加進ans

46. Permutations Given a collection of distinct integers, return all possible permutations. Example: Input: [1,2,3] Output: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]

public List<List<Integer>> permute(int[] nums) { if (nums == null || nums.length == 0) return new ArrayList<>(); List<List<Integer>> ans = new ArrayList<>(); helper(nums, ans, new ArrayList<>()); return ans; } private void helper(int[] nums, List<List<Integer>> ans, List<Integer> list) { if (list.size() == nums.length) { ans.add(new ArrayList<>(list)); return; } for (int i = 0; i < nums.length; i++) { if (!list.contains(nums[i])) { list.add(nums[i]); helper(nums, ans, list); list.remove(list.size() - 1); } } } time: o (n*n) space: o(n)?

90. Subsets II Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power set).

public List<List<Integer>> subsetsWithDup(int[] nums) { if (nums == null || nums.length == 0) { return new ArrayList<>(); } List<List<Integer>> ans = new ArrayList<>(); Arrays.sort(nums); backtrack(nums, ans, new ArrayList<>(), 0); return ans; } private void backtrack(int[] nums, List<List<Integer>> ans, List<Integer> list, int start) { ans.add(new ArrayList<>(list)); if (start >= nums.length) { return; } for (int i = start; i < nums.length; i++) { if (i != start && nums[i] == nums[i - 1]) { continue; } list.add(nums[i]); backtrack(nums, ans, list, i + 1); list.remove(list.size() - 1); } } 記得要sort ans.add(要new) time: o(2^n) space: o(n)

15. 3Sum Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero. Note: The solution set must not contain duplicate triplets. Example: Given array nums = [-1, 0, 1, 2, -1, -4], A solution set is: [ [-1, 0, 1], [-1, -1, 2] ]

public List<List<Integer>> threeSum(int[] nums) { if (nums == null || nums.length == 0) { return new ArrayList<>(); } Arrays.sort(nums); List<List<Integer>> ans = new ArrayList<>(); for(int i = 0; i <= nums.length - 3; i++) { while (i != 0 && i <= nums.length - 3 && nums[i] == nums[i - 1]) { i++; } int target = -nums[i]; int l = i + 1; int r = nums.length - 1; List<Integer> list = new ArrayList<>(); while (l < r) { if (nums[l] + nums[r] == target) { ans.add(Arrays.asList(nums[i], nums[l], nums[r])); list = new ArrayList<>(); l++; r--; while (l < r && nums[l] == nums[l - 1]) l++; while (l < r && nums[r] == nums[r + 1]) r--; } else if (nums[l] + nums[r] > target) { r--; } else { l++; } } } return ans; } 用two pointer, 但是記得要避免重複,所以一開始要sort, 中間也要確認l, r, i有沒有重複了 time: (n平方) space: o (1)

103. Binary Tree Zigzag Level Order Traversal Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between). For example: Given binary tree [3,9,20,null,null,15,7], return its zigzag level order traversal as: [ [3], [20,9], [15,7] ]

public List<List<Integer>> zigzagLevelOrder(TreeNode root) { if (root == null) { return new ArrayList<>(); } List<List<Integer>> ans = new ArrayList<>(); Deque<TreeNode> q = new LinkedList<>(); boolean fromLeft = false; q.addFirst(root); while (!q.isEmpty()) { List<Integer> list = new ArrayList<>(); int size = q.size(); for (int i = 0; i < size; i++) { if (!fromLeft) { TreeNode temp = q.pollFirst(); list.add(temp.val); if (temp.left != null) { q.offerLast(temp.left); } if (temp.right != null) { q.offerLast(temp.right); } } else { TreeNode temp = q.pollLast(); list.add(temp.val); if (temp.right != null) { q.offerFirst(temp.right); } if (temp.left != null) { q.offerFirst(temp.left); } } } ans.add(list); fromLeft = !fromLeft; } return ans; } 用Deque, 如果pollLast, 就從node.right開始存,存進去則是offerFirst 拿出來跟存進去一定相反 time: o(n) space: o(n)

49. Group Anagrams Given an array of strings, group anagrams together. Example: Input: ["eat", "tea", "tan", "ate", "nat", "bat"], Output: [ ["ate","eat","tea"], ["nat","tan"], ["bat"] ]

public List<List<String>> groupAnagrams(String[] strs) { if (strs == null || strs.length == 0) { return new ArrayList<>(); } Map<String, List<String>> map = new HashMap<>(); for (String s : strs) { char[] chars = s.toCharArray(); Arrays.sort(chars); String sortedS = new String(chars); if (!map.containsKey(sortedS)) { map.put(sortedS, new ArrayList<String>()); } map.get(sortedS).add(s); } return new ArrayList<List<String>>(map.values()); } map.values()可以得到list map.keySet()可以得到set time: o(n) space: o(n) 記得return 是new arrayList 不是直接回傳 map.values()

22. Generate Parentheses Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

public List<String> generateParenthesis(int n) { if (n == 0) return new ArrayList<>(); List<String> list = new ArrayList<>(); StringBuilder sb = new StringBuilder(); backtrack(list, sb, 0, 0, n); return list; } private void backtrack(List<String> list, StringBuilder sb, int left, int right, int n) { if (sb.length() == n * 2) { list.add(sb.toString()); return; } if (left < n) { sb.append("("); backtrack(list, sb, left + 1, right, n); sb.setLength(sb.length() - 1); } if (right < left) { sb.append(")"); backtrack(list, sb, left, right + 1, n); sb.setLength(sb.length() - 1); } }

2. Add Two Numbers You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. You may assume the two numbers do not contain any leading zero, except the number 0 itself.

public ListNode addTwoNumbers(ListNode l1, ListNode l2) { if (l1 == null) return l2; if (l2 == null) return l1; int carry = 0; ListNode dummy = new ListNode(0); ListNode cur = dummy; while (l1 != null || l2 != null) { if (l1 == null) { carry += l2.val; cur.next = new ListNode(carry % 10); l2 = l2.next; } else if (l2 == null) { carry += l1.val; cur.next = new ListNode(carry % 10); l1 = l1.next; } else { carry += l1.val + l2.val; cur.next = new ListNode(carry % 10); l1 = l1.next; l2 = l2.next; } carry /= 10; cur = cur.next; } if (carry > 0) { cur.next = new ListNode(carry); } return dummy.next; }

445. Add Two Numbers II You are given two non-empty linked lists representing two non-negative integers. The most significant digit comes first and each of their nodes contain a single digit. Add the two numbers and return it as a linked list. You may assume the two numbers do not contain any leading zero, except the number 0 itself. Follow up: What if you cannot modify the input lists? In other words, reversing the lists is not allowed.

public ListNode addTwoNumbers(ListNode l1, ListNode l2) { if (l1 == null) return l2; if (l2 == null) return l1; Stack<Integer> stack1 = new Stack<>(); Stack<Integer> stack2 = new Stack<>(); while (l1 != null) { stack1.push(l1.val); l1 = l1.next; } while (l2 != null) { stack2.push(l2.val); l2 = l2.next; } ListNode pre = new ListNode(0); int sum = 0; while (!stack1.isEmpty() || !stack2.isEmpty()) { if (stack1.isEmpty()) { sum += stack2.pop(); } else if (stack2.isEmpty()) { sum += stack1.pop(); } else { sum += (stack1.pop() + stack2.pop()); } ListNode temp = new ListNode(sum / 10); pre.val = sum % 10; sum /= 10; temp.next = pre; pre = temp; } return pre.val == 0? pre.next: pre; } time: o(m+n) space: o(m+n)

142. Linked List Cycle II Given a linked list, return the node where the cycle begins. If there is no cycle, return null. To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list. Note: Do not modify the linked list.

public ListNode detectCycle(ListNode head) { if (head == null) return head; ListNode slow = head; ListNode fast = head; boolean hasCycle = false; while (fast != null && fast.next != null) { fast = fast.next.next; slow = slow.next; if (slow == fast) { hasCycle = true; break; } } if (!hasCycle) return null; fast = head; while (fast != slow) { fast = fast.next; slow = slow.next; } return slow; } time: o(n) space: o(1)

23. Merge k Sorted Lists Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } return a linkedlist with correct order

public ListNode mergeKLists(ListNode[] lists) { if (lists == null || lists.length == 0) { return null; } PriorityQueue<ListNode> pq = new PriorityQueue<>(new Comparator<ListNode>(){ public int compare(ListNode l1, ListNode l2) { return l1.val - l2.val; } }); for (ListNode node: lists) { if (node != null) { //這裡要注意 pq.offer(node); } } ListNode dummy = new ListNode(0); ListNode cur = dummy; while (!pq.isEmpty()) { cur.next = pq.poll(); cur = cur.next; if (cur.next != null) { pq.offer(cur.next); } } return dummy.next; } 注意lists裡面的ListNode可能為null comparator後面的 });別忘記 time : O(nlogk) n = node num, k = lists.length space: O(k) ****一定要用dummy, 如果在while外面就先poll的話, 他的next就不會被check了

21. Merge Two Sorted Lists Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. Example: Input: 1->2->4, 1->3->4 Output: 1->1->2->3->4->4

public ListNode mergeTwoLists(ListNode l1, ListNode l2) { if (l1 == null && l2 == null) return null; if (l1 == null) return l2; if (l2 == null) return l1; ListNode result = null; if (l1.val < l2.val) { result = l1; result.next = mergeTwoLists(l1.next, l2); } else { result = l2; result.next = mergeTwoLists(l2.next, l1); } return result; } -------------------- public ListNode mergeTwoLists(ListNode l1, ListNode l2) { if (l1 == null && l2 == null) return null; if (l1 == null) return l2; if (l2 == null) return l1; ListNode dummy = new ListNode(0); ListNode cur = dummy; ListNode n1 = l1; ListNode n2 = l2; while (n1 != null && n2 != null) { if (n1.val < n2.val) { cur.next = n1; n1 = n1.next; } else { cur.next = n2; n2 = n2.next; } cur = cur.next; } while (n1 != null) { cur.next = n1; n1 = n1.next; cur = cur.next; } while (n2 != null) { cur.next = n2; n2 = n2.next; cur = cur.next; } return dummy.next; } 可以iterate or recursion time: o(m+n) space: o(1)?!

328. Odd Even Linked List Input: 1->2->3->4->5->NULL Output: 1->3->5->2->4->NULL

public ListNode oddEvenList(ListNode head) { if (head == null || head.next == null || head.next.next == null) { return head; } ListNode odd = head; ListNode even = head.next; ListNode second = even; while (even != null && even.next != null) { odd.next = odd.next.next; even.next = even.next.next; even = even.next; odd = odd.next; } odd.next = second; return head; } 記得條件是even time: o(n) space: o(1)

206. Reverse Linked List Reverse a singly linked list. Example: Input: 1->2->3->4->5->NULL Output: 5->4->3->2->1->NULL

public ListNode reverseList(ListNode head) { if (head == null) return head; ListNode pre = null; ListNode cur = head; while (cur != null) { ListNode temp = cur.next; cur.next = pre; pre = cur; cur = temp; } return pre; } time: o(n) space: o(1)

116. Populating Next Right Pointers in Each Node You are given a perfect binary tree where all leaves are on the same level, and every parent has two children. The binary tree has the following definition: struct Node { int val; Node *left; Node *right; Node *next; } Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL. 就是有一個next 每個node要連到他右邊的node

public Node connect(Node root) { if (root == null) return null; Node mostLeft = root; while (mostLeft != null) { Node cur = mostLeft; while (cur != null) { if (cur.left != null) { cur.left.next = cur.right; } if (cur.right != null && cur.next != null) { cur.right.next = cur.next.left; } cur = cur.next; } mostLeft = mostLeft.left; } return root; } time: o(n) space: o(1)

426. Convert Binary Search Tree to Sorted Doubly Linked List Convert a BST to a sorted circular doubly-linked list in-place. Think of the left and right pointers as synonymous to the previous and next pointers in a doubly-linked list.

public Node treeToDoublyList(Node root) { if (root == null) return root; Node[] minMax = helper(root); minMax[0].left = minMax[1]; minMax[1].right = minMax[0]; return minMax[0]; } private Node[] helper(Node root) { if (root == null) { return new Node[]{null, null}; } Node[] left = helper(root.left); Node[] right = helper(root.right); root.left = left[1]; if (left[1] != null) left[1].right = root; root.right = right[0]; if (right[0] != null) right[0].left = root; Node min = left[0] != null? left[0] : root; Node max = right[1] != null? right[1] : root; return new Node[] {min, max}; } time: o(n) space: o(h) 記得最後是return minMax[0]

67. Add Binary Given two binary strings, return their sum (also a binary string). The input strings are both non-empty and contains only characters 1 or 0. Example 1: Input: a = "11", b = "1" Output: "100"

public String addBinary(String a, String b) { if (a == null && b == null) { return ""; } else if (a == null || a.length() == 0) { return b; } else if (b == null || b.length() == 0) { return a; } int indA = a.length() - 1; int indB = b.length() - 1; int carry = 0; StringBuilder sb = new StringBuilder(); while (indA >= 0 && indB >= 0) { carry += (a.charAt(indA) - '0') + (b.charAt(indB) - '0'); sb.append(carry % 2); carry /= 2; indA--; indB--; } while (indA >= 0) { carry += (a.charAt(indA) - '0'); sb.append(carry % 2); carry /= 2; indA--; } while (indB >= 0) { carry += (b.charAt(indB) - '0'); sb.append(carry % 2); carry /= 2; indB--; } if (carry > 0) { sb.append(1); } return sb.reverse().toString(); }

415. Add Strings Given two non-negative integers num1 and num2 represented as string, return the sum of num1 and num2

public String addStrings(String num1, String num2) { int len1 = num1.length(); int len2 = num2.length(); int[] chars = new int[Math.max(len1, len2) + 1]; int i1 = len1 - 1; int i2 = len2 - 1; int carry = 0; int index = chars.length - 1; while (index >= 0) { if (i1 >= 0 && i2 >= 0) { carry += Integer.valueOf(num1.charAt(i1) - '0') + Integer.valueOf(num2.charAt(i2) - '0'); } else if (i1 >= 0) { carry += Integer.valueOf(num1.charAt(i1) - '0'); } else if (i2 >= 0) { carry += Integer.valueOf(num2.charAt(i2) - '0'); } chars[index] = carry % 10; carry /= 10; index--; i1--; i2--; } StringBuilder sb = new StringBuilder(); for (int i : chars) { sb.append(i); } while (sb.length() > 0 && sb.charAt(0) == '0') { sb.deleteCharAt(0); } return sb.length() == 0? "0" : sb.toString(); } delete first stringbuilder的時候要check 長度>0 time: o(m+n) space o (m+n)

791. Custom Sort String S and T are strings composed of lowercase letters. In S, no letter occurs more than once. S was sorted in some custom order previously. We want to permute the characters of T so that they match the order that S was sorted. More specifically, if x occurs before y in S, then x should occur before y in the returned string. Return any permutation of T (as a string) that satisfies this property. Input: S = "cba" T = "abcd" Output: "cbad"

public String customSortString(String S, String T) { int[] letters = new int[26]; for (char c : T.toCharArray()) { letters[c - 'a']++; } StringBuilder sb = new StringBuilder(); for (char c : S.toCharArray()) { while (letters[c - 'a'] > 0) { sb.append(c); letters[c- 'a']--; } } for (char c : T.toCharArray()) { while (letters[c - 'a'] > 0) { sb.append(c); letters[c - 'a']--; } } return sb.toString(); } 把原本的string的char存進array, 之後用sort的string去比對, 有的話加進StringBuilder, 最後一個for loop 把剩下的char加進StringBuilder(不要iterate from char, 直接用原本的string應該比較快(string長度應該小於26)) time: O(m+n) space: O(26)

5. Longest Palindromic Substring Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000. Example 1: Input: "babad" Output: "bab" Note: "aba" is also a valid answer.

public String longestPalindrome(String s) { if (s == null || s.length() == 0) { return ""; } int maxLen = 0; int start = 0; for (int i = 0; i < s.length(); i++) { int len = helper(s, i, i); if (len > maxLen) { maxLen = len; start = i - len / 2; } len = helper(s, i, i + 1); if (len > maxLen) { maxLen = len; start = i - len / 2 + 1; } } return s.substring(start, start + maxLen); } private int helper(String s, int i, int j) { int count = 0; while (i >= 0 && j < s.length()) { if (s.charAt(i) != s.charAt(j)) { break; } else if (i == j) { count++; } else { count += 2; } i--; j++; } return count; } 回文可以從兩個方面下手: two pointer一起從中間 two pointer 差1 往外找 有一個helper function 會回傳長度, update when 長度 > max len time: o(n^2) space: o(1)

76. Minimum Window Substring Given a string S and a string T, find the minimum window in S which will contain all the characters in T in complexity O(n). Example: Input: S = "ADOBECODEBANC", T = "ABC" Output: "BANC" Note: 1. If there is no such window in S that covers all characters in T, return the empty string "". 2. If there is such window, you are guaranteed that there will always be only one unique minimum window in S.

public String minWindow(String s, String t) { if(t.length()> s.length()) return ""; Map<Character, Integer> map = new HashMap<>(); for(char c : t.toCharArray()){ map.put(c, map.getOrDefault(c,0) + 1); } int counter = map.size(); int begin = 0, end = 0; int head = 0; int len = Integer.MAX_VALUE; while(end < s.length()){ char c = s.charAt(end); if( map.containsKey(c) ){ map.put(c, map.get(c)-1); if(map.get(c) == 0) counter--; } end++; while(counter == 0){ char tempc = s.charAt(begin); if(map.containsKey(tempc)){ map.put(tempc, map.get(tempc) + 1); if(map.get(tempc) > 0){ counter++; } } if(end-begin < len){ len = end - begin; head = begin; } begin++; } } if(len == Integer.MAX_VALUE) return ""; return s.substring(head, head+len); } time: o(s) space: o(t) two pointer, end一直跑, 去check map, 當map = 0的時候count--, 當count == 0代表都已包含t的char了, check begin, begin加回map, 同時check len是最小的, 如果是的話update head 和438一起看

43. Multiply Strings Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2, also represented as a string. Example 1: Input: num1 = "2", num2 = "3" Output: "6"

public String multiply(String num1, String num2) { int len1 = num1.length(), len2 = num2.length(); int[] product = new int[len1 + len2]; for (int i = len1 - 1; i >= 0; i--) { int i1 = num1.charAt(i) - '0'; for (int j = len2 - 1; j >= 0; j--) { int i2 = num2.charAt(j) - '0'; product[i + j + 1] += i1 * i2; } } int carry = 0; for (int i = product.length - 1; i >= 0; i--) { carry += product[i]; product[i] = carry % 10; carry /= 10; } StringBuilder sb = new StringBuilder(); for (int i : product) { sb.append(i); } while (sb.length() != 0 && sb.charAt(0) == '0') { sb.deleteCharAt(0); } return sb.length() == 0? "0": sb.toString(); }

402. Remove K Digits Given a non-negative integer num represented as a string, remove k digits from the number so that the new number is the smallest possible. Note: The length of num is less than 10002 and will be ≥ k. The given num does not contain any leading zero.

public String removeKdigits(String s, int k) { if (s == null || s.length() == 0) { return "0"; } if (k >= s.length()) { return "0"; } Stack<Character> stack = new Stack<>(); for (int i = 0; i < s.length(); i++) { // int num = s.charAt(i) - '0'; while (!stack.isEmpty() && stack.peek() > s.charAt(i) && k > 0) { stack.pop(); k--; } stack.push(s.charAt(i)); } while (k > 0) { stack.pop(); k--; } StringBuilder sb = new StringBuilder(); while (!stack.isEmpty()) { // System.out.println(stack.peek()); sb.append(stack.pop()); } sb = sb.reverse(); while (sb.length() > 0 && sb.charAt(0) == '0') { sb.deleteCharAt(0); } return sb.length() == 0? "0":sb.toString(); } 用stack存 跟前面的比, 之後sb.reverse, 然後去除開頭的0 time: o(n+k) space: o(n)

151. Reverse Words in a String Given an input string, reverse the string word by word. Example 1: Input: "the sky is blue" Output: "blue is sky the"

public String reverseWords(String s) { if (s == null || s.equals("")) return ""; s = s.trim(); String[] words = s.split("\\s+"); if (words.length == 0) return ""; StringBuilder sb = new StringBuilder(); sb.append(words[words.length - 1]); for (int i = words.length - 2; i >= 0; i--) { sb.append(" "); sb.append(words[i]); } return sb.toString(); } time: o(n) space: o(n) 記得要trim這個string, check split完之後

105. Construct Binary Tree from Preorder and Inorder Traversal Given preorder and inorder traversal of a tree, construct the binary tree. Note: You may assume that duplicates do not exist in the tree.

public TreeNode buildTree(int[] preorder, int[] inorder) { if (preorder == null || inorder == null || preorder.length == 0 || inorder.length == 0) { return null; } return construct(preorder, inorder, 0, 0, inorder.length - 1); } private TreeNode construct(int[] pre, int[] in, int preInd, int start, int end) { if (start > end || preInd >= pre.length) { return null; } TreeNode root = new TreeNode(pre[preInd]); int inInd = 0; for (int i = start; i <= end; i++) { if (in[i] == pre[preInd]) { inInd = i; } } root.left = construct(pre, in, preInd + 1, start, inInd - 1); root.right = construct(pre, in, preInd + inInd - start + 1, inInd + 1, end); return root; } preorder有一個index: preInd會等於下一次的root(左或右) inorder則是每次在一個區間裡面跑,去找和root一樣的值, inInd前面的都是root.left, 後面的都是root.right time: o(n) space: o(log n)

450. Delete Node in a BST Given a root node reference of a BST and a key, delete the node with the given key in the BST. Return the root node reference (possibly updated) of the BST. Basically, the deletion can be divided into two stages: Search for a node to remove. If the node is found, delete the node. Note: Time complexity should be O(height of tree).

public TreeNode deleteNode(TreeNode root, int key) { if (root == null) { return null; } if (key < root.val) { root.left = deleteNode(root.left, key); } else if (key > root.val) { root.right = deleteNode(root.right, key); } else { if (root.left == null) { return root.right; } else if (root.right == null) { return root.left; } root.val = findMin(root.right).val; root.right = deleteNode(root.right, root.val); } return root; } private TreeNode findMin(TreeNode node) { while (node.left != null) { node = node.left; } return node; } recursion的方式,先確認key在哪裡, 等到key == root的時候, 從右邊挑min取代root.val, 然後root的右邊再跑一次delete(root.right, min(root.val)) time: o(h) space: o(h)

236. Lowest Common Ancestor of a Binary Tree Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According to the definition of LCA on Wikipedia: "The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself)." Given the following binary tree: root = [3,5,1,6,2,0,8,null,null,7,4] Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 Output: 3 Explanation: The LCA of nodes 5 and 1 is 3.

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { //if (both != null) return root // else (return lowestCommonAncestor(not null node)) if (root == null) { return null; } if (root.val == p.val || root.val == q.val) { return root; } TreeNode left = lowestCommonAncestor(root.left, p, q); TreeNode right = lowestCommonAncestor(root.right, p, q); if (left != null && right != null) { return root; } if (left != null) { return left; } else { return right; } } 左右去找, 如果是null代表p,q都在另一邊 記得要比較val那一行不要忘記

235. Lowest Common Ancestor of a Binary Search Tree Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST. According to the definition of LCA on Wikipedia: "The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself)." Given binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5]

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if (root.val == q.val || root.val == p.val) { return root; } if (p.val > root.val && q.val < root.val || p.val < root.val && q.val > root.val) { return root; } if (p.val < root.val) { return lowestCommonAncestor(root.left, p, q); } else { return lowestCommonAncestor(root.right, p, q); } } 利用binary search tree的特性來找 要考慮到如果p,q等於自己的話就回傳root 该算法的时间复杂度为 O(h) , h 为树的高度

133. Clone Graph Given the head of a graph, return a deep copy (clone) of the graph. Each node in the graph contains a label (int) and a list (List[UndirectedGraphNode]) of its neighbors. There is an edge between the given node and each of the nodes in its neighbors. /** * Definition for undirected graph. * class UndirectedGraphNode { * int label; * List<UndirectedGraphNode> neighbors; * UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList<UndirectedGraphNode>(); } * }; */

public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) { if (node == null) { return null; } Map<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<>(); Queue<UndirectedGraphNode> q = new LinkedList<>(); q.offer(node); while (!q.isEmpty()) { UndirectedGraphNode temp = q.poll(); List<UndirectedGraphNode> oldNodeList = temp.neighbors; if (!map.containsKey(temp)) { map.put(temp, new UndirectedGraphNode(temp.label)); } List<UndirectedGraphNode> newNodeList = map.get(temp).neighbors; for (int i = 0; i < oldNodeList.size(); i++) { UndirectedGraphNode nb = oldNodeList.get(i); if (!map.containsKey(nb)) { map.put(nb, new UndirectedGraphNode(nb.label)); q.offer(nb); } newNodeList.add(map.get(nb)); } } return map.get(node); } 用map存舊node, 新node 跑neighbors的時候如果map還沒有這個node就加進map, 並加進queue, 第一個node要在外面加進去queue time: o(n) space: o(n)

844. Backspace String Compare Given two strings S and T, return if they are equal when both are typed into empty text editors. # means a backspace character. Input: S = "ab#c", T = "ad#c" Output: true Explanation: Both S and T become "ac".

public boolean backspaceCompare(String S, String T) { StringBuilder sb1 = new StringBuilder(); for (int i = 0; i < S.length(); i++) { if (S.charAt(i) != '#') { sb1.append(S.charAt(i)); } else if (sb1.length() > 0){ sb1.deleteCharAt(sb1.length() - 1); } } StringBuilder sb2 = new StringBuilder(); for (int i = 0; i < T.length(); i++) { if (T.charAt(i) != '#') { sb2.append(T.charAt(i)); } else if (sb2.length() > 0){ sb2.deleteCharAt(sb2.length() - 1); } } return sb1.toString().equals(sb2.toString()); } time: o(n) space: o(n)

252. Meeting Rooms Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei), determine if a person could attend all meetings.

public boolean canAttendMeetings(Interval[] intervals) { if (intervals == null || intervals.length == 0) { return true; } PriorityQueue<Interval> pq = new PriorityQueue<>(new Comparator<Interval>(){ public int compare(Interval i1, Interval i2) { return i1.start - i2.start; } }); for (int i = 0; i < intervals.length; i++) { pq.offer(intervals[i]); } int pre = Integer.MIN_VALUE; while (!pq.isEmpty()) { Interval temp = pq.poll(); // System.out.println("temp.start: " + temp.start); // System.out.println("pre: " + pre); if (temp.start < pre) { return false; } pre = temp.end; } return true; } 記得pre = cur 解法二:Arrays.sort, space下降 Arrays.sort(intervals, new Comparator<Interval>() { public int compare(Interval i1, Interval i2) { return i1.start - i2.start; } });

207. Course Schedule There are a total of n courses you have to take, labeled from 0 to n-1. Some courses may have prerequisites, for example to take course 0 you have to first take course 1, which is expressed as a pair: [0,1] Given the total number of courses and a list of prerequisite pairs, is it possible for you to finish all courses?

public boolean canFinish(int numCourses, int[][] prerequisites) { if (prerequisites == null || prerequisites.length == 0) { return true; } int[] pre = new int[numCourses]; ArrayList[] graph = new ArrayList[numCourses]; for (int i = 0; i < graph.length; i++) { graph[i] = new ArrayList<Integer>(); } for (int[] link: prerequisites) { pre[link[0]]++; graph[link[1]].add(link[0]); } Queue<Integer> q = new LinkedList<>(); int count = 0; for (int i = 0; i < pre.length; i++) { if (pre[i] == 0) { count++; q.offer(i); } } while (!q.isEmpty()) { int cur = q.poll(); ArrayList list = graph[cur]; for (int i = 0; i < list.size(); i++) { pre[(int)list.get(i)]--; if (pre[(int)list.get(i)] == 0) { count++; q.offer((int)list.get(i)); } } } return count == numCourses; } 托僕排序, 如果有環就是false, 沒有環就false 要有兩個array: graph存list(graph), pre代表有多少先修課, queue從完全沒有先修課的開始跑, 一個一個把arraylist裡面的pre減掉, 等到先修課都修完之後(pre[] = 0)則count++, 加進queue, 最後檢查count 是否等於numCourses time: o(n) space: o(n)

55. Jump Game Given an array of non-negative integers, you are initially positioned at the first index of the array. Each element in the array represents your maximum jump length at that position. Determine if you are able to reach the last index.

public boolean canJump(int[] nums) { int maxReach = 0; for (int i = 0; i < nums.length; i++) { if (i > maxReach) { return false; } maxReach = Math.max(maxReach, i + nums[i]); } return maxReach >= nums.length - 1; } time: o(n) space: o(1)

567. Permutation in String Given two strings s1 and s2, write a function to return true if s2 contains the permutation of s1. In other words, one of the first string's permutations is the substring of the second string. Example 1: Input:s1 = "ab" s2 = "eidbaooo" Output:True Explanation: s2 contains one permutation of s1 ("ba").

public boolean checkInclusion(String s1, String s2) { if (s1.length() == 0) { return true; } if (s1.length() > s2.length()) { return false; } int[] chars = new int[26]; for (int i = 0; i < s1.length(); i++) { chars[s1.charAt(i) - 'a']++; chars[s2.charAt(i) - 'a']--; } if (count0(chars)) return true; for (int i = s1.length(); i < s2.length(); i++) { chars[s2.charAt(i) - 'a']--; chars[s2.charAt(i - s1.length()) - 'a']++; if (count0(chars)) return true; } return false; } private boolean count0(int[] chars) { for (int i : chars) { if (i != 0) return false; } return true; }

check if words are sorted according to new order of alphabets

public boolean checkOrder(String[] words, String order) { if (words.length <= 1) { return true; } for (int i = 1; i < words.length; i++) { String s1 = words[i-1]; String s2 = words[i]; if (!check(s1, s2, order)) { return false; } } return true; } private boolean check(String s1, String s2, String order) { int min = Math.min(s1.length(), s2.length()); for (int i = 0; i < min; i++) { String c1 = s1.substring(i, i+1); String c2 = s2.substring(i, i+1); if (order.indexOf(c1) > order.indexOf(c2)) { return false; } if (order.indexOf(c1) < order.indexOf(c2)) { return true; } } if (s1.length() > s2.length()) return false; return true; }

678. Valid Parenthesis String Given a string containing only three types of characters: '(', ')' and '*', write a function to check whether this string is valid. We define the validity of a string by these rules: Any left parenthesis '(' must have a corresponding right parenthesis ')'. Any right parenthesis ')' must have a corresponding left parenthesis '('. Left parenthesis '(' must go before the corresponding right parenthesis ')'. '*' could be treated as a single right parenthesis ')' or a single left parenthesis '(' or an empty string. An empty string is also valid. String 有 (, ), or *,判斷是不是valid string

public boolean checkValidString(String s) { if (s == null || s.length() == 0) { return true; } int sum = 0; for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == '(' || s.charAt(i) == '*') { sum++; } else { sum--; } if (sum < 0) { return false; } } if (sum == 0) return true; sum = 0; for (int i = s.length() - 1; i>= 0; i--) { if (s.charAt(i) == ')' || s.charAt(i) == '*') { sum++; } else { sum--; } if (sum < 0) return false; } return true; } 左右各遍歷一次,從左邊開始的時候讓*是+, 從右邊開始的時候是讓星號+,只要任何一個時候sum等於負的就return false, 第一次結束如果sum = 0 則return false time: O(n) space: O(1)

110. Balanced Binary Tree Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary tree is defined as: a binary tree in which the depth of the two subtrees of every node never differ by more than 1. Example 1: Given the following tree [3,9,20,null,null,15,7]: 3 / \ 9 20 / \ 15 7

public boolean isBalanced(TreeNode root) { return helper(root) >= 0; } private int helper(TreeNode root) { if (root == null) return 0; int left = helper(root.left); int right = helper(root.right); if (left == -1 || right == -1 || Math.abs(left - right) > 1) { return -1; } return Math.max(left, right) +1 ; } time: o(n) space: o(log n)

10. Regular Expression Matching Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'. '.' Matches any single character. '*' Matches zero or more of the preceding element. The matching should cover the entire input string (not partial). Note: s could be empty and contains only lowercase letters a-z. p could be empty and contains only lowercase letters a-z, and characters like . or *.

public boolean isMatch(String s, String p) { if (s == null || p == null) { return false; } boolean[][] dp = new boolean[s.length() + 1][p.length() + 1]; dp[0][0] = true; for (int i = 0; i < p.length(); i++) { if (p.charAt(i) == '*' && dp[0][i-1]) { dp[0][i+1] = true; } } for (int i = 0; i < s.length(); i++) { for (int j = 0; j < p.length(); j++) { if (p.charAt(j) == s.charAt(i)) { dp[i + 1][j + 1] = dp[i][j]; } if (p.charAt(j) == '.') { dp[i + 1][j + 1] = dp[i][j]; } if (p.charAt(j) == '*') { if (p.charAt(j-1) != s.charAt(i) && p.charAt(j-1) != '.') { dp[i+1][j+1] = dp[i+1][j-1]; } else { dp[i+1][j+1] = (dp[i+1][j] || dp[i][j+1] || dp[i+1][j-1]); } } } } return dp[s.length()][p.length()]; }

local minimum

public int findLocalMinimum(int[] nums) { if (nums == null || nums.length == 0) { return -1; } if (nums.length == 1) { return 0; } int l = 0, r = nums.length - 1; while (l < r) { int mid = l + (r - l) / 2; if (nums[mid] < nums[mid + 1]) { r = mid; } else { l = mid + 1; } } return l; } 用 binary search, 考慮只有兩個數字的情況判斷誰要+1

234. Palindrome Linked List Given a singly linked list, determine if it is a palindrome. Example 1: Input: 1->2 Output: false /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */

public boolean isPalindrome(ListNode head) { if (head == null) return true; Stack<ListNode> stack = new Stack(); ListNode slow = head, fast = head; while (fast != null && fast.next != null) { stack.push(slow); slow = slow.next; fast = fast.next; fast = fast.next; } if (fast == null) { } else { slow = slow.next; } while(slow != null) { if (slow.val != stack.pop().val) { return false; } else { slow = slow.next; } } return true; } 可以用stack解或是in place, 先找中點, 後面的reverse然後check public boolean isPalindrome(ListNode head) { if (head == null || head.next == null) return true; ListNode mid = findMid(head); ListNode second = mid.next; second = reverse(second); mid.next = null; //check while (head != null && second != null) { if (head.val != second.val) { return false; } head = head.next; second = second.next; } return true; } private ListNode findMid(ListNode head) { if (head == null || head.next == null) { return head; } ListNode slow = head, fast = head; while (fast.next != null && fast.next.next != null) { slow = slow.next; fast = fast.next.next; } return slow; } private ListNode reverse(ListNode head) { if (head == null || head.next == null) { return head; } ListNode pre = null; ListNode cur = head; while (cur != null) { ListNode temp = cur.next; cur.next = pre; pre = cur; cur = temp; } return pre; } find middle要找的是前一個, 不是後一個,

125. Valid Palindrome Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases. Note: For the purpose of this problem, we define empty string as valid palindrome.

public boolean isPalindrome(String s) { if (s == null || s.length() == 0) { return true; } s = s.toLowerCase(); int i = 0; int j = s.length() - 1; while (i < j) { while (i < j && !Character.isLetterOrDigit(s.charAt(i))) { i++; } while (i < j && !Character.isLetterOrDigit(s.charAt(j))) { j--; } if (s.charAt(i) != s.charAt(j)) { return false; } i++; j--; } return true; } 要記得toLowerCase() Character.isLetterOrDigit() false完記得要i++, j-- time: o(n) space: o(1)

572. Subtree of Another Tree Given two non-empty binary trees s and t, check whether tree t has exactly the same structure and node values with a subtree of s. A subtree of s is a tree consists of a node in s and all of this node's descendants. The tree s could also be considered as a subtree of itself.

public boolean isSubtree(TreeNode s, TreeNode t) { if (s == null) return false; return isSame(s, t) || isSubtree(s.left, t) || isSubtree(s.right, t); } private boolean isSame(TreeNode s, TreeNode t) { if (s == null || t == null) return s == t; if (s.val == t.val) return isSame(s.left, t.left) && isSame(s.right, t.right); return false; } time: o(n) space: o(h)

20. Valid Parentheses Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. An input string is valid if: Open brackets must be closed by the same type of brackets. Open brackets must be closed in the correct order. Note that an empty string is also considered valid.

public boolean isValid(String s) { if (s == null || s.length() == 0) { return true; } Stack<Character> stack = new Stack<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (c == '(' || c == '{' || c == '[') { stack.push(c); } else if (c == ')' && !stack.isEmpty() && stack.peek() == '(') { stack.pop(); } else if (c == ']' && !stack.isEmpty() && stack.peek() == '[') { stack.pop(); } else if (c == '}' && !stack.isEmpty() && stack.peek() == '{') { stack.pop(); } else { return false; } } return stack.size() == 0; } 記得check右邊的時候要check !stack.isEmpty(),不然當所有括弧都是右括弧會錯 time: o(n) space: o(n)

98. Validate Binary Search Tree Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as follows: The left subtree of a node contains only nodes with keys less than the node's key. The right subtree of a node contains only nodes with keys greater than the node's key. Both the left and right subtrees must also be binary search trees.

public boolean isValidBST(TreeNode root) { if (root == null) return true; return helper(root, Long.MIN_VALUE, Long.MAX_VALUE); } private boolean helper(TreeNode root, long left, long right) { if (root == null) { return true; } if (root.val <= left || root.val >= right) { return false; } return helper(root.left, left, root.val) && helper(root.right, root.val, right); } time: o(n) space: o(n)???

240. Search a 2D Matrix II Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties: Integers in each row are sorted in ascending from left to right. Integers in each column are sorted in ascending from top to bottom. Example: Consider the following matrix: [ [1, 4, 7, 11, 15], [2, 5, 8, 12, 19], [3, 6, 9, 16, 22], [10, 13, 14, 17, 24], [18, 21, 23, 26, 30] ] Given target = 5, return true. Given target = 20, return false.

public boolean searchMatrix(int[][] matrix, int target) { if (matrix == null || matrix.length == 0 || matrix[0] == null || matrix[0].length == 0) { return false; } int i = 0; int j = matrix[0].length - 1; while (i < matrix.length && j >= 0) { if (matrix[i][j] == target) { return true; } else if (matrix[i][j] > target) { j--; } else { i++; } } return false; } time O(m + n) (row + column) space O(1)

680. Valid Palindrome II Given a non-empty string s, you may delete at most one character. Judge whether you can make it a palindrome. Example 2: Input: "abca" Output: True Explanation: You could delete the character 'c'.

public boolean validPalindrome(String s) { if (s == null || s.length() == 0) { return true; } int i = 0, j = s.length() - 1; while (i < j) { if (s.charAt(i) == s.charAt(j)) { i++; j--; } else { return isPalindrome(s, i + 1, j) || isPalindrome(s, i, j - 1); } } return true; } private boolean isPalindrome(String s, int i, int j) { while (i < j) { if (s.charAt(i) != s.charAt(j)) { return false; } i++; j--; } return true; } 遇到不一樣的, 去測如果除掉自己之後剩下的字是不是回文 time: o(n)? space: o(1)?

139. Word Break Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s can be segmented into a space-separated sequence of one or more dictionary words.

public boolean wordBreak(String s, List<String> wordDict) { if (s.equals("")) return true; Set<String> set = new HashSet<>(wordDict); boolean[] b = new boolean[s.length() + 1]; b[0] = true; for (int i = 1; i <= s.length(); i++) { for (int j = 0; j < i; j++) { if (b[j]&& set.contains(s.substring(j, i))) { b[i] = true; } } } return b[s.length()]; } DP: O(n^2) DP的方法, 有一個boolean[] 記得substring那邊簡單就好不要加一減一的

flattern a linkedlist 5 -> 10 -> 19 -> 28 | | | | V V V V 7 20 22 35 | | | V V V 8 50 40 | | V V 30 45

public class ListNode{ int val; ListNode right, down; ListNode (int x) { value = x; right = null; down = null; } } public ListNode flatten(ListNode root) { if (root == null || root.right == null) { return root; } ListNode right = flatten(root.right); return merge(root, right); } private ListNode merge(ListNode left, ListNode right) { if (left == null) return right; if (right == null) return left; ListNode dummy = new ListNode(0); if (left.val < right.val) { dummy.down = left; left.down = merge(left.down, right); } else { dummy.down = right; right.down = merge(right.down, left); } return dummy.down; }

138. Copy List with Random Pointer A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null. Return a deep copy of the list.

public class Solution { public RandomListNode copyRandomList(RandomListNode head) { if (head == null) { return null; } //insert RandomListNode cur = head; while (cur != null) { RandomListNode temp = cur.next; cur.next = new RandomListNode(cur.label); cur.next.next = temp; cur = cur.next.next; } //random cur = head; while (cur != null) { if (cur.random != null) { cur.next.random = cur.random.next; } cur = cur.next.next; } //split cur = head; RandomListNode newNode = head.next; RandomListNode ans = head.next; while (cur != null) { cur.next = newNode.next; if (newNode.next != null) { newNode.next = cur.next.next; } cur = cur.next; newNode = newNode.next; } return ans; } } 記得, random處理的時候要小心random有可能是null time : o(n) space: o(1)

50. Pow(x, n) mplement pow(x, n), which calculates x raised to the power n (x*n).

public double myPow(double x, int n) { if (n == 0) return 1; if (n == 1) return x; if (n < 0) { x = 1/x; n = -n; if (-n == Integer.MIN_VALUE) { return x * myPow(x, (n - 1)); } } return n % 2 == 0? myPow(x*x, n / 2) : x * myPow(x*x, n/2); } 記得recursive 除2解法 out of bound那邊先不要寫 time: o(log n) space: o(1)

224. Basic Calculator Implement a basic calculator to evaluate a simple expression string. The expression string may contain open ( and closing parentheses ), the plus + or minus sign -, non-negative integers and empty spaces . 正負括弧

public int calculate(String s) { if (s == null || s.length() == 0) { return 0; } int sign = 1; int num = 0; int result = 0; Stack<Integer> stack = new Stack(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (Character.isDigit(c)) { num = num * 10 + c - '0'; } else if (c == '+') { result += sign * num; sign = 1; num = 0; } else if (c == '-') { result += sign * num; sign = -1; num = 0; } else if (c == '(') { stack.push(result); result = 0; stack.push(sign); sign = 1; } else if (c == ')') { result += sign * num; result *= stack.pop(); result += stack.pop(); num = 0; sign = 1; } } if (num != 0) result += sign * num; return result; } time: o(n) space: o(n)

227. Basic Calculator II Implement a basic calculator to evaluate a simple expression string. The expression string contains only non-negative integers, +, -, *, / operators and empty spaces . The integer division should truncate toward zero. Example 1: Input: "3+2*2" Output: 7

public int calculate(String s) { if (s == null || s.length() == 0) { return 0; } int num = 0; char sign = '+'; Stack<Integer> stack = new Stack<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (Character.isDigit(c)) { num = 10 *num + (c - '0'); } if (c == '+' || c == '-' || c == '*' || c == '/' || i == s.length() - 1) { if (sign == '+') { stack.push(num); num = 0; } else if (sign == '-') { stack.push(-num); num = 0; } else if (sign == '*') { num *= stack.pop(); stack.push(num); num = 0; } else if (sign == '/') { num = stack.pop() / num; stack.push(num); num = 0; } sign = c; } } int ans = 0; while (!stack.isEmpty()) { ans += stack.pop(); } return ans; } time: o(n) space: o(n)

518. Coin Change 2 You are given coins of different denominations and a total amount of money. Write a function to compute the number of combinations that make up that amount. You may assume that you have infinite number of each kind of coin.

public int change(int amount, int[] coins) { int[] dp = new int[amount + 1]; dp[0] = 1; for (int c : coins) { for (int j = 1; j < dp.length ; j++) { if (j - c >= 0) { dp[j] += dp[j - c]; } } } return dp[amount]; } time: o(m*n) space: o(n)

322. Coin Change You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.

public int coinChange(int[] coins, int amount) { if (coins == null || coins.length == 0) { return 0; } int[] dp = new int[amount + 1]; dp[0] = 0; for (int i = 1; i < dp.length; i++) { int min = Integer.MAX_VALUE; for (int c: coins) { if (c == i) { min = 1; break; } if (i - c >= 0 && dp[i - c] > -1) { min = Math.min(min, dp[i - c] + 1); } } if (min == Integer.MAX_VALUE) { dp[i] = -1; } else { dp[i] = min; } } return dp[amount]; } time: o(n*m) space: o(n)

165. Compare Version Numbers Compare two version numbers version1 and version2. If version1 > version2 return 1; if version1 < version2 return -1;otherwise return 0. You may assume that the version strings are non-empty and contain only digits and the . character. The . character does not represent a decimal point and is used to separate number sequences. For instance, 2.5 is not "two and a half" or "half way to version three", it is the fifth second-level revision of the second first-level revision. You may assume the default revision number for each level of a version number to be 0. For example, version number 3.4 has a revision number of 3 and 4 for its first and second level revision number. Its third and fourth level revision number are both 0.

public int compareVersion(String version1, String version2) { String[] one = version1.split("\\."); String[] two = version2.split("\\."); int i = 0; int j = 0; int ans = 0; while (i < one.length && j < two.length) { if (Integer.valueOf (one[i]) == Integer.valueOf(two[j])) { i++; j++; } else if (Integer.valueOf(one[i]) > Integer.valueOf(two[j])) { ans = 1; return ans; } else { ans = -1; return ans; } } while (i < one.length) { if (Integer.valueOf(one[i]) == 0) { i++; } else { ans = 1; break; } } while (j < two.length){ if (Integer.valueOf(two[j]) == 0) { j++; } else { ans = -1; break; } } return ans; } 就算長度不一樣停下來, 還是要確認.之後是不是0, 是0的話繼續跑 記得是\\.

443. String Compression Given an array of characters, compress it in-place. The length after compression must always be smaller than or equal to the original array. Every element of the array should be a character (not int) of length 1. After you are done modifying the input array in-place, return the new length of the array. Follow up: Could you solve it using only O(1) extra space?

public int compress(char[] chars) { if (chars == null || chars.length == 0) { return 0; } int start = 0; int count = 0; for (int i = 0; i < chars.length; i++) { count++; if (i == chars.length - 1 || chars[i] != chars[i+1]) { chars[start] = chars[i]; start++; if (count != 1) { String s = String.valueOf(count); for (int j = 0; j < s.length(); j++) { chars[start] = s.charAt(j); start++; } } count = 0; } } return start; } time: o(n) space: o(1)

323. Number of Connected Components in an Undirected Graph Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), write a function to find the number of connected components in an undirected graph. Input: n = 5 and edges = [[0, 1], [1, 2], [3, 4]] 0 3 | | 1 --- 2 4 Output: 2

public int countComponents(int n, int[][] edges) { int[] nodes = new int[n]; for (int i = 0; i < n; i++) { nodes[i] = i; } for (int[] e : edges) { int left = find(nodes, e[0]); int right = find(nodes, e[1]); if (left != right) { nodes[left] = right; n--; } } return n; } private int find(int[] nodes, int num) { while (nodes[num] != num) { num = nodes[num]; } return num; } 先create一個array裡面的數字等於index 之後開始跑edge裡的數字 如果edge數[0], [1]不相等, n--, 且讓array[第一個數字] = 第二個數字

339. Nested List Weight Sum Given a nested list of integers, return the sum of all integers in the list weighted by their depth. Each element is either an integer, or a list -- whose elements may also be integers or other lists.

public int depthSum(List<NestedInteger> nestedList) { if (nestedList == null || nestedList.size() == 0) { return 0; } return dfs(nestedList, 1, 0); } private int dfs(List<NestedInteger> nestedList, int count, int cur) { for (NestedInteger n : nestedList) { if (n.isInteger()) { cur += count * n.getInteger(); } else { cur += dfs(n.getList(), count + 1, 0); } } return cur; } 可用dfs or bfs(queue) 記得else 的cur是從0開始, 不是傳ans進去 time: o(n) space: o(1)

29. Divide Two Integers Given two integers dividend and divisor, divide two integers without using multiplication, division and mod operator. Return the quotient after dividing dividend by divisor. The integer division should truncate toward zero.

public int divide(int dividend, int divisor) { int sign = 1; long divid = dividend, divis = divisor; if (dividend < 0) { divid = -divid; sign *= -1; } if (divisor < 0) { divis = -divis; sign *= -1; } long ans = 0; while (divid >= divis) { divid -= divis; ans++; } ans = ans * sign; if (ans > Integer.MAX_VALUE) { ans = Integer.MAX_VALUE; } else if (ans < Integer.MIN_VALUE) { ans = Integer.MIN_VALUE; } return (int)ans; } 先處理正負的問題,然後要用long來處理 followup 用binary search

287. Find the Duplicate Number Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one. Example 1: Input: [1,3,4,2,2] Output: 2

public int findDuplicate(int[] nums) { int slow = nums[0]; int fast = nums[0]; do { slow = nums[slow]; fast = nums[nums[fast]]; } while (slow != fast); slow = nums[0]; while (slow != fast) { slow = nums[slow]; fast = nums[fast]; } return slow; } 和linkedlist cycle很像 time: o(n) space: o(1)

215. Kth Largest Element in an Array merge sort

public int findKthLargest(int[] nums, int k) { if (nums == null || nums.length == 0) { return -1; } mergesort(nums, 0, nums.length - 1); return nums[nums.length - k]; } private void mergesort(int[] nums, int start, int end) { if (start == end) return; int mid = start + (end - start) / 2; mergesort(nums, start, mid); mergesort(nums, mid + 1, end); merge(nums, start, mid, mid + 1, end); } private void merge(int[] nums, int start1, int end1, int start2, int end2) { int[] arr1 = new int[end1 - start1 + 1]; int[] arr2 = new int[end2 - start2 + 1]; System.arraycopy(nums, start1, arr1, 0, arr1.length); System.arraycopy(nums, start2, arr2, 0, arr2.length); int a1 = 0, a2 = 0, index = start1; while(a1 < arr1.length && a2 < arr2.length) { if (arr1[a1] < arr2[a2]) { nums[index] = arr1[a1]; a1++; } else { nums[index] = arr2[a2]; a2++; } index++; } while (a1 < arr1.length) { nums[index] = arr1[a1]; a1++; index++; } while (a2 < arr2.length) { nums[index] = arr2[a2]; a2++; index++; } }

153. Find Minimum in Rotated Sorted Array Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]). Find the minimum element. You may assume no duplicate exists in the array. Example 1: Input: [3,4,5,1,2] Output: 1

public int findMin(int[] nums) { if (nums == null || nums.length == 0) { return -1; } int i = 0; int j =nums.length - 1; while (i < j) { int mid = i + (j - i) / 2; if (nums[mid] > nums[j]) { i = mid + 1; } else { j = mid; } } return nums[i]; } time: o(log n) space: o(1)

162. Find Peak Element A peak element is an element that is greater than its neighbors. Given an input array nums, where nums[i] ≠ nums[i+1], find a peak element and return its index. The array may contain multiple peaks, in that case return the index to any one of the peaks is fine. You may imagine that nums[-1] = nums[n] = -∞.

public int findPeakElement(int[] nums) { if (nums == null || nums.length == 0) { return 0; } int left = 0; int right = nums.length - 1; while (left < right) { int mid = left + (right - left) / 2; if (nums[mid] < nums[mid + 1]) { left = mid + 1; } else { right = mid; } } return left; } 用binary search解, 記得考慮只有兩個數字的情況來判斷誰要+1 time: log n space: n

387. First Unique Character in a String Given a string, find the first non-repeating character in it and return it's index. If it doesn't exist, return -1.

public int firstUniqChar(String s) { int[] chars = new int[26]; for(int i = 0; i < s.length(); i++){ chars[s.charAt(i) - 'a']++; } for(int i = 0; i < s.length(); i++){ if(chars[s.charAt(i) - 'a'] == 1){ return i; } } return -1; }

127. Word Ladder Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that: Only one letter can be changed at a time. Each transformed word must exist in the word list. Note that beginWord is not a transformed word. Note: Return 0 if there is no such transformation sequence. All words have the same length. All words contain only lowercase alphabetic characters. You may assume no duplicates in the word list. You may assume beginWord and endWord are non-empty and are not the same.

public int ladderLength(String beginWord, String endWord, List<String> wordList) { if (!wordList.contains(endWord)) { return 0; } Set<String> wordSet = new HashSet<>(wordList); Queue<String> q = new LinkedList<>(); int count = 1; q.offer(beginWord); while (!q.isEmpty()) { int size = q.size(); for (int i = 0; i < size; i++) { String cur = q.poll(); for (int j = 0; j < cur.length(); j++) { char[] chars = cur.toCharArray(); for (char c = 'a'; c <= 'z'; c++) { chars[j] = c; String temp = new String(chars); if (temp.equals(endWord)) { return count + 1; } else if (wordSet.contains(temp)){ q.offer(temp); wordSet.remove(temp); } } } } count ++; } return 0; } 記得char[] chars = cur.toCharArray();要寫在開始跑長度的下面,否則char會被改掉,因為每次的chars都要回覆成本來的文字才對 time: o (26n)*L space: o(26n)*L n = number of words we reached L = length of each word in list

300. Longest Increasing Subsequence Input: [10,9,2,5,3,7,101,18] Output: 4 Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.

public int lengthOfLIS(int[] nums) { if (nums == null || nums.length == 0) { return 0; } int[] dp = new int[nums.length]; int size = 0; for (int i : nums) { int l = 0; int r = size; while (l != r) { int mid = l + (r-l) / 2; if (dp[mid] < i) { l = mid + 1; } else { r = mid; } } dp[l] = i; if (l == size) { size++; } } return size; } n^2的解法 vs n log n 記得n log n 是用binary search, dp[]都會一直是sorted的 space: o(n)

超不會的一題 3. Longest Substring Without Repeating Characters Given a string, find the length of the longest substring without repeating characters. Input: "pwwkew" Output: 3

public int lengthOfLongestSubstring(String s) { if (s == null || s.length() == 0) { return 0; } int max = 0; int[] nums = new int[256]; int j = 0; for (int i = 0; i < s.length(); i++) { while (j < s.length() && nums[s.charAt(j)] == 0) { nums[s.charAt(j)] = 1; max = Math.max(max, j - i + 1); j++; } nums[s.charAt(i)] = 0; } return max; } method 2: public int lengthOfLongestSubstring(String s) { if (s == null || s.length() == 0) return 0; Map<Character, Integer> map = new HashMap<>(); int max = 1, start = 0; char[] chars = s.toCharArray(); for (int i = 0; i < chars.length; i++) { char c = chars[i]; if (map.containsKey(c)) { if (map.get(c) >= start) { start = map.get(c) + 1; } } map.put(c, i); max = Math.max(max, i - start + 1); } return max; } time: o(n) space: o(n)

11. Container With Most Water Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water. Note: You may not slant the container and n is at least 2.

public int maxArea(int[] height) { if (height == null || height.length == 0) return 0; int max = 0; int i = 0; int j = height.length - 1; while (i < j) { max = Math.max(max, (j - i) * Math.min(height[i], height[j])); if (height[i] > height[j]) { j--; } else { i++; } } return max; } time: o(n) space: o(1)

695. Max Area of Island Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water. Find the maximum area of an island in the given 2D array. (If there is no island, the maximum area is 0.)

public int maxAreaOfIsland(int[][] grid) { if (grid == null || grid.length == 0) { return 0; } int max = 0; for (int i = 0; i < grid.length; i++) { for (int j = 0; j < grid[0].length; j++) { if (grid[i][j] == 1) { int cur = dfs(grid, i, j, 0); max = Math.max(cur, max); } } } return max; } private int dfs(int[][] grid, int i, int j, int area) { if (grid[i][j] == 1) { grid[i][j] = 0; area += 1; } else { return 0; } if (i - 1 >= 0) { area += dfs(grid, i - 1, j, 0); } if (j - 1 >= 0) { area += dfs(grid, i, j-1, 0); } if (i + 1 < grid.length) { area += dfs(grid, i+1, j, 0); } if (j + 1 < grid[0].length) { area += dfs(grid, i, j+1, 0); } return area; } 後面area +=, 且是0, helper是回傳int

560. Subarray Sum Equals K Given an array of integers and an integer k, you need to find the total number of continuous subarrays whose sum equals to k.

public int subarraySum(int[] nums, int k) { if (nums == null || nums.length == 0) { return 0; } int ans = 0; //<sum, count> Map<Integer, Integer> map = new HashMap<>(); map.put(0, 1); int sum = 0; for (int i : nums) { sum += i; if (map.containsKey(sum - k)) { ans += map.get(sum - k); } map.put(sum, map.getOrDefault(sum, 0) + 1); } return ans; } 記得map.put(0,1) first 然後sum - k 這邊要小心不要寫反

123. Best Time to Buy and Sell Stock III Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete at most two transactions. Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again).

public int maxProfit(int[] prices) { if (prices == null || prices.length < 2) { return 0; } int[] firstDP = new int[prices.length]; int min = prices[0]; for (int i = 1; i < prices.length; i++) { firstDP[i] = Math.max(firstDP[i - 1], prices[i] - min); min = Math.min(min, prices[i]); } int ans = 0; int inMax = prices[prices.length - 1]; for (int i = prices.length - 2; i >= 0; i--) { ans = Math.max(ans, inMax - prices[i] + firstDP[i]); inMax = Math.max(inMax, prices[i]); } return ans; } 跑兩個for, 第一次是第一次buy sell, 在這個position可以賺到的第一次profit 第二次是第二個交易, 假設在這個position buy second stock time: o(n) space: o(n)

122. Best Time to Buy and Sell Stock II Say you have an array for which the ith element is the price of a given stock on day i. Design an algorithm to find the maximum profit. You may complete as many transactions as you like (i.e., buy one and sell one share of the stock multiple times). Note: You may not engage in multiple transactions at the same time (i.e., you must sell the stock before you buy again).

public int maxProfit(int[] prices) { if (prices == null || prices.length == 0) { return 0; } int ans = 0; int pre = prices[0]; for (int i = 1; i < prices.length; i++) { if (prices[i] > pre) { ans += (prices[i] - pre); } pre = prices[i]; } return ans; } 用上升跟下降來判斷 time : o(n) space: o(1)

121 Best Time to Buy and Sell Stock Say you have an array for which the ith element is the price of a given stock on day i. If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit. Note that you cannot sell a stock before you buy one.

public int maxProfit(int[] prices) { if (prices == null || prices.length == 0) { return 0; } int max = 0; int min = Integer.MAX_VALUE; for (int i : prices) { max = Math.max(max, i - min); min = Math.min(min, i); } return max; } time: o(n) space: o(1)

53. Maximum Subarray Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum. Example: Input: [-2,1,-3,4,-1,2,1,-5,4], Output: 6 Explanation: [4,-1,2,1] has the largest sum = 6.

public int maxSubArray(int[] nums) { if (nums == null || nums.length == 0) { return 0; } int max = Integer.MIN_VALUE; int min = 0; int sum = 0; for (int i = 0; i < nums.length; i++) { sum += nums[i]; max = Math.max(max, sum - min); min = Math.min(min, sum); } return max; } time: o(n) space: o(1) dp的方式, 記得min, 同時update max

221. Maximal Square Given a 2D binary matrix filled with 0's and 1's, find the largest square containing only 1's and return its area. Example: Input: 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 Output: 4

public int maximalSquare(char[][] matrix) { if (matrix == null || matrix.length == 0 ) return 0; int ans = 0; int[][] dp = new int[matrix.length+1][matrix[0].length+1]; for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[0].length; j++) { if (matrix[i][j] == '1') { dp[i+1][j+1] = Math.min(dp[i][j+1], Math.min(dp[i+1][j], dp[i][j])) + 1; ans = Math.max(ans, dp[i+1][j+1]); } } } return ans*ans; } 用dp來解,等於找前三個min+1, 且前提是matrix[i][j]= '1' time: o(mn) space: o(mn)

253. Meeting Rooms II Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei), find the minimum number of conference rooms required.

public int minMeetingRooms(Interval[] intervals) { int[] start = new int[intervals.length]; int[] end = new int[intervals.length]; for (int i = 0; i < intervals.length; i++) { start[i] = intervals[i].start; end[i] = intervals[i].end; } Arrays.sort(start); Arrays.sort(end); int endInt = 0; int count = 0; for (int j = 0; j < start.length; j++) { if( start[j] >= end[endInt]) { endInt ++; } else { count ++; } } return count; }

64. Minimum Path Sum Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path. Note: You can only move either down or right at any point in time. 請 in place寫

public int minPathSum(int[][] grid) { if (grid == null || grid.length == 0 || grid[0].length == 0) { return 0; } int m = grid.length; int n = grid[0].length; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j ++) { if (i - 1 < 0 && j - 1 < 0) { continue; } else if (i - 1 < 0) { grid[i][j] += grid[i][j-1]; } else if (j - 1 < 0) { grid[i][j] += grid[i - 1][j]; } else { grid[i][j] += Math.min(grid[i][j-1], grid[i - 1][j]); } } } return grid[m - 1][n - 1]; } time: o(n) space: o(1) 可以不用create dp array

268. Missing Number Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missing from the array.

public int missingNumber(int[] nums) { int n = nums.length; int sum = n * (n+1) / 2; for (int i: nums) { sum -= i; } return sum; } time: o(n) space: o(1) 全部加起來,之後一個一個減掉

414. Third Maximum Number Given a non-empty array of integers, return the third maximum number in this array. If it does not exist, return the maximum number. The time complexity must be in O(n).

public int thirdMax(int[] nums) { if (nums == null || nums.length == 0) { return 0; } Integer max1 = null, max2 = null, max3 = null; for (Integer i : nums) { if (i.equals(max1) || i.equals(max2) || i.equals(max3)) { continue; } if (max1 == null || i > max1) { max3 = max2; max2 = max1; max1 = i; } else if (max2 == null || i > max2) { max3 = max2; max2 = i; } else if (max3 == null || i > max3) { max3 = i; } } return max3 == null? max1 : max3; } time: o(n) space: o(1) 記得用Integer, null and equals

694. Number of Distinct Islands Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water. Count the number of distinct islands. An island is considered to be the same as another if and only if one island can be translated (and not rotated or reflected) to equal the other.

public int numDistinctIslands(int[][] grid) { if (grid == null || grid.length == 0) return 0; Set<String> set = new HashSet<>(); for (int i = 0; i < grid.length; i++) { for (int j = 0; j < grid[0].length; j++) { if (grid[i][j] == 1) { StringBuilder sb = new StringBuilder(); helper(grid, i, j, "", sb); set.add(sb.toString()); } } } return set.size(); } private void helper(int[][] grid, int i, int j, String s, StringBuilder sb) { if(i < 0 || j < 0 || i > grid.length-1 || j > grid[0].length-1 || grid[i][j] == 0){ sb.append("0"); return; } sb.append(s); grid[i][j] = 0; helper(grid, i - 1, j, "1", sb); helper(grid, i, j - 1, "2", sb); helper(grid, i + 1, j, "3", sb); helper(grid, i, j + 1, "4", sb); } 記得是如果有一個不滿足就+0 就是除了滿足之外也要sb.append不然會有不一樣的也認成一樣的狀況

200. Number of Islands Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.

public int numIslands(char[][] grid) { if (grid == null || grid.length == 0 || grid[0].length == 0) { return 0; } int ans = 0; for (int i = 0; i < grid.length; i++) { for (int j = 0; j < grid[0].length; j++) { if (grid[i][j] == '1') { ans++; helper(grid, i, j); } } } return ans; } private void helper(char[][] grid, int i, int j) { if (grid[i][j] == '0') return; grid[i][j] = '0'; if (i - 1 >= 0) helper(grid, i-1, j); if (i + 1 < grid.length) helper(grid, i+1, j); if (j - 1 >= 0) helper(grid, i, j - 1); if (j + 1 < grid[0].length) helper(grid, i, j + 1); } 走過的變成0, 但是recursion要記得如果已經是0的直接return 的base case time: o(m*n) space: o(1)

26. Remove Duplicates from Sorted Array Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length. Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory. Example 1: Given nums = [1,1,2], Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively. It doesn't matter what you leave beyond the returned length.

public int removeDuplicates(int[] nums) { if (nums == null || nums.length == 0) { return 0; } if (nums.length == 1) return 1; int count = 1; for (int i = 1; i < nums.length; i++) { if (nums[i] != nums[i - 1]) { nums[count] = nums[i]; count++; } } return count; } time: o(n) space: o(1)

26. Remove Duplicates from Sorted Array Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length. Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.f

public int removeDuplicates(int[] nums) { if (nums == null || nums.length == 0) { return 0; } if (nums.length == 1) { return 1; } int dup = 0; for (int i = 0;i < nums.length; i++) { if (nums[i] != nums[dup]) { nums[dup + 1] = nums[i]; dup++; } } return dup+1; } two pointer來解, 因為已經是sort好的array, 所以for loop跑比較快dup就是每次要更新的position(先用dup對比是不是重複, 不是重複 就可以新增)

702. Search in a Sorted Array of Unknown Size Given an integer array sorted in ascending order, write a function to search target in nums. If target exists, then return its index, otherwise return -1. However, the array size is unknown to you. You may only access the array using an ArrayReader interface, where ArrayReader.get(k) returns the element of the array at index k (0-indexed). You may assume all integers in the array are less than 10000, and if you access the array out of bounds, ArrayReader.get will return 2147483647.

public int search(ArrayReader reader, int target) { int pow = 0; int end = 0; while (reader.get(end) < target) { end = (int)Math.pow(2, pow); if (reader.get(end) > target) { break; } pow++; } if (end == 0) { if (reader.get(end) == target) { return end; } return -1; } int start = (int)Math.pow(2, pow-1); System.out.println(start); System.out.println(end); start = start+1; while (start < end) { int mid = start + (end - start) / 2; if (reader.get(mid) >= target) { end = mid; } else { start = mid + 1; } } if (reader.get(start) == target) { return start; } else if (reader.get(end) == target) { return end; } return -1; }

33. Search in Rotated Sorted Array Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]). You are given a target value to search. If found in the array return its index, otherwise return -1. You may assume no duplicate exists in the array. Your algorithm's runtime complexity must be in the order of O(log n).

public int search(int[] nums, int target) { if(nums == null || nums.length == 0){ return -1; } //find min int start = 0; int end = nums.length-1; // int find = nums[end]; while(start < end){ int mid = start + (end - start) / 2; if(nums[mid] > nums[end]){ start = mid + 1; }else{ end = mid; } } int min = start; if(target >= nums[min] && target <= nums[nums.length-1]){ return binarySearch(nums, min, nums.length-1, target); }else{ return binarySearch(nums, 0, min-1, target); } } private int binarySearch(int[] nums, int start, int end, int target){ while(true){ if(end < start){ return -1; } int mid = start + (end-start) / 2; if(nums[mid] == target){ return mid; } if(nums[mid] < target){ start = mid + 1; }else{ end = mid - 1; } } } 先找min, 再看是要哪一邊做binary search time : o(log n) space: o(1) 有min之後等於min就好不要多此一舉 記得前面是跟nums[end]比較

42. Trapping Rain Water Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.

public int trap(int[] heights) { if (heights == null || heights.length <= 2) { return 0; } int peak = 0; for (int i = 1; i < heights.length; i++) { if (heights[i] > heights[peak]) { peak = i; } } int ans = 0; int leftPeak = 0, rightPeak = heights.length - 1; for (int i = 1; i < peak; i++) { if (heights[i] > heights[leftPeak]) { leftPeak = i; } else { ans += heights[leftPeak] - heights[i]; } } for (int i = heights.length - 2; i > peak; i--) { if (heights[i] > heights[rightPeak]) { rightPeak = i; } else { ans += heights[rightPeak] - heights[i]; } } return ans; } 找最高的那個index, 之後分左右各一次for: left_peak, right_peak, 如果小於left, right peak就加到ans, 不然就更新peak time: O(n) space: O(1)

735. Asteroid Collision We are given an array asteroids of integers representing asteroids in a row. For each asteroid, the absolute value represents its size, and the sign represents its direction (positive meaning right, negative meaning left). Each asteroid moves at the same speed. Find out the state of the asteroids after all collisions. If two asteroids meet, the smaller one will explode. If both are the same size, both will explode. Two asteroids moving in the same direction will never meet.

public int[] asteroidCollision(int[] a) { Deque<Integer> s = new LinkedList<>(); for (int i : a) { if (i > 0) s.add(i); else { while (!s.isEmpty() && s.getLast() > 0 && s.getLast() < -i) s.pollLast(); if (!s.isEmpty() && s.getLast() == -i) s.pollLast(); else if (s.isEmpty() || s.getLast() < 0) s.add(i); } } while (!s.isEmpty()) { ans[ind] = s.pollFirst(); ind++; } } time: o(n) space: o(n)

349. Intersection of Two Arrays Given two arrays, write a function to compute their intersection.

public int[] intersection(int[] nums1, int[] nums2) { if (nums1 == null || nums2 == null) { return new int[]{}; } Set<Integer> set = new HashSet<>(); Set<Integer> intersect = new HashSet<>(); for (int i : nums1) { set.add(i); } for (int j : nums2) { if (set.contains(j)) { intersect.add(j); } } int[] ans = new int[intersect.size()]; int i = 0; for (int num : intersect) { ans[i] = num; i++; } return ans; } -------------------------- public int[] intersection(int[] nums1, int[] nums2) { if (nums1 == null || nums2 == null) { return new int[0]; } if (nums1.length == 0 || nums2.length == 0) { return new int[0]; } Arrays.sort(nums1); Arrays.sort(nums2); int i = 0; int j = 0; Set<Integer> set = new HashSet<>(); while (i < nums1.length && j < nums2.length) { if (nums1[i] == nums2[j]) { set.add(nums1[i]); i++; j++; } else if (nums1[i] < nums2[j]) { i++; } else { j++; } } int[] ans = new int[set.size()]; int count = 0; for (int s : set) { ans[count] = s; count ++; } return ans; } two pointer: O(nlogn) 因為要先sort, 如果array已經sorted的話就用這個方法 o (max(len n, len m)) 第一種方法: O(n)

239. Sliding Window Maximum Given an array nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position. Return the max sliding window. Example: Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3 Output: [3,3,5,5,6,7]

public int[] maxSlidingWindow(int[] nums, int k) { if (nums == null || nums.length == 0 || k > nums.length) { return new int[]{}; } int[] ans = new int[nums.length - k + 1]; PriorityQueue<int[]> pq = new PriorityQueue<>(new Comparator<int[]>() { public int compare(int[] i1, int[] i2) { return i2[0] - i1[0]; } }); for (int i = 0; i < k; i++) { pq.offer(new int[]{nums[i], i}); } ans[0] = pq.peek()[0]; int index = 1; for (int i = k; i < nums.length; i++) { pq.offer(new int[]{nums[i], i}); while (pq.peek()[1] < index) { pq.poll(); } ans[index] = pq.peek()[0]; index++; } return ans; }

238. Product of Array Except Self Given an array nums of n integers where n > 1, return an array output such that output[i] is equal to the product of all the elements of nums except nums[i]. Example: Input: [1,2,3,4] Output: [24,12,8,6]

public int[] productExceptSelf(int[] nums) { if (nums == null || nums.length == 0) { return new int[]{}; } int[] ans = new int[nums.length]; int leftProduct = 1; for (int i = 0; i < nums.length; i++) { ans[i] = leftProduct; leftProduct *= nums[i]; } int rightProduct = 1; for (int j = nums.length - 1; j >= 0; j--) { ans[j] *= rightProduct; rightProduct *= nums[j]; } return ans; } 兩次for loop一次從左一次從右 time: o(n) space: o(1)

1. Two Sum Given an array of integers, return indices of the two numbers such that they add up to a specific target. You may assume that each input would have exactly one solution, and you may not use the same element twice. Example: Given nums = [2, 7, 11, 15], target = 9, Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].

public int[] twoSum(int[] nums, int target) { if (nums == null || nums.length == 0) { return new int[]{}; } Map<Integer, Integer> map = new HashMap<>(); int[] ans = new int[2]; for (int i = 0; i < nums.length; i++) { if (map.containsKey(target - nums[i])) { ans[0] = map.get(target - nums[i]); ans[1] = i; break; } map.put(nums[i], i); } return ans; } 用map來存value, index time: o(n) space: o(n)

88. Merge Sorted Array Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array. Note: The number of elements initialized in nums1 and nums2 are m and n respectively. You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2. Example: Input: nums1 = [1,2,3,0,0,0], m = 3 nums2 = [2,5,6], n = 3 Output: [1,2,2,3,5,6]

public void merge(int[] nums1, int m, int[] nums2, int n) { if (nums2 == null || nums2.length == 0) return; int i = m + n - 1; int l = m - 1; int r = n - 1; while (i >= 0 && l >= 0 && r >= 0) { if (nums1[l] > nums2[r]) { nums1[i] = nums1[l]; l--; } else { nums1[i] = nums2[r]; r--; } i--; } while (l >= 0) { nums1[i] = nums1[l]; l--; i--; } while (r >= 0) { nums1[i] = nums2[r]; r--; i--; } } time: o(m+n) space: o(1)

31. Next Permutation Implement next permutation, which rearranges numbers into the lexicographically next greater permutation of numbers. If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in ascending order). The replacement must be in-place and use only constant extra memory. Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the right-hand column. 1,2,3 → 1,3,2 3,2,1 → 1,2,3 1,1,5 → 1,5,1

public void nextPermutation(int[] nums) { if (nums == null || nums.length == 0) { return; } int index = -1; for (int i = nums.length - 2; i >= 0; i--) { if (nums[i] < nums[i + 1]) { index = i; break; } } if (index == -1) { Arrays.sort(nums); return; } int swapIndex = index + 1; for (int i = index + 1; i < nums.length; i++) { if (nums[i] > nums[index] && nums[i] < nums[swapIndex]) { swapIndex = i; } } swap(nums, index, swapIndex); Arrays.sort(nums, index + 1, nums.length); } private void swap(int[] nums, int index, int swapIndex) { int temp = nums[index]; nums[index] = nums[swapIndex]; nums[swapIndex] = temp; } 從後面找回來, 找到比較小的index, swap他跟 第二大的index, 之後index+1後面的必須由小排到大 找的方式要分兩次,因為要找到第二小的index, 才swap才會是next permutation Arrays.sort(array, start index, end index(exclude)) 如果最後不要直接sort的話, 可以reverse, 但是前面的if (nums[i] < nums[swapIndex]) 要加上等於

344. Reverse String Write a function that reverses a string. The input string is given as an array of characters char[]. Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory. You may assume all the characters consist of printable ascii characters.

public void reverseString(char[] s) { if (s == null || s.length == 0) return; int i = 0; int j = s.length-1; while (i < j) { char temp = s[i]; s[i] = s[j]; s[j] = temp; i++; j--; } }

186. Reverse Words in a String II Given an input string , reverse the string word by word. Example: Input: ["t","h","e"," ","s","k","y"," ","i","s"," ","b","l","u","e"] Output: ["b","l","u","e"," ","i","s"," ","s","k","y"," ","t","h","e"]

public void reverseWords(char[] str) { if (str == null || str.length == 0) { return; } reverse(str, 0, str.length - 1); int start = 0; for (int i = 0; i < str.length; i++) { if (str[i] == ' ') { reverse(str, start, i - 1); start = i + 1; } } reverse(str, start, str.length - 1); } private void reverse(char[] chars, int i, int j) { while (i < j) { char temp = chars[i]; chars[i] = chars[j]; chars[j] = temp; i++; j--; } } time: o(n) space: o(1)

75. Sort Colors Given an array with n objects colored red, white or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white and blue. Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively. Note: You are not suppose to use the library's sort function for this problem.

public void sortColors(int[] nums) { if (nums == null || nums.length == 0) { return; } int left = 0; int right = nums.length - 1; int i = 0; while (i <= right) { if (nums[i] == 2) { nums[i] = nums[right]; nums[right] = 2; right--; } else if (nums[i] == 0) { nums[i] = nums[left]; nums[left] = 0; left++; i++; } else { i++; } } } two pointer 記得while (i <=right) 記得是等於 nums[i] == 2的時候i不能動因為傳過去的也有可能是0需要再向左傳 用2,0,1來想

一些複雜度: sb.reverse()? str.substring()?

sb.reverse(): O(n) str.substring(): O(n)


Conjuntos de estudio relacionados

Writing Equations from Word Problems

View Set

Retirement Savings and Income Planning Chapter 1

View Set

Chapter 1 Health care delivery & Evidence based Nursing

View Set

Chapter 2 financial statements and cash flow

View Set

W6: Motion In The Ocean/Ocean Conveyer Belt

View Set