前言
每天刷一刷,5050發。
LeetCode Top 200(50 - 100)
51 Binary Tree Level Order Traversal
二叉樹的層序遍歷
For example:
Given binary tree [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
return
[
[3],
[9,20],
[15,7]
]
Binary Tree Level Order Traversal
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
if(root == null)return new ArrayList<>();
Queue<TreeNode> q = new LinkedList<>();
List<List<Integer>> res = new ArrayList<>();
q.add(root);
//層序遍歷使用隊列 現進先出
while(!q.isEmpty()){
int size = q.size();
List<Integer> t = new ArrayList<>();
for(int i = 0; i < size; i++) {
TreeNode node = q.poll();
t.add(node.val);
if(node.left != null)
q.add(node.left);
if(node.right != null)
q.add(node.right);
}
res.add(t);
}
return res;
}
}
52 Binary Tree Zigzag Level Order Traversal
二叉樹之字型遍歷
Binary Tree Zigzag Level Order Traversal
class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if (root == null) return res;
Stack<TreeNode> stack1 = new Stack<>();
Stack<TreeNode> stack2 = new Stack<>();
stack1.add(root);
while (!stack1.isEmpty() || !stack2.isEmpty()) {
ArrayList<Integer> list = new ArrayList<>();
if (!stack1.isEmpty()) {
while (!stack1.isEmpty()) {
TreeNode node = stack1.pop();
list.add(node.val);
if (node.left != null) stack2.add(node.left);
if (node.right != null) stack2.add(node.right);
}
res.add(new ArrayList<>(list));
} else {
while (!stack2.isEmpty()) {
TreeNode node = stack2.pop();
list.add(node.val);
if (node.right != null) stack1.add(node.right);
if (node.left != null) stack1.add(node.left);
}
res.add(new ArrayList<>(list));
}
}
return res;
}
}
53 Maximum Depth of Binary Tree
二叉樹的深度
class Solution {
public int maxDepth(TreeNode root) {
if(root == null)
return 0;
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
}
54 Construct Binary Tree from Preorder and Inorder Traversa
使用前序排序和中序排序的值構造二叉樹
Construct Binary Tree from Preorder and Inorder Traversal
public class BuildTree {
public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
int preL = pre.length, inL = in.length;
if (pre == null || in == null || preL != inL)
throw new IllegalArgumentException();
return build(pre, 0, preL - 1, in, 0, inL - 1);
}
//{1,2,4,7,3,5,6,8} 前序遍歷 1 是根 (第一個元素)
//{4,7,2,1,5,3,8,6} {4,7,2 (左孩子)1(右孩子) 5,3,8,6} 進行遞歸
private TreeNode build(int[] pre, int ps, int pe, int[] in, int is, int ie) {
if (ps > pe || is > ie) return null;
TreeNode root = new TreeNode(pre[ps]);
for (int i = is; i <= ie; i++) {
if (pre[ps] == in[i]) {
root.left = build(pre, ps + 1, i - is + ps, in, is, i - 1);
root.right = build(pre, i - is + ps + 1, pe, in, i + 1, ie );
break;
}
}
return root;
}
}
55 Convert Sorted Array to Binary Search Tree
給定一個按升序排序元素的數組,將其轉換爲高度平衡的BST。對於這個問題,高度平衡二叉樹被定義爲每個節點的兩個子樹的深度相差不超過1的二叉樹。
Convert Sorted Array to Binary Search Tree
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
if(nums.length == 0)return null;
return helper(nums,0, nums.length - 1);
}
//每次取中值 構建左右子樹
private TreeNode helper(int[] nums,int l, int r){
if(l > r)return null;
if(l == r)return new TreeNode(nums[l]);
int mid = (l + r) / 2;
TreeNode root = new TreeNode(nums[mid]);
root.left = helper(nums, l , mid - 1);
root.right = helper(nums, mid + 1 , r);
return root;
}
}
56 Populating Next Right Pointers in Each Node
你得到了一個完美的二叉樹,所有的葉子都在同一個層次上,並且每個父母都有兩個孩子。二叉樹有以下內容填充每個下一個指針以指向其下一個右節點。如果沒有下一個右節點,則下一個指針應設置爲空。最初,所有下一個指針都設置爲空。
Populating Next Right Pointers in Each Node
class Solution {
public Node connect(Node root) {
if(root == null) return null;
Queue<Node> q = new LinkedList<>();
q.add(root);
while(!q.isEmpty()) {
int size = q.size();
while(size -- > 0) {
Node node = q.remove();
if(node.left != null)q.add(node.left);
if(node.right != null)q.add(node.right);
if(size != 0) {
node.next = q.peek();
}
}
}
return root;
}
}
57 Pascal’s Triangle
打印三角形
Example:
Input: 5
Output:
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> res = new ArrayList<>();
if(numRows < 1)return res;
List<Integer> list = new ArrayList<>();
for(int i = 0; i < numRows; i ++) {
list.add(0, 1);
for(int j = 1; j < i; j ++) {
list.set(j, res.get(i - 1).get(j - 1) + res.get(i - 1).get(j));
}
res.add(new ArrayList<>(list));
}
return res;
}
}
58 Best Time to Buy and Sell Stock
股票的最佳買賣時間,次數限制1。
Example:
Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
Not 7-1 = 6, as selling price needs to be larger than buying price.
Best Time to Buy and Sell Stock
class Solution {
//dp[i][k][0] = Math.max(dp[i - 1][k][0], dp[i - 1][k][1] + price[i])
//dp[i][k][1] = Math.max(dp[i - 1][k][1], dp[i - 1][k - 1][0] - price[i]);
public int maxProfit(int[] prices) {
int i_k_0 = 0;
int i_k_1 = Integer.MIN_VALUE;
for(int i = 0; i < prices.length; i ++) {
i_k_0 = Math.max(i_k_0, i_k_1 + prices[i]);
i_k_1 = Math.max(i_k_1, - prices[i]);
}
return i_k_0;
}
}
59 Best Time to Buy and Sell Stock II
股票的最佳買賣時間,不限制買賣次數。
Best Time to Buy and Sell Stock II
class Solution {
//dp[i][k][0] = Math.max(dp[i - 1][k][0], dp[i - 1][k][1] + price[i])
//dp[i][k][1] = Math.max(dp[i - 1][k][1], dp[i - 1][k - 1][0] - price[i]);
public int maxProfit(int[] prices) {
int i_k_0 = 0;
int i_k_1 = Integer.MIN_VALUE;
for(int i = 0; i < prices.length; i ++) {
int tmp = i_k_0;
i_k_0 = Math.max(i_k_0, i_k_1 + prices[i]);
i_k_1 = Math.max(i_k_1, tmp - prices[i]);
}
return i_k_0;
}
}
60 Binary Tree Maximum Path Sum
給定一個非空的二叉樹,求最大路徑和。對於此問題,路徑定義爲沿父子連接從某個起始節點到樹中任何節點的任意節點序列。路徑必須至少包含一個節點,並且不需要經過根節點。
Example:
Input: [1,2,3]
1
/ \
2 3
Output: 6
Input: [-10,9,20,null,null,15,7]
-10
/ \
9 20
/ \
15 7
Output: 42
class Solution {
public int maxPathSum(TreeNode root) {
if(root == null) return 0;
findMaxPathSum(root);
return max;
}
int max = Integer.MIN_VALUE;
private int findMaxPathSum(TreeNode node) {
if(node == null)return 0;
//如果左右節點的值小於0 則不加
int left = Math.max(0, findMaxPathSum(node.left));
int right = Math.max(0, findMaxPathSum(node.right));
max = Math.max(max , node.val + left + right);
//返回經過node節點的最大值
return node.val + Math.max(left , right);
}
}
61 Valid Palindrome
給定字符串,請僅考慮字母數字字符並忽略大小寫,從而確定它是否是迴文。
Example 1:
Input: "A man, a plan, a canal: Panama"
Output: true
Example 2:
Input: "race a car"
Output: false
class Solution {
public boolean isPalindrome(String s) {
s = s.toLowerCase(); // convert all to lower cases.
s = s.replaceAll("[^a-z^0-9]+", ""); // remove all non-digital and non-letter.
int len = s.length();
for (int i = 0; i < len; i++) {
if (s.charAt(i) != s.charAt(len - i - 1)) {
return false;
}
}
return true;
}
}
62 Word Ladder
給定兩個單詞(beginWord和endWord)以及字典的單詞列表,找到從beginWord到endWord的最短轉換序列的長度,例如:一次只能更改一個字母。每個轉換的單詞都必須存在於單詞列表中。
Example 1:
Input:
beginWord = "hit",
endWord = "cog",
wordList = ["hot","dot","dog","lot","log","cog"]
Output: 5
Explanation: As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.
Example 2:
Input:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log"]
Output: 0
Explanation: The endWord "cog" is not in wordList, therefore no possible transformation.
63 Longest Consecutive Sequence
給定一個未排序的整數數組,請找出最長的連續元素序列的長度。您的算法應以O(n)複雜度運行。
Example:
Input: [100, 4, 200, 1, 3, 2]
Output: 4
Explanation: The longest consecutive elements sequence is [1, 2, 3, 4]. Therefore its length is 4.
class Solution {
public int longestConsecutive(int[] nums) {
Set<Integer> num_set = new HashSet<Integer>();
for (int num : nums) {
num_set.add(num);
}
//最大長度
int longestStreak = 0;
for (int num : num_set) {
//找到每個序列的最小值開始計算
if (!num_set.contains(num - 1)) {
int currentNum = num;//當前數字
int currentStreak = 1;//當前的長度
while (num_set.contains(currentNum + 1)) {
currentNum += 1;
currentStreak += 1;
}
longestStreak = Math.max(longestStreak, currentStreak);
}
}
return longestStreak;
}
}
64 Surrounded Regions
給定一個包含“ X”和“ O”(字母O)的2D板,捕獲被“ X”包圍的所有區域。
Example:
X X X X
X O O X
X X O X
X O X X
After running your function, the board should be:
X X X X
X X X X
X X X X
X O X X
思路:反向填充
class Solution {
boolean isFlag[][];
int m, n;
int d[][] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
private boolean isArea(int x, int y) {
return x >= 0 && y >= 0 && x < m && y < n;
}
private void flag(char[][] board, int x, int y, boolean flag) {
if (flag) board[x][y] = 'X';
isFlag[x][y] = true;
for (int i = 0; i < 4; i++) {
int newX = x + d[i][0];
int newY = y + d[i][1];
if (isArea(newX, newY) && board[newX][newY] == 'O' && !isFlag[newX][newY])
flag(board, newX, newY, flag);
}
}
public void solve(char[][] board) {
m = board.length;
if (m == 0) return;
n = board[0].length;
isFlag = new boolean[m][n];
for (int j = 0; j < n; j++) {
if (board[0][j] == 'O') {
flag(board, 0, j, false);
}
if (board[m - 1][j] == 'O') {
flag(board, m - 1, j, false);
}
}
for (int i = 0; i < m; i++) {
if (board[i][0] == 'O') {
flag(board, i, 0, false);
}
if (board[i][n - 1] == 'O') {
flag(board, i, n - 1, false);
}
}
for (int i = 1; i < m; i++)
for (int j = 1; j < n; j++)
if (board[i][j] == 'O' && !isFlag[i][j]) {
flag(board, i, j, true);
}
}
}
65 Palindrome Partitioning
給定字符串s,分區s,使得分區的每個子字符串都是迴文。返回s的所有可能的迴文分區。
Example:
Input: "aab"
Output:
[
["aa","b"],
["a","a","b"]
]
public List<List<String>> partition(String s) {
int len = s.length();
boolean[][] dp = new boolean[len][len];
List<List<String>> r = new ArrayList<>();
dfs(r, s, 0, new ArrayList<>(), dp);
return r;
}
void dfs(List<List<String>> r, String s, int start, List<String> path, boolean[][] dp) {
int len = s.length();
if (start >= len) r.add(new ArrayList<>(path));
for (int i = start; i < len; i++) {
// i
// abca ... //a == a, ok
if (s.charAt(i) != s.charAt(start)) continue;
// i
// abca ... //b != c continue
if (i - 1 > start + 1 && !dp[start + 1][i - 1]) continue;
dp[start][i] = true;
path.add(s.substring(start, i + 1));
dfs(r, s, i + 1, path, dp);
path.remove(path.size() - 1);
}
}
66 Gas Station
沿循環路線有N個加油站,其中加氣站i的氣體量爲gas [i]。您有一輛帶無限油箱的汽車,從第i站到下一個(i + 1)的行車成本爲[i]。您可以從其中一個加油站的空罐開始旅程。如果您可以沿順時針方向繞過迴路一次,則返回起始加油站的索引,否則返回-1。
Example:
Input:
gas = [1,2,3,4,5]
cost = [3,4,5,1,2]
Output: 3
Explanation:
Start at station 3 (index 3) and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 4. Your tank = 4 - 1 + 5 = 8
Travel to station 0. Your tank = 8 - 2 + 1 = 7
Travel to station 1. Your tank = 7 - 3 + 2 = 6
Travel to station 2. Your tank = 6 - 4 + 3 = 5
Travel to station 3. The cost is 5. Your gas is just enough to travel back to station 3.
Therefore, return 3 as the starting index.
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int n = gas.length;
if(n==0) return -1;
int start = 0;
int residual = 0;
int sum = 0;
for(int i = 0; i < n; i++){
sum += gas[i] - cost[i];
residual += gas[i] - cost[i];
//如果剩餘的小於 到下一站到距離,則說明起始點一定不是這站和之前到站
if(residual < 0){
start = i + 1;
residual = 0;
}
}
//sum爲跑完之後剩下的油,如果>=0,則說明可以跑完 返回start
//不能跑完返回-1
return sum >= 0 ? start : -1;
}
}
67 Single Number
給定一個非空的整數數組,每個元素出現兩次,除了一個。找到那一個。
思路:0 ^ n = n. n ^ n = 0;
class Solution {
public int singleNumber(int[] nums) {
if(nums.length == 0)return 0;
int res = nums[0];
for(int i = 1; i < nums.length; i ++) {
res ^= nums[i];
}
return res;
}
}
68 Copy List with Random Pointer
複製複雜鏈表,這個鏈表不僅有指向下一個節點的指針,還有一個指向隨機節點的指針
/*
// Definition for a Node.
class Node {
int val;
Node next;
Node random;
public Node(int val) {
this.val = val;
this.next = null;
this.random = null;
}
}
*/
class Solution {
public Node copyRandomList(Node head) {
if (head == null) return null;
Node node = head;
//在原鏈表的每個節點後面添加一個相同節點
while (node != null) {
Node nNode = new Node(node.val);
nNode.next = node.next;
node.next = nNode;
node = nNode.next;
}
//複製隨機節點
node = head;
while (node != null) {
if(node.random != null)
node.next.random = node.random.next;
node = node.next.next;
}
//分裂兩個鏈表
Node pre = new Node(0);
Node npre = new Node(0);
pre.next = head;
npre.next = head.next;
node = head;
Node nNode = head.next;
while (node != null) {
node.next = nNode.next;
node = node.next;
if(node == null)break;
nNode.next = node.next;
nNode = nNode.next;
}
// while(head != null) {
// System.out.print("[" + head.val + "," +
// (head.random == null ? "null" : head.random.val) + " ]");
// head = head.next;
// }
return npre.next;
}
}
69 Word Break
給定一個非空字符串s和包含非空單詞列表的字典wordDict,請確定s是否可以分段爲一個或多個字典單詞的以空格分隔的序列。
class Solution {
HashMap<String, Boolean> map = new HashMap<>();
public boolean wordBreak(String s, List<String> wordDict) {
if (s == null || s.isEmpty()) return true;
if (map.containsKey(s)) return map.get(s);
for (String w : wordDict) {
int val = s.indexOf(w);
if (val != -1) {
//剔除符合條件的字符串
String temp = s.substring(0, val);
String temp1 = s.substring(val + w.length(), s.length());
if (wordBreak(temp, wordDict) && wordBreak(temp1, wordDict)) {
map.put(s, true);
return true;
}
}
}
map.put(s, false);
return false;
}
}
70 Word Break II
給定一個非空字符串s和包含非空單詞列表的字典wordDict,請確定s是否可以分段爲一個或多個字典單詞的以空格分隔的序列。輸出可能的分段信息。
71 Linked List Cycle
判斷鏈表中是否存在環
public class Solution {
public boolean hasCycle(ListNode head) {
if(head == null)return false;
ListNode low = head;
ListNode fast = head;
while(fast != null && fast.next != null) {
low = low.next;
fast = fast.next.next;
if(low == fast)return true;
}
return false;
}
}
72 LRU Cache
實現LRU算法
class LRUCache {
class Node {
int key;
int value;
Node next;
Node pre;
public Node(){}
public Node(int key, int value) {
this.key = key;
this.value = value;
next = null;
pre = null;
}
}
Node head;
Node tail;
int capacity;
HashMap<Integer, Node> map;
public LRUCache(int capacity) {
if (capacity <= 0) throw new IllegalArgumentException();
this.capacity = capacity;
map = new HashMap<>();
head = new Node();
tail = new Node();
//初始化頭尾指針
tail.pre = head;
head.next = tail;
}
public int get(int key) {
if (!map.containsKey(key)) return -1;
return moveHead(key).value;
}
public Node moveHead(int key) {
Node node = map.get(key);
if(node.pre == head) return node;
//刪除當前位置節點
Node preNode = node.pre;
preNode.next = node.next;
preNode.next.pre = preNode;
//設置到頭節點
putHead(node);
return node;
}
private Node putHead(Node node) {
node.next = head.next;
head.next = node;
node.pre = head;
node.next.pre = node;
return node;
}
public void put(int key, int value) {
if(map.containsKey(key)) {
//將節點放到第一個
//修改新值
moveHead(key).value = value;
} else {
Node node = putHead(new Node(key, value));
map.put(key, node);
}
if (map.size() > capacity) {
removeTail(tail.pre);
}
}
private void removeTail(Node node) {
tail.pre = tail.pre.pre;
tail.pre.next = tail;
map.remove(node.key);
}
}
73 Sort List
使用恆定的空間複雜度,以O(n log n)時間對鏈表進行排序。
class Solution {
public ListNode sortList(ListNode head) {
if(head == null)return null;
ListNode dummyMin = new ListNode(1);
ListNode dummyMax = new ListNode(1);
ListNode preMin = dummyMin;
ListNode preMax = dummyMax;
ListNode pre;
pre = head;
ListNode node = head.next;
while(node != null) {
if(node.val > head.val) {
preMax.next = node;
preMax = preMax.next;
} else if(node.val < head.val) {
preMin.next = node;
preMin = preMin.next;
} else {
pre.next = node;
pre = pre.next;
}
node = node.next;
}
preMax.next = preMin.next = pre.next = null;
dummyMin.next = sortList(dummyMin.next);
dummyMax.next = sortList(dummyMax.next);
ListNode minListNode = dummyMin;
while(minListNode.next != null) {
minListNode = minListNode.next;
}
minListNode.next = head;
pre.next = dummyMax.next;
return dummyMin.next;
}
}
74 Max Points on a Line(Hard)
給定2D平面上的n個點,求出同一直線上的最大點數。
75 Evaluate Reverse Polish Notation
用反向波蘭語表示法計算算術表達式的值。有效的運算符爲+,-,*,/。每個操作數可以是整數或另一個表達式。注意:兩個整數之間的除法應截斷爲零。給定的RPN表達式始終有效。這意味着表達式將始終求結果,並且不會被零運算除以。
Example 1:
Input: ["2", "1", "+", "3", "*"]
Output: 9
Explanation: ((2 + 1) * 3) = 9
Example 2:
Input: ["4", "13", "5", "/", "+"]
Output: 6
Explanation: (4 + (13 / 5)) = 6
Evaluate Reverse Polish Notation
76 Maximum Product Subarray
給定一個整數數組nums,在具有最大乘積的數組(至少包含一個數字)中找到連續的子數組。
class Solution {
public int maxProduct(int[] nums) {
if(nums == null || nums.length < 1)return 0;
int max = nums[0];
int min = nums[0];
int res = max;
for(int i = 1; i < nums.length; i ++) {
if(nums[i] < 0) {
int tmp = max;
max = min;
min = tmp;
}
max = Math.max(nums[i], nums[i] * max);
min = Math.min(nums[i], nums[i] * min);
res = Math.max(max, res);
}
return res;
}
}
77 Min Stack
設計一個堆棧,該堆棧支持在固定時間內推送,彈出,頂出和檢索最小元素。push(x)-將元素x推入堆棧pop()-刪除堆棧頂部的元素。top()-獲取頂部元素。getMin()-檢索堆棧中的最小元素。
class MinStack {
/** initialize your data structure here. */
int min = Integer.MAX_VALUE;
Stack<Integer> stack;
public MinStack() {
stack = new Stack<Integer>();
}
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;
}
}
78 Intersection of Two Linked Lists
返回兩個鏈表的交點
Intersection of Two Linked Lists
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null)
return null;
ListNode a = headA;
ListNode b = headB;
while(a != b){
a = a == null ? headB : a.next;
b = b == null ? headA : b.next;
}
return a;
}
}
79 Find Peak Element
峯值元素是大於其相鄰元素的元素。給定一個輸入數組nums,其中nums [i]≠nums [i + 1],找到一個峯值元素並返回其索引。該數組可能包含多個峯,在這種情況下,將索引返回到任何一個峯都可以。
Example 1:
Input: nums = [1,2,3,1]
Output: 2
Explanation: 3 is a peak element and your function should return the index number 2.
Example 2:
Input: nums = [1,2,1,3,5,6,4]
Output: 1 or 5
Explanation: Your function can return either index number 1 where the peak element is 2,
or index number 5 where the peak element is 6.
class Solution {
public int findPeakElement(int[] nums) {
int l = 0, r = nums.length - 1;
while(l < r) {
int mid = l - (l - r) / 2;
if(nums[mid] > nums[mid + 1])
r = mid;
else
l = mid + 1;
}
return l;
}
}
80 Missing Ranges(VIP專享)
81 Fraction to Recurring Decimal
給定兩個表示分數的分子和分母的整數,以字符串格式返回分數。如果小數部分是重複的,請將重複的部分括在括號中。
Example 1:
Input: numerator = 1, denominator = 2
Output: "0.5"
Example 2:
Input: numerator = 2, denominator = 1
Output: "2"
Example 3:
Input: numerator = 2, denominator = 3
Output: "0.(6)"
public String fractionToDecimal(int numerator, int denominator) {
if (denominator == 0) return "";
StringBuilder str = new StringBuilder();
HashMap<Long, Integer> map = new HashMap<Long, Integer>();
if (numerator < 0 && denominator > 0 || numerator > 0 && denominator < 0) {
str.append('-');
}
long num = Math.abs((long) numerator);
long den = Math.abs((long) denominator);
long n = num / den;
long reminder = num % den;
str.append(n);
if (reminder == 0) return str.toString();
else str.append('.');
while (!map.containsKey(reminder)) {
map.put(reminder, str.length());
n = reminder * 10 / den;
reminder = reminder * 10 % den;
if (reminder != 0 || reminder == 0 && !map.containsKey(reminder)) {
str.append(n);
}
}
if (reminder != 0) {
str.insert(map.get(reminder), "(");
str.append(')');
}
return str.toString();
}
82 Majority Element
給定大小爲n的數組,找到多數元素。多數元素是出現超過⌊n / 2倍的元素。您可以假定數組爲非空,並且多數元素始終存在於數組中
class Solution {
public int majorityElement(int[] nums) {
int count = 0;
Integer candidate = null;
for (int num : nums) {
if (count == 0) {
candidate = num;
}
count += (num == candidate) ? 1 : -1;
}
return candidate;
}
}
83 Excel Sheet Column Number
給定列標題(如Excel工作表中所示),返回其對應的列號。例如:
For example:
A -> 1 B -> 2 C -> 3 ... Z -> 26 AA -> 27 AB -> 28 ...
class Solution {
public int titleToNumber(String s) {
int sum = 0;
for(int i = 0; i < s.length(); i ++){
sum = sum * 26 + (s.charAt(i) - 'A' + 1);
}
return sum;
}
}
84 Factorial Trailing Zeroes
給定整數n,返回n!中尾隨零的數目。
class Solution {
public int trailingZeroes(int n) {
return n < 5 ? 0 : n / 5 + trailingZeroes(n / 5);
}
}
85 Largest Number
給定一個非負整數列表,將它們排列爲最大的數字。
Example 1:
Input: [10,2]
Output: "210"
Example 2:
Input: [3,30,34,5,9]
Output: "9534330"
class Solution {
public String largestNumber(int[] numbers) {
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < numbers.length; i++) {
list.add(numbers[i]);
}
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
String s1 = o1 + "" + o2;
String s2 = o2 + "" + o1;
return s2.compareTo(s1);
}
});
if(list.get(0) == 0)return "0";
String res = "";
for (int i = 0; i < list.size(); i++) {
res += list.get(i);
}
return res;
}
}
86 Rotate Array
給定一個數組,將數組向右旋轉k步,其中k爲非負數。
Example:
Input: [1,2,3,4,5,6,7] and k = 3
Output: [5,6,7,1,2,3,4]
Explanation:
rotate 1 steps to the right: [7,1,2,3,4,5,6]
rotate 2 steps to the right: [6,7,1,2,3,4,5]
rotate 3 steps to the right: [5,6,7,1,2,3,4]
class Solution {
public void rotate(int[] nums, int k) {
if(nums == null || nums.length == 0 || k <= 0)return;
int n = k % nums.length;
reverse(nums, 0, nums.length - 1);
reverse(nums, 0, n - 1);
reverse(nums, n, nums.length - 1);
}
private void reverse(int[] nums,int l, int r) {
while(l < r) {
int tmp = nums[l];
nums[l] = nums[r];
nums[r] = tmp;
l ++;
r --;
}
}
}
87 Reverse Bits
給定的32位無符號整數的反向位。
Example:
Input: 00000010100101000001111010011100
Output: 00111001011110000010100101000000
Explanation: The input binary string 00000010100101000001111010011100 represents the unsigned integer 43261596, so return 964176192 which its binary representation is 00111001011110000010100101000000.
public class Solution {
// you need treat n as an unsigned value
public int reverseBits(int n) {
int res = 0;
for(int i = 0; i < 32; i ++){
res <<= 1;
res |= n & 1;
n >>= 1;
}
return res;
}
}
88 Populating Next Right Pointers in Each Node
您將得到一棵完美的二叉樹,其中所有葉子都在同一水平上,每個父級都有兩個孩子。二進制樹具有以下定義:
struct Node { int val; Node *left; Node *right; Node *next; }
填充每個下一個指針以指向其下一個右節點。如果沒有下一個右節點,則下一個指針應設置爲NULL。最初,所有下一個指針都設置爲NULL。
Populating Next Right Pointers in Each Node
class Solution {
public Node connect(Node root) {
if (root == null) return null;
if (root.left != null) {
root.left.next = root.right;
root.right.next = root.next == null ? null : root.next.left;
}
connect(root.left);
connect(root.right);
return root;
}
}
89 Number of 1 Bits
編寫一個函數,該函數採用無符號整數並返回其具有的’1’位的數量(也稱爲漢明權重)
Example 1:
Input: 00000000000000000000000000001011
Output: 3
Explanation: The input binary string 00000000000000000000000000001011 has a total of three '1' bits.
public class Solution {
// you need to treat n as an unsigned value
public int hammingWeight(int n) {
int count = 0;
while(n != 0) {
n &= n - 1;
count ++;
}
return count;
}
}
90 House Robber
您是計劃在街道上搶房屋的專業強盜。每棟房屋都藏有一定數量的金錢,阻止您搶劫每座房屋的唯一限制是相鄰房屋都已連接了安全系統,如果在同一晚闖入兩棟相鄰房屋,它將自動與警方聯繫。給定代表每個房屋的金額的非負整數列表,請確定您今晚可在不提醒警察的情況下搶走的最大金額。
Example 1:
Input: [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.
- 1 記憶化搜索
class Solution {
int memo[];
public int rob(int[] nums) {
if(nums == null || nums.length == 0)return 0;
memo = new int[nums.length];
Arrays.fill(memo, -1);
return tryRob(nums, 0);
}
public int tryRob(int[] nums, int index) {
if(index >= nums.length)return 0;
if(memo[index] != -1)return memo[index];
int res = 0;
for(int i = index; i < nums.length; i ++) {
//偷和不偷兩個狀態
res = Math.max(res, nums[i] + tryRob(nums, i + 2));
}
memo[index] = res;
return res;
}
}
- 2 動態規劃
class Solution {
public int rob(int[] nums) {
if(nums == null || nums.length == 0)return 0;
memo = new int[nums.length];
memo[nums.length - 1] = nums[nums.length - 1];
for(int i = nums.length -2; i >= 0; i --) {
for(int j = i; j < nums.length; j ++) {
memo[i] = Math.max(memo[i], nums[j] +
(j + 2 < nums.length ? memo[j + 2] : 0));
}
}
return memo[0];
}
}
91 Number of Islands
給定二維地圖“ 1”(土地)和“ 0”(水),計算島嶼的數量。一個島嶼被水包圍,是通過水平或垂直連接相鄰的陸地而形成的。您可以假定網格的所有四個邊緣都被水包圍。
Example :
Input:
11110
11010
11000
00000
Output: 1
class Solution {
int m, n;
boolean visited[][];
int[][] move;
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) return 0;
m = grid.length;
n = grid[0].length;
visited = new boolean[m][n];
move = new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int count = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (!visited[i][j] && grid[i][j] =='1'){
fill(grid, i, j);
count++;
}
}
}
return count;
}
private void fill(char[][] grid, int x, int y) {
visited[x][y] = true;
for (int i = 0; i < 4; i++) {
int newX = x + move[i][0];
int newY = y + move[i][1];
if (isArea(newX, newY) && !visited[newX][newY] && grid[newX][newY] == '1') {
fill(grid, newX, newY);
}
}
}
private boolean isArea(int x, int y) {
return x >= 0 && x < m && y >= 0 && y < n;
}
}
92 Happy Number
編寫算法以確定數字是否爲“ happy”。一個快樂的數字是由以下過程定義的數字:以任何正整數開頭,用該數字的平方和代替該數字,然後重複該過程,直到該數字等於1(它將停留在該數字處),否則它將循環在不包含1的循環中無休止地循環。以1結尾的那些數字是快樂數字。
Example:
Input: 19
Output: true
Explanation:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
class Solution {
public boolean isHappy(int n) {
String num = n + "";
int sum = 0;
HashSet<Integer> set = new HashSet<Integer>();
for (int i = 0; i < num.length(); i++) {
sum += (num.charAt(i) - '0') * (num.charAt(i) - '0');
if (i + 1 == num.length() && sum == 1) {
return true;
}
if (i + 1 == num.length() && sum != 1) {
if (!set.add(sum))
return false;
i = -1;
num = sum + "";
sum = 0;
}
}
return false;
}
}
93 Count Primes
找到n以內的所有素數
class Solution {
// 找到n以內的所有素數個數
public int countPrimes(int n) {
//默認值是false,如果是不是素數我們標爲true
//當然你也可以使用 Arrays.fill(f, true); 默認全設爲true,如果不是素數我們設爲false
boolean s[] = new boolean[n];
//如果n小於3的話就沒有 因爲找到n以內 所以2以內是沒有的
if (n < 3) return 0;
//c 可以理解爲最多的素數個數
//以爲我們知道所有的偶數都不是素數,所有我們可以剔除一半
//但是你可能會有疑問 2 不是偶數嗎 --> 這裏 2 和 1 相抵消
//比如 5 以內的話 5 / 2 = 2 素數就爲 2 和 3
//首先我們假設 小於 c 的奇數全是素數
int c = n / 2;
// 之後我們只要剔除 在這個奇數範圍內 不是素數的數就可以了
// 因爲我們已經把偶數去掉了,所以只要剔除奇數的奇數倍就可以了
for (int i = 3; i * i < n; i += 2) {
//說明 i 是不是素數,而且已經是剔除過的
if (s[i])
continue;
//這裏是計算c 中剔除完不是素數的奇數個數 下面解釋各個值的含義
//我們要剔除的是 i 的 奇數倍
//爲什麼是 i * i開始呢 我們打個比方,假設我們此時i = 5
//那麼我們開始剔除 j = 1 時就是本身,此時要麼已經被剔除,要麼就是素數,所以 1 不考慮
//當 j = 2 || j = 4時,乘積爲偶數所以也不在我們考慮範圍內
//當 j = 3時,我們考慮 3 * 5 但是這種情況已經是當 i = 3的時候被考慮進去了所以我們只要考慮之後的就可以了
//那麼爲什麼 j = j + i * 2呢
//根據上面所說 我們從3開始考慮 3 * 3,3 * 5,3 * 7....只要 j < n 我們就剔除
//帶入i : i * i, i * ( i + 2 ) , i * ( i + 4 )....
for (int j = i * i; j < n; j += i * 2) {
//只要找到c個奇數中的合數,c就減1,把 j標記爲非素數
if (!s[j]) {
s[j] = true;
c--;
}
}
}
return c;
}
}
94 Reverse Linked List
反轉鏈表
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null)return null;
ListNode pre = null;
ListNode node = head;
while(node != null) {
ListNode next = node.next;
node.next = pre;
pre = node;
node = next;
}
return pre;
}
}
95 Course Schedule(圖)
您必須參加總共numCourses課程,從0到numCourses-1標記。某些課程可能有先決條件,例如,要學習課程0,您必須首先學習課程1,該課程以一對錶示:[0,1]給定課程總數和先決條件對列表,您是否可以完成所有課程?
Example 1:
Input: numCourses = 2, prerequisites = [[1,0]]
Output: true
Explanation: There are a total of 2 courses to take.
To take course 1 you should have finished course 0. So it is possible.
Example 2:
Input: numCourses = 2, prerequisites = [[1,0],[0,1]]
Output: false
Explanation: There are a total of 2 courses to take.
To take course 1 you should have finished course 0, and to take course 0 you should
also have finished course 1. So it is impossible.
96 Implement Trie (Prefix Tree)
實現一個單詞查找樹與插入、搜索和startsWith
class Trie {
TrieNode root;
/**
* Initialize your data structure here.
*/
public Trie() {
root = new TrieNode();
}
/**
* Inserts a word into the trie.
*/
public void insert(String word) {
TrieNode p = root;
for (char c : word.toCharArray()) {
if (p.kids[c - 'a'] == null) {
p.kids[c - 'a'] = new TrieNode();
}
p = p.kids[c - 'a'];
}
p.isEnd = true;
}
/**
* Returns if the word is in the trie.
*/
public boolean search(String word) {
TrieNode p = root;
for (char c : word.toCharArray()) {
if (p.kids[c - 'a'] == null) {
return false;
}
p = p.kids[c - 'a'];
}
return p.isEnd;
}
/**
* Returns if there is any word in the trie that starts with the given prefix.
*/
public boolean startsWith(String prefix) {
TrieNode p = root;
for (char c : prefix.toCharArray()) {
if (p.kids[c - 'a'] == null) {
return false;
}
p = p.kids[c - 'a'];
}
return true;
}
}
class TrieNode {
TrieNode[] kids;
boolean isEnd;
public TrieNode() {
kids = new TrieNode[26];
isEnd = false;
}
}
97 Word Search II
給定2D木板和詞典中的單詞列表,請在木板中查找所有單詞。每個單詞必須由順序相鄰的單元格的字母構成,其中“相鄰”單元格是水平或垂直相鄰的單元格。同一字母單元在一個單詞中最多隻能使用一次。
Example:
Input:
board = [
['o','a','a','n'],
['e','t','a','e'],
['i','h','k','r'],
['i','f','l','v']
]
words = ["oath","pea","eat","rain"]
Output: ["eat","oath"]
class Solution {
public List<String> findWords(char[][] board, String[] words) {
List<String> res = new ArrayList<>();
TrieNode root = buildTrie(words);
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
dfs(board, i, j, root, res);
}
}
return res;
}
private void dfs(char[][] board, int i, int j, TrieNode root, List<String> res) {
char ch = board[i][j];
if (ch == '#' || root.next[ch - 'a'] == null) return;
if (root.next[ch - 'a'].word != null) {
res.add(root.next[ch - 'a'].word);
root.next[ch - 'a'].word = null;
}
root = root.next[ch - 'a'];
board[i][j] = '#';
if (i > 0) dfs(board, i - 1, j, root, res);
if (j > 0) dfs(board, i, j - 1, root, res);
if (i < board.length - 1) dfs(board, i + 1, j, root, res);
if (j < board[0].length - 1) dfs(board, i, j + 1, root, res);
board[i][j] = ch;
}
class TrieNode {
String word;
TrieNode[] next = new TrieNode[26];
}
private TrieNode buildTrie(String[] words) {
TrieNode root = new TrieNode();
for (String w : words) {
TrieNode p = root;
for (char ch : w.toCharArray()) {
if (p.next[ch - 'a'] == null) {
p.next[ch - 'a'] = new TrieNode();
}
p = p.next[ch - 'a'];
}
p.word = w;
}
return root;
}
}
98 Maximum Subarray
class Solution {
public int maxSubArray(int[] nums) {
int max = nums[0];
int res = nums[0];
for(int i = 1; i < nums.length; i ++){
max = Math.max(nums[i] , max + nums[i]);
res = Math.max(res , max);
}
return res;
}
}
99 Kth Largest Element in an Array
找到一個無序數組中的最大k元素。返回座標。
Kth Largest Element in an Array
public class Solution {
public int findKthLargest(int[] arr, int k) {
if (arr == null || arr.length == 0)
return 0;
int n = arr.length;
int start = 0;
int end = n - 1;
int index = partition(arr, start, end);
while (index != k - 1) {
if (index > k - 1) {
end = index - 1;
} else {
start = index + 1;
}
index = partition(arr, start, end);
}
return arr[index];
}
private int partition(int[] arr, int l, int r) {
int tmp = arr[l];
while (l < r) {
while (l < r && arr[r] <= tmp) r--;
arr[l] = arr[r];
while (l < r && arr[l] >= tmp) l++;
arr[r] = arr[l];
}
arr[l] = tmp;
return l;
}
}
100 Contains Duplicate
給定一個整數數組,查找該數組是否包含任何重複項。
如果任何值在數組中至少出現兩次,則函數應返回true;如果每個元素都不同,則函數應返回false。
class Solution
{
public boolean containsDuplicate(int[] nums)
{
HashSet<Integer> set = new HashSet<>();
for (int i = 0; i < nums.length; i++)
if (!set.add(nums[i]))
return true;
return false;
}
}