LeetCode 《开篇》

Posted by Jfson on 2018-12-12
  • LeetCode 《开篇》

《开篇》

PS: 先更文章,后续更新每道题目详细解读 & 视频
通过大概10道题来熟悉,常见的算法题类型:Array ,String,Stack,LinkList,Tree,Dynamic Programming,DFS/BFS,Backtracking,Greedy,Divide and Conquer

本文中的算法题大概需要2-3周来完成

1.Array

LeetCode 283.Move Zeroes (Easy)

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]

Note:

  1. You must do this in-place without making a copy of the array
  2. Minimize the total number of operations
  • Solution 1: 复制一个数组,不满足 Note 1
  • Solution 2: 遍历一遍,0就交换非0的num
    • [0,1,0,3,12] -> [1,0,0,3,12] ->[1,3,0,0,12] ->[1,3,12,0,0] ; T(n):O(n) ; operations: 3n
  • Solution 3: 遍历一遍,填充。T(n): O(2n) 满足Note 2 。operations: n
  • 题解:image
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Solution{
//Solution 2
public void moveZeroes(int[] nums) {
int j = 0;
for(int i = 0; i < nums.length; i++) {
if(nums[i] != 0) {
int temp = nums[j];
nums[j] = nums[i];
nums[i] = temp;
j++;
}
}
}
//Solution 3
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){
nums[j++] = nums[i];
}
}
for (;j<nums.length;j++){
nums[j] = 0;
}
}
}

2.Stack

LeetCode 20. Valid Parentheses (Easy)

Given a string containing just the characters ‘(’,’)’,’{’,’}’,’[’ and ’]’,determine if the input string is valid.
An input string is valid if:

1.Open brackets must be closed by the same type of brackets.
2.Open brackets must be closed in correct order.

题意:类似于代码中括号合法检测。
Note that an empty string is also considered valid.
Example 1: Input: “()” Output: true
Example 2: Input: “()[]{}” Output: true
Example 3: Input: “(]” Output: false
Example 4: Input: “()[)]” Output: false
Example 5: Input: “{[]}” Output: true

  • Solution 1: 四个if (error)
  • Solution 2: 计数 (error) ()()()[(])
  • Solution 3: Stack ()
  • 题解: image
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public boolean isValid(String s) {
HashMap<Character, Character> map = new HashMap<>();
map.put(')', '(');
map.put('}', '{');
map.put(']', '[');
Stack stack = new Stack();
for(int i = 0;i<s.length;i++) {
if(map.containtsKey(s.charAt(i))){ // end with
Character top = stack.empty() ? "*" : statck.pop(); //remove
if(top != map.get(s.charAt(i))){
return false;
}
}else{
stack.push(s.charAt(i));
}
}
return stack.empty();
}
}

3.Linked List

LeetCode 61.Rotate List (Medium)

Given a linked list , rotate the list to the right by k places , where k is non-negative

Example 1:
Input: 1 -> 2 -> 3 -> 4 -> 5 -> NULL, k = 2
Output: 4 -> 5 -> 1 -> 2 -> 3 -> NULL
Explanation:
Rotate 1 steps tp right: 5 -> 1 -> 2 -> 3 -> 4 -> NULL
Rotate 2 steps tp right: 4 -> 5 -> 1 -> 2 -> 3 -> NULL

Example 2:
Input: 0 -> 1 -> 2-> NULL ,k = 4
Output: 2-> 0 -> 1 -> NULL
Rotate 1 steps tp right: 2 -> 0 -> 1 -> NULL
Rotate 2 steps tp right: 1 -> 2 -> 0 -> NULL
Rotate 3 steps tp right: 0 -> 1 -> 2 -> NULL
Rotate 4 steps tp right: 2 -> 0 -> 1 -> NULL

  • Solution : image

    image

    • Fast index , slow index
    • Swap : image
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if (head==null||head.next==null) return head;
ListNode res = new ListNode(0);
res.next = head;
ListNode fast = res;
ListNode slower = res;
int i;
for ( i = 0; fast.next !=null; i++) {
fast = fast.next;
}
for (int j = i - k%i; j >0; j--) {
slower = slower.next;
}
// swap
fast.next = res.next;
res.next = slower.next;
slower.next = null;
return res.next;
}
}

4. Tree

589.N-ary Tree Preorder Traversal (Easy)

589 N-ary Tree Preorder Traversal

Given an n-ary tree, return the preorder traversal of its nodes’ values.
Note:
Return its preorder traversal as: [1,3,5,6,2,4].
Recursive solution is trivial, could you do it iteratively?
题意:前序遍历n叉数,不用递归,用遍历

  • Solution: 遍历
    • LcTree_1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution{
//solution: 用 stack 存储child 节点(因为前序遍历,所以遍历用倒序h)。
//用while 轮训child 节点值并存储..
public List<Integer> preorder(Node root) {
List<Integer> ret = new ArrayList<>();
if (root == null) return ret;
Stack<Node> stack = new Stack<>();
stack.add(root);
while (!stack.empty()){
root = stack.pop();
ret.add(root.val);
for (int i = root.children.size()-1; i >=0; i--) {
stack.add(root.children.get(i));
}
}
return ret;
}
}

5.Dynamic Programming

那斐波切数列:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233

  • 概念: image
  • 时间复杂度 T(n) = O(2^n) —> O(n)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
// 递归
public int fibonacci(int n){
if(n == 0){
return 0;
}else if(n == 1){
return 1;
}else { // n > 2
return fibonacci(n-1)+fibonacci(n-2);
}
}
//DP
public int fibonacciDP(int n){
int[] res = new int[n];
for(int i=0;i<=n;i++){
if(i == 0) res[i] = 0;
if(i == 1) {
res[i] = 1;
continue;
}
// i >=2
res[i] = res[i-1] + res[i-2];
}
}
}
  • 动态规划 :很多重叠子问题,问题能够分解成子问题来解决
  • 递归: 找出口 –> DP: 找递归

LeetCode: 62. Unique Paths (Medium)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).
How many possible unique paths are there?
Note: m and n will be at most 100.
Example 1:
Input: m = 3, n = 2
Output: 3
Explanation:
From the top-left corner, there are a total of 3 ways to reach the bottom-right corner:
1. Right -> Right -> Down
2. Right -> Down -> Right
3. Down -> Right -> Right
Example 2:
Input: m = 7, n = 3
Output: 28

  • solution: 找递归 image
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public int uniquePaths(int m, int n) {
if(m == 0 || n==0){
return 0;
}else if(m == 1 || n == 1){
return 1;
}else{
return uniquePathsDp(m,n-1)+ uniquePathsDp(m-1,n);
}
}
public int uniquePathsDp(int m, int n) {
if (m == 0 || n ==0) return 0;
if (m == 1 || n == 1) return 1;
int[][] dp = new int[m][n];
for(int i = 0; i<m; i++){
for(int j = 0; j<n; j++){
if(i==0||j==0)
dp[i][j] = 1;
else
dp[i][j] = dp[i][j-1] + dp[i-1][j];
}
}
return dp[m-1][n-1];
}
}
  • 时间复杂度T(n) :O(2^(m+n)) —> O(m*n)

6.DFS/BFS

  • 概念: image
  • 深度优先搜索,栈(递归)实现;广度优先搜索,队列(遍历)实现;
  • DFS: 迷宫出口,不撞南墙不回头。暴力尝试(递归操作)
  • BFS:宽度遍历树的。遍历操作

LeetCode 200. Number of Islands (Medium)

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.

Example 1:

1
2
3
4
5
6
7
> Input:
> 11110
> 11010
> 11000
> 00000
> Output: 1
>

>

Example 2:

1
2
3
4
5
6
7
> Input:
> 11000
> 11000
> 00100
> 00011
> Output: 3
>

题解: image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Solution {
// DFS
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) return 0;
int m = grid.length;
int n = grid[0].length;
int islandNums = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == '1'){
++islandNums;
dfs(grid, i, j, m, n);
}
}
}
return islandNums;
}
public void dfs(char[][] grid, int mStart, int nStart, int m, int n) {
if (mStart < 0 || nStart < 0 || mStart >= m || nStart >= n || grid[mStart][nStart] == '0') return;
grid[mStart][nStart] = '0';
dfs(grid, mStart - 1, nStart, m, n);
dfs(grid, mStart + 1, nStart, m, n);
dfs(grid, mStart, nStart - 1, m, n);
dfs(grid, mStart, nStart + 1, m, n);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Solution {
int[][] directions = new int[][]{{-1,0}, {1,0}, {0,-1}, {0,1}};
Queue<int []> q = new LinkedList();
// BFS
public int numIslands(char[][] grid) {
int m = grid.length;
if (m == 0) return 0;
int n = grid[0].length;
int ans = 0;
for (int i=0;i<m;i++) {
for (int j=0;j<n;j++) {
if (grid[i][j] == '1') {
bfs(grid, i, j);
ans++;
}
}
}
return ans;
}
public void bfs(char[][] grid, int a, int b) {
q.add(new int[]{a,b});
while (!q.isEmpty()) {
int[] arr = q.poll();
for (int i=0;i<4;i++) {
int x = arr[0] + directions[i][0];
int y = arr[1] + directions[i][1];
if (x < 0 || x >= grid.length || y <0 || y >= grid[0].length) {
continue;
}
if (grid[x][y] == '1') {
q.add(new int[]{x, y});
grid[x][y] = '0';
}
}
}
}
}

7.BackTracking

  • 暴力解法

LeetCode 78. Subsets (Medium)

Given a set of distinct integers, nums, return all possible subsets (the power set).

Note: The solution set must not contain duplicate subsets.

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
> Input: nums = [1,2,3]
> Output:
> [
> [3],
> [1],
> [2],
> [1,2,3],
> [1,3],
> [2,3],
> [1,2],
> []
> ]
>
  • Solution: image
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public List<List<Integer>> subsets(int[] nums) {
if (nums == null || nums.length == 0) return null;
List<List<Integer>> lists = new ArrayList<>();
Arrays.sort(nums);
backTracking(lists,new ArrayList<Integer>(),nums,0);
return lists;
}
public void backTracking(List<List<Integer>> list,List<Integer> tempList, int[] nums, int start) {
list.add(new ArrayList<>(tempList));
for (int i = start; i < nums.length; i++) {
if (i > start && nums[i] == nums[i-1]) continue; //skip
tempList.add(nums[i]);
backTracking(list,tempList,nums,i+1);
tempList.remove(tempList.size()-1);
}
}
}

8.Greed

  • 背包—>局部最优

LeetCode 714. Best Time to Buy and Sell Stock with Transaction Fee

Your are given an array of integers prices, for which the i-th element is the price of a given stock on day i; and a non-negative integer fee representing a transaction fee.

You may complete as many transactions as you like, but you need to pay the transaction fee for each transaction. You may not buy more than 1 share of a stock at a time (ie. you must sell the stock share before you buy again.)

Return the maximum profit you can make.

Example 1:

1
2
3
4
5
> Input: prices = [1, 3, 2, 8, 4, 9], fee = 2
> Output: 8
> Explanation: The maximum profit can be achieved by:
> Buying at prices[0] = 1Selling at prices[3] = 8Buying at prices[4] = 4Selling at prices[5] = 9The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8.
>

>

Note:

0 < prices.length <= 50000.

0 < prices[i] < 50000.

0 <= fee < 50000.

1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public int maxProfit(int[] prices, int fee) {
if (prices == null || prices.length <=1) return 0;
int cash = 0;
int hold = -prices[0];
for (int i = 1;i< prices.length;i++){
cash = Math.max(cash,hold + prices[i]-fee);
hold = Math.max(hold, cash-prices[i]);
}
return cash;
}
}

9.Divide and Conquer


pv UV: