<center>#104 Maximum Depth of Binary Tree</center>
- link
- Description:
- Given a binary tree, find its maximum depth.
- The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.
- Solution:
- 遞歸,以當前節(jié)點為根的樹最大深度是左右子樹中深度更高的那一棵加一
- Code:
# code block public int maxDepth(TreeNode root) { if (root == null) { return 0; } int left = maxDepth(root.left); int right = maxDepth(root.right); return Math.max(left, right) + 1; }
- Time Complexity: O(n)
- Space Complexity: O(1)
<center>#118 Pascal's Triangle</center>
- link
- Description:
- Given numRows, generate the first numRows of Pascal's triangle.
- Input: 5
- Output:
[ [1], [1,1], [1,2,1], [1,3,3,1], [1,4,6,4,1] ]
- Solution:
- 模擬題,根據(jù)圖上的規(guī)律來進行循環(huán)
- 注意防止數(shù)組越界
- Code:
# code block public List<List<Integer>> generate(int numRows) { List<List<Integer>> result = new ArrayList<>(); if (numRows <= 0) { return result; } List<Integer> firstRow = new ArrayList<Integer>(); firstRow.add(1); result.add(firstRow); for (int i = 2; i <= numRows; i++) { List<Integer> ithRow = new ArrayList<>(); List<Integer> lastRow = result.get(result.size() - 1); for (int j = 0; j < i; j++) { if (j == 0 || j == i - 1) { ithRow.add(1); } else { ithRow.add(lastRow.get(j - 1) + lastRow.get(j)); } } result.add(ithRow); } return result; }
<center>#119 Pascal's Triangle II</center>
- link
- Description:
- Given an index k, return the kth row of the Pascal's triangle.
- Input: 3
- Output: [1,3,3,1]
- Assumptions:
- Could you optimize your algorithm to use only O(k) extra space?
- Solution:
- Pascal's Triangle 的follow up,重點在于O(k)的空間復雜度
- 通過滾動數(shù)組的方式可以達到O(k)的空間復雜度
- Code:
# code block public List<Integer> getRow(int rowIndex) { Integer[][] rows = new Integer[2][rowIndex + 1]; rows[0][0] = 1; rows[1][0] = 1; for (int i = 0; i <= rowIndex; i++) { for (int j = 1; j < i; j++) { rows[i % 2][j] = rows[(i + 1) % 2][j - 1] + rows[(i + 1) % 2][j]; } rows[i % 2][i] = 1; } List<Integer> result = Arrays.asList(rows[rowIndex % 2]); return result; }
- Time Complexity: O(k ^ 2)
- Space Complexity: O(k)
<center>#119 Pascal's Triangle II</center>
- link
- Description:
- Given an index k, return the kth row of the Pascal's triangle.
- Input: 3
- Output: [1,3,3,1]
- Assumptions:
- Could you optimize your algorithm to use only O(k) extra space?
- Solution:
- Pascal's Triangle 的follow up,重點在于O(k)的空間復雜度
- 通過滾動數(shù)組的方式可以達到O(k)的空間復雜度
- Code:
# code block public List<Integer> getRow(int rowIndex) { Integer[][] rows = new Integer[2][rowIndex + 1]; rows[0][0] = 1; rows[1][0] = 1; for (int i = 0; i <= rowIndex; i++) { for (int j = 1; j < i; j++) { rows[i % 2][j] = rows[(i + 1) % 2][j - 1] + rows[(i + 1) % 2][j]; } rows[i % 2][i] = 1; } List<Integer> result = Arrays.asList(rows[rowIndex % 2]); return result; }
- Time Complexity: O(k ^ 2)
- Space Complexity: O(k)
<center>#121 Best Time to Buy and Sell Stock</center>
- link
- Description:
- 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 (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.
- Input: [7, 1, 5, 3, 6, 4]
- Output: 5
- Solution:
- 記錄當前遇到的最小值,每次將當前賣出與最小值買入所得利潤與最大利潤進行比較
- Code:
# code block public int maxProfit(int[] prices) { if (prices == null || prices.length <= 1) { return 0; } int profit = 0; int min = prices[0]; for (int i = 1; i < prices.length; i++) { if (prices[i] > min && prices[i] - min > profit) { profit = prices[i] - min; } min = Math.min(min, prices[i]); } return profit; }
- Time Complexity: O(n)
- Space Complexity: O(1)
<center>#122 Best Time to Buy and Sell Stock II</center>
- link
- Description:
- 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 (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
- Input: [1,2,3,1,6]
- Output: 7
- Solution:
- 這題可以簡化為找到所有的遞增區(qū)間的總增長
- Code:
# code block public int maxProfit(int[] prices) { int profit = 0; if (prices == null || prices.length <= 1) { return profit; } for (int i = 1; i < prices.length; i++) { if (prices[i] > prices[i - 1]) { profit = profit + prices[i] - prices[i - 1]; } } return profit; }
- Time Complexity: O(n)
- Space Complexity: O(1)
<center>#125 Valid Palindrome</center>
- link
- Description:
- Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.
- Input: "A man, a plan, a canal: Panama"
- Output: true
- Solution:
- 相向型的兩根指針題
- 熟悉Java的Character和String的API會很容易做
- Code:
# code block public boolean isPalindrome(String s) { if (s == null || s.length() == 0) { return true; } int start = 0, end = s.length() - 1; char[] sc = s.toCharArray(); while (start < end) { while (start < end && !Character.isLetterOrDigit(sc[start])) { start++; } while (start < end && !Character.isLetterOrDigit(sc[end])) { end--; } if (start < end) { char startL = Character.toLowerCase(sc[start]); char endL = Character.toLowerCase(sc[end]); if (startL != endL) { return false; } start++; end--; } } return true; }
- Time Complexity: O(n)
<center>#141 Linked List Cycle</center>
- link
- Description:
- Given a linked list, determine if it has a cycle in it.
- Follow up:
- Can you solve it without using extra space?
- Solution:
- 最簡單的想法就是用HashSet存訪問過的點,再遇到就返回true
- 不用額外空間的話,就最好使用快慢指針,如果快指針走到底了,就說明無環(huán),如果快慢指針相遇了,就是有環(huán)
- Code:
# code block public boolean hasCycle(ListNode head) { if (head == null || head.next == null) { return false; } ListNode slow = head.next; ListNode fast = head.next.next; while (fast != null && fast.next != null) { if (fast == slow) { return true; } fast = fast.next.next; slow = slow.next; } return false; }
- Time Complexity: O(n)
- Space Complexity: O(1)
<center>#Find Minimum in Rotated Sorted Array</center>
-
Description:
- 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.
Input: [4 5 6 7 0 1 2]
Output: 4
-
Assumptions:
- You may assume no duplicate exists in the array.
-
Solution:
- rotated排序數(shù)組, 無重復, 滿足使用二分法的條件。 取中點的值, 如果小于最后一個值, 說明從中點到最后一個值為遞增,中間不會有最小值, 反之則在。
- 注意點:
- Corner case: 數(shù)組是一個未翻轉(zhuǎn)的排序數(shù)組。
-
Code:
# code block public int findMin(int[] nums) { if (nums == null || nums.length == 0) { return 0; } int start = 0, end = nums.length - 1; while (start < end - 1) { int mid = start + (end - start) / 2; if (nums[mid] < nums[end]) { end = mid; } else { start = mid; } } return nums[start] < nums[end] ? nums[start] : nums[end]; }
Time Complexity: O(lg n)
Space Complexity: O(1)
<center>#154 Find Minimum in Rotated Sorted Array II</center>
-
Description:
- Follow up for "Find Minimum in Rotated Sorted Array":
- What if duplicates are allowed?
- Would this affect the run-time complexity? How and why?
- 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.
- Follow up for "Find Minimum in Rotated Sorted Array":
Input: [4 5 6 7 0 0 1 2]
Output: 4
-
Assumptions:
- The array may contain duplicates.
-
Solution:
復雜度上升到O(n), 不能用二分法。這題重點是不能使用二分法的原因。
二分法的本質(zhì)是通過每一次判斷舍棄一半的不可能為答案的值, 或者保留有可能是答案的那一半的值。
假設(shè)一個數(shù)組全是0, 其中有一個-1. 當我們嘗試做二分,不可能在O(1)的時間內(nèi)發(fā)現(xiàn)答案會在哪一邊。
Code:
# code block public int findMin(int[] nums) { int result = Integer.MAX_VALUE; for (int i = 0; i < nums.length; i++) { result = Math.min(nums[i], result); } return result; }
Time Complexity: O(n)
Space Complexity: O(1)
<center>#160 Intersection of Two Linked Lists</center>
- link
- Description:
- Write a program to find the node at which the intersection of two singly linked lists begins.
- Input:
A: a1 → a2 ↘ c1 → c2 → c3 ↗ B: b1 → b2 → b3
- Output: c1
- Solution:
- 這道題的基礎(chǔ)解法是使用hashtable遍歷其中一條鏈表,存儲經(jīng)過的節(jié)點,在與另一個鏈表一一比較
- 最優(yōu)的解法請參考如下solution,從算法的角度來講記下來就好,如果有興趣做數(shù)學證明的也可以嘗試一下
- Code:
# code block public ListNode getIntersectionNode(ListNode headA, ListNode headB) { if (headA == null || headB == null) { return null; } ListNode pt = headA; while (pt.next != null) { pt = pt.next; } pt.next = headB; ListNode slow = headA.next; ListNode fast = headA.next.next; while (fast != null && fast.next != null && slow != fast) { fast = fast.next.next; slow = slow.next; } if (fast == null || fast.next == null) { pt.next = null; return null; } while (slow != headA) { slow = slow.next; headA = headA.next; } pt.next = null; return slow; }
- Time Complexity: O(n)
- Space Complexity: O(1)
<center>#162 Find Peak Element</center>
- link
- Description:
- A peak element is an element that is greater than its neighbors.
- Given an input array where num[i] ≠ num[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.
- Input: [1, 2, 3, 1]
- Output: 2
- Assumptions:
- You may imagine that num[-1] = num[n] = -∞.
- Solution:
- 二分法, 如果中間值大于左右鄰居則為peak, 如果中間值小于右鄰居,則保證右邊肯定有peak, 如果中間值小于左鄰居,則保證左邊肯定有peak,保留有peak的一半。
- Code:
# code block public int findPeakElement(int[] nums) { if (nums == null || nums.length == 0) { return -1; } int start = 0, end = nums.length - 1; while (start < end - 1) { int mid = start + (end - start) / 2; if (nums[mid] > nums[mid - 1] && nums[mid] > nums[mid + 1]) { return mid; } else if (nums[mid] > nums[mid - 1]) { start = mid; } else { end = mid; } } return nums[start] > nums[end] ? start : end; }
- Time Complexity: O(lg n)
- Space Complexity: O(1)
<center>#167 Two Sum II - Input array is sorted </center>
-
Description:
- Given an array of integers that is already sorted in ascending order, find two numbers such that they add up to a specific target number.
- The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.
- You may assume that each input would have exactly one solution and you may not use the same element twice.
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
-
Assumptions:
- each input would have exactly one solution
- you may not use the same element twice
-
Solution:
- Two Sum 的題一般有兩種解法, 一種是用hash, 一種是用兩根指針。
- 對于本題來說,在排序數(shù)組中兩根指針時間復雜度為O(n)與hash相同, 空間復雜度為O(1)優(yōu)于hash的O(n)。
- 所以Two Sum加排序數(shù)組就意味著最優(yōu)解是使用兩根指針.初始化左指針left指向數(shù)組起始,初始化右指針right指向數(shù)組結(jié)尾。根據(jù)已排序這個特性:
*如果numbers[left]與numbers[right]的和value小于target,說明應(yīng)該增加value,因此left右移指向一個較大的值。
*如果value大于target,說明應(yīng)該減小value,因此right左移指向一個較小的值。
*value等于target,則找到,返回left+1和right+1。
*注意點:
*注意返回值是1-based索引,不是0-based索引
*兩個int相加可能會溢出, 但是使用int可以通過leetcode的test case, 用long更優(yōu)
-
Code:
# code block public int[] twoSum(int[] numbers, int target) { if (numbers == null || numbers.length < 2) { return new int[0]; } int[] result = new int[0]; // 初始化兩根指針 int left = 0, right = numbers.length - 1; while (left < right) { int val = numbers[left] + numbers[right]; if (val == target) { // find the answer and return it result = new int[2]; // the result should be 1-based index not the 0-based result[0] = left + 1; result[1] = right + 1; return result; } else if (val > target) { // drop the right right--; } else { // drop the left left++; } } return result; }
Time Complexity: O(n)
Space Complexity: O(1)
<center>#175 Combine Two Tables</center>
- link
- Description:
- Write a SQL query for a report that provides the following information for each person in the Person table, regardless if there is an address for each of those people:
- FirstName, LastName, City, State
- Input:
Table: Person +-------------+---------+ | Column Name | Type | +-------------+---------+ | PersonId | int | | FirstName | varchar | | LastName | varchar | +-------------+---------+ PersonId is the primary key column for this table. Table: Address +-------------+---------+ | Column Name | Type | +-------------+---------+ | AddressId | int | | PersonId | int | | City | varchar | | State | varchar | +-------------+---------+ AddressId is the primary key column for this table.
- Solution:
- 因為每個人不管地址存不存在都要在新表中,所以用person表左外連接address表
- Code:
# code block SELECT a.FirstName, a.LastName, b.City, b.State FROM Person a LEFT OUTER JOIN Address b on a.PersonId = b.PersonId;
<center>#189 Rotate Array</center>
- link
- Description:
- Rotate an array of n elements to the right by k steps.
- For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].
Could you do it in-place with O(1) extra space?
- Input: [1,2,3,4,5,6,7] 3
- Output: [5,6,7,1,2,3,4]
- Assumptions:
- 三步翻轉(zhuǎn)法,原理可以通過折紙來模擬。解決O(n)時間O(1)空間數(shù)組或者字符串左右移的最優(yōu)方法。
- Solution:
- Code:
# code block public void rotate(int[] nums, int k) { if (nums == null || nums.length < 2) { return; } int n = nums.length; k = k % n; if (k == 0) { return; } reverse(nums, 0, n - k - 1); reverse(nums, n - k, n - 1); reverse(nums, 0, n - 1); } private void reverse(int[] nums, int start, int end) { while (start < end) { int tmp = nums[start]; nums[start] = nums[end]; nums[end] = tmp; start++; end--; } }
- Time Complexity: O(n)
- Space Complexity: O(1)
<center>#206 Reverse Linked List</center>
- link
- Description:
- Reverse a singly linked list.
- Input: [1,2,3,4]
- Output: [4,3,2,1]
- Solution:
- 鏈表頭的next記得置null
- Code:
# code block public ListNode reverseList(ListNode head) { if (head == null || head.next == null) { return head; } ListNode prev = head; ListNode next = head.next; while (next != null) { ListNode tmp = next.next; next.next = prev; prev = next; next = tmp; } head.next = null; return prev; }
- Time Complexity: O(n)
- Space Complexity: O(1)
<center>#216 Combination Sum III</center>
- link
- Description:
- Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.
- Input: k = 3, n = 9
- Output: [[1,2,6], [1,3,5], [2,3,4]]
- Solution:
- 典型的隱式圖DFS遍歷, 與combination sum的區(qū)別在于多了combination元素個數(shù)的限制, 解決方案是在dfsHelper中加入一個變量記錄還需要的元素的數(shù)量。
- Code:
# code block public List<List<Integer>> combinationSum3(int k, int n) { List<List<Integer>> result = new ArrayList<>(); if (k == 0 || n <= 0) { return result; } dfsHelper(1, n, k, new ArrayList<Integer>(), result); return result; } private void dfsHelper(int start, int n, int k, List<Integer> state, List<List<Integer>> result) { if (k == 0 && n == 0) { result.add(new ArrayList<Integer>(state)); return; } if (k <= 0 || n <= 0) { return; } for (int i = start; i <= 9; i++) { if (i <= n) { state.add(i); dfsHelper(i + 1, n - i, k - 1, state, result); state.remove(state.size() - 1); } } }
<center>#217 Contains Duplicate</center>
- link
- Description:
- Given an array of integers, find if the array contains any duplicates. Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.
- Input: [1,1]
- Output: true
- Solution:
- 判斷重復使用哈希表
- Code:
# code block public boolean containsDuplicate(int[] nums) { if (nums == null || nums.length <= 1) { return false; } Set<Integer> set = new HashSet<>(); for (int i = 0; i < nums.length; i++) { if (set.contains(nums[i])) { return true; } set.add(nums[i]); } return false; }
- Time Complexity: O(n)
- Space Complexity: O(n)
<center>#283 Move Zeroes</center>
-
Description:
- 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.
Input: [0, 1, 0, 3, 12]
Output: [1, 3, 12, 0, 0]
-
Assumptions:
- You must do this in-place without making a copy of the array.
- Minimize the total number of operations.
-
Solution:
- 最基本的兩根指針問題,要求in-place并且最小化操作數(shù)量。最能理解的方法是循環(huán)一遍,去零, 再將后面意義置零。假設(shè)這個數(shù)組大部分都是零,那么總操作數(shù)就大約是兩次循環(huán)。
- 優(yōu)化的辦法是使用快慢指針。 定義左指針左邊的數(shù)不是零, 遍歷數(shù)組,一旦遇到不是零的就將左右指針的值交換, 是零就將右指針又移一格。這樣就只遍歷數(shù)組一遍。
- 該算法保證了如果右指針大于左指針, 那么左指針向右(包含左指針), 右指針向左(不包含右指針)的區(qū)域內(nèi)全部都是0.
-
Code:
# code block public void moveZeroes(int[] nums) { if (nums == null || nums.length == 0) { return; } int left = 0, right = 0; while (right < nums.length) { if (nums[right] != 0) { int tmp = nums[right]; nums[right] = nums[left]; nums[left] = tmp; left++; } right++; } }
Time Complexity: O(n)
Space Complexity: O(1)