LeetCode之Array題目彙總

Two Sum

Given an array of integers, 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.

Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2


參考:LeetCode 001 Two Sum

    public int[] twoSum(int[] nums, int target) {

        if (nums == null || nums.length <= 1) {
            return new int[2];
        }

        Map<Integer, Integer> map = new HashMap<Integer, Integer>();

        // key = target - nums[i], just one solution
        for (int i = 0; i < nums.length; i++) {
            map.put(target - nums[i], i);
        }

        for (int i = 0; i < nums.length; i++) {
            Integer v = map.get(nums[i]);

            // can't use itself
            if (v != null && v != i) {
                return new int[] { i + 1, v + 1 };
            }
        }

        return null;
    }

3Sum

Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:

  • Elements in a triplet (a,b,c) must be in non-descending order. (ie, abc)
  • The solution set must not contain duplicate triplets.
    For example, given array S = {-1 0 1 2 -1 -4},

    A solution set is:
    (-1, 0, 1)
    (-1, -1, 2)

參考:LeetCode 015 3Sum

分析:

  1. 對數組進行排序;
  2. start從0到n-1,對num[start]求另外兩個數,這裏用mid和end;
  3. mid指向start+1,q指向結尾。sum = num[start] + num[mid]+ num[end];
  4. 利用加逼定理求解,終止條件是mid == end;
  5. 順帶去重

去重:

  1. 如果start到了start+1,num[start] == num[start - 1],則求出的解肯定重複了;
  2. 如果mid++,num[mid] = num[mid - 1],則求出的解肯定重複了。
    public List<List<Integer>> threeSum(int[] nums) {

        if (nums == null || nums.length < 3) {
            return new ArrayList<List<Integer>>();
        }

        Set<List<Integer>> set = new HashSet<List<Integer>>();

        Arrays.sort(nums);

        for (int start = 0; start < nums.length; start++) {

            if (start != 0 && nums[start - 1] == nums[start]) {
                continue;
            }

            int mid = start + 1, end = nums.length - 1;

            while (mid < end) {

                int sum = nums[start] + nums[mid] + nums[end];

                if (sum == 0) {

                    List<Integer> tmp = new ArrayList<Integer>();
                    tmp.add(nums[start]);
                    tmp.add(nums[mid]);
                    tmp.add(nums[end]);
                    set.add(tmp);

                    while (++mid < end && nums[mid - 1] == nums[mid])
                        ;
                    while (--end > mid && nums[end + 1] == nums[end])
                        ;
                }

                else if (sum < 0) {
                    mid++;
                }

                else {
                    end--;
                }
            }
        }

        return new ArrayList<List<Integer>>(set);
    }

3Sum Closest

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

    For example, given array S = {-1 2 1 -4}, and target = 1.

    The sum that is closest to the target is 2\. (-1 + 2 + 1 = 2).

參考:LeetCode 016 3Sum Closest

    public int threeSumClosest(int[] nums, int target) {

        if (nums == null || nums.length < 3) {
            return Integer.MIN_VALUE;
        }

        Arrays.sort(nums);

        int minGap = Integer.MAX_VALUE;
        int result = 0;

        for (int start = 0; start < nums.length; start++) {

            int mid = start + 1, end = nums.length - 1;

            while (mid < end) {

                int sum = nums[start] + nums[mid] + nums[end];
                int gap = Math.abs(sum - target);

                if (gap < minGap) {
                    minGap = gap;
                    result = sum;
                }

                if (sum < target) {
                    mid++;
                } else {
                    end--;
                }
            }
        }

        return result;
    }

4Sum

Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note:

  • Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, abcd)
  • The solution set must not contain duplicate quadruplets.
    For example, given array S = {1 0 -1 0 -2 2}, and target = 0.

    A solution set is:
    (-1,  0, 0, 1)
    (-2, -1, 1, 2)
    (-2,  0, 0, 2)

參考:LeetCode 018 4Sum

    public List<List<Integer>> fourSum(int[] nums, int target) {

        if (nums == null || nums.length < 4) {
            return new ArrayList<List<Integer>>();
        }

        Arrays.sort(nums);

        Set<List<Integer>> set = new HashSet<List<Integer>>();

        // 和3Sum一樣,只是多了一個循環
        for (int a = 0; a < nums.length - 3; a++) {

            int target_3Sum = target - nums[a];

            for (int b = a + 1; b < nums.length - 2; b++) {

                int c = b + 1, d = nums.length - 1;

                while (c < d) {

                    int sum = nums[b] + nums[c] + nums[d];

                    if (sum == target_3Sum) {

                        // 將結果加入集合
                        List<Integer> tmp = new ArrayList<Integer>();
                        tmp.add(nums[a]);
                        tmp.add(nums[b]);
                        tmp.add(nums[c]);
                        tmp.add(nums[d]);
                        set.add(tmp);

                        // 去重
                        while (++c < d && nums[c - 1] == nums[c])
                            ;
                        while (--d > c && nums[d + 1] == nums[d])
                            ;
                    }

                    else if (sum < target_3Sum) {
                        c++;
                    } else {
                        d--;
                    }
                }
            }
        }

        return new ArrayList<List<Integer>>(set);
    }

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 (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.


參考:LeetCode 121 Best Time to Buy and Sell Stock

  • lowest:當前prices最小值
  • maxProfit:當前profit最大值
prices 7 2 3 6 1 9
lowest 7 2 2 2 1 1
maxProfit 0 0 1 4 4 8
    public int maxProfit(int[] prices) {

        if (prices.length <= 1) {
            return 0;
        }

        int maxProfit = 0;
        int lowest = Integer.MAX_VALUE;

        for (int v : prices) {
            lowest = Math.min(v, lowest);
            maxProfit = Math.max(maxProfit, v - lowest);
        }

        return maxProfit;
    }

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 (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).


參考:LeetCode 122 Best Time to Buy and Sell Stock II

只要有利潤就賣,就是最優解。

prices 7 2 3 6 1 9
profit 0 0 1 4 4 12
    public int maxProfit(int[] prices) {

        int profit = 0;

        for (int i = 1; i < prices.length; i++) {

            if (prices[i - 1] < prices[i]) {
                profit += prices[i] - prices[i - 1];
            }
        }

        return profit;
    }

Combination Sum

Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

The same repeated number may be chosen from C unlimited number of times.

Note:

  • All numbers (including target) will be positive integers.
  • Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1a2 ≤ … ≤ ak).
  • The solution set must not contain duplicate combinations.

For example, given candidate set 2,3,6,7 and target 7,
A solution set is:
[7]
[2, 2, 3]


參考:LeetCode 039 Combination Sum

使用遞歸,注意保存結果時,應該新建一個ArrayList:result.add(new ArrayList< Integer>(cur))。否則result會指向一直變化的cur。

    public List<List<Integer>> combinationSum(int[] candidates, int target) {

        if (candidates == null || candidates.length == 0) {
            return new ArrayList<List<Integer>>();
        }

        List<List<Integer>> result = new ArrayList<List<Integer>>();
        ArrayList<Integer> cur = new ArrayList<Integer>();

        Arrays.sort(candidates);
        dfs(0, target, result, cur, candidates);

        return result;
    }

    private void dfs(int start, int target, List<List<Integer>> result,
            ArrayList<Integer> cur, int[] candidates) {

        if (target == 0) {
            result.add(new ArrayList<Integer>(cur));
            return;
        }

        for (int i = start; i < candidates.length; i++) {

            // candidates[i] > target,則遞歸結束,後面不可能是解
            if (candidates[i] > target) {
                return;
            }

            cur.add(candidates[i]);
            dfs(i, target - candidates[i], result, cur, candidates);
            cur.remove(cur.size() - 1);
        }
    }

Combination Sum II

Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

Each number in C may only be used once in the combination.

Note:

  • All numbers (including target) will be positive integers.
  • Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1a2 ≤ … ≤ ak).
  • The solution set must not contain duplicate combinations.

For example, given candidate set 10,1,2,7,6,1,5 and target 8,
A solution set is:
[1, 7]
[1, 2, 5]
[2, 6]
[1, 1, 6]


參考:LeetCode 040 Combination Sum II

  1. Combination Sum每個元素可以使用多次,所以遞歸是dfs(i, target - candidates[i], result, cur, candidates);
  2. Combination Sum II每個元素只能使用一次,所以遞歸是dfs(i + 1, target - candidates[i], rt, cur, candidates);因爲解可能重複,所以使用set,最後轉成list。

    public List<List<Integer>> combinationSum2(int[] candidates, int target) {

        if (candidates == null || candidates.length == 0) {
            return new ArrayList<List<Integer>>();
        }

        Set<List<Integer>> rt = new HashSet<List<Integer>>();
        ArrayList<Integer> cur = new ArrayList<Integer>();

        Arrays.sort(candidates);
        dfs(0, target, rt, cur, candidates);

        return new ArrayList<List<Integer>>(rt);
    }

    private void dfs(int start, int target, Set<List<Integer>> rt,
            ArrayList<Integer> cur, int[] candidates) {

        if (target == 0) {
            rt.add(new ArrayList<Integer>(cur));
            return;
        }

        for (int i = start; i < candidates.length; i++) {

            // candidates[i] > target,則遞歸結束,後面不可能是解
            if (candidates[i] > target) {
                return;
            }

            cur.add(candidates[i]);
            dfs(i + 1, target - candidates[i], rt, cur, candidates);
            cur.remove(cur.size() - 1);
        }
    }

Combination Sum III

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.

Ensure that numbers within the set are sorted in ascending order.

Example 1:

Input: k = 3, n = 7

Output:

[[1,2,4]]

Example 2:

Input: k = 3, n = 9

Output:

[[1,2,6], [1,3,5], [2,3,4]]

Credits:
Special thanks to @mithmatt for adding this problem and creating all test cases.


參考:LeetCode 216 Combination Sum III

這次是指定了元素的個數,用一個變量記錄即可。

    public List<List<Integer>> combinationSum3(int k, int n) {

        List<List<Integer>> rt = new ArrayList<List<Integer>>();

        if (k < 1 || n < 1) {
            return rt;
        }

        List<Integer> cur = new ArrayList<Integer>();
        dfs(rt, cur, 0, k, n, 1);
        return rt;
    }

    private void dfs(List<List<Integer>> rt, List<Integer> cur, int sum, int k,
            int n, int level) {

        if (sum == n && k == 0) {
            rt.add(new ArrayList<Integer>(cur));
            return;
        } else if (sum > n || k <= 0) {
            return;
        }

        for (int i = level; i <= 9; i++) {
            cur.add(i);
            dfs(rt, cur, sum + i, k - 1, n, i + 1);
            cur.remove(cur.size() - 1);
        }
    }

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.


參考:LeetCode 105 Construct Binary Tree from Preorder and Inorder Traversal

題目要求:根據前序遍歷和中序遍歷序列,構建二叉樹。

  • 前序遍歷p:1 2 4 3 5 6
  • 中序遍歷i:4 2 1 5 3 6

    1
    

    / \
    2 3
    / / \
    4 5 6

前序遍歷p[0]是二叉樹的根結點,1是i[2],則:

  • p[1…2]是1的左子樹的前序遍歷,i[0…1]是1的左子樹的中序遍歷
  • p[3…5]是1的右子樹的前序遍歷,i[3…5]是1的右子樹的中序遍歷
  • 遞歸


    int p = 0;
    int[] preorder;
    int[] inorder;

    public TreeNode buildTree(int[] preorder, int[] inorder) {

        this.preorder = preorder;
        this.inorder = inorder;

        return buildTree(0, preorder.length);
    }

    TreeNode buildTree(int start, int end) {

        if (start >= end) {
            return null;
        }

        TreeNode root = new TreeNode(preorder[p]);

        int i;
        for (i = start; i < end && preorder[p] != inorder[i]; i++)
            ;

        p++;
        root.left = buildTree(start, i);
        root.right = buildTree(i + 1, end);

        return root;
    }

Construct Binary Tree from Inorder and Postorder Traversal

Given inorder and postorder traversal of a tree, construct the binary tree.

Note:
You may assume that duplicates do not exist in the tree.


參考:LeetCode 106 Construct Binary Tree from Inorder and Postorder Traversal

    int p;
    int[] postorder;
    int[] inorder;

    public TreeNode buildTree(int[] inorder, int[] postorder) {

        this.p = postorder.length - 1;
        this.inorder = inorder;
        this.postorder = postorder;

        return buildTree(0, postorder.length);
    }

    TreeNode buildTree(int start, int end) {

        if (start >= end) {
            return null;
        }

        TreeNode root = new TreeNode(postorder[p]);

        int i;
        for (i = start; i < end && postorder[p] != inorder[i]; i++)
            ;

        p--;
        root.right = buildTree(i + 1, end);
        root.left = buildTree(start, i);

        return root;
    }

Contains Duplicate

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.


參考:LeetCode 217 Contains Duplicate

    public boolean containsDuplicate(int[] nums) {

        Set<Integer> s = new HashSet<Integer>();

        for (int n : nums) {
            if (s.contains(n)) {
                return true;
            }
            s.add(n);
        }

        return false;
    }

Contains Duplicate II

Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the difference between i and j is at most k.


參考:LeetCode 219 Contains Duplicate II

建立一個map,key是出現過的元素,value是該元素的下標。若相同元素距離大於k,則更新下標。

    public boolean containsNearbyDuplicate(int[] nums, int k) {

        Map<Integer, Integer> map = new HashMap<Integer, Integer>();

        for (int i = 0; i < nums.length; i++) {
            if (map.containsKey(nums[i])) {
                if (i - map.get(nums[i]) <= k) {
                    return true;
                }
            }
            map.put(nums[i], i);
        }

        return false;
    }

Contains Duplicate III

Given an array of integers, find out whether there are two distinct indices i and j in the array such that the difference between nums[i] and nums[j] is at most t and the difference between i and j is at most k.


參考:LeetCode 220 Contains Duplicate III

對於加入的元素,要能夠在O(1)時間內查找,同時還要自動排序,維持一個k個元素的TreeSet。

    public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {

        if (k < 1 || t < 0 || nums == null || nums.length < 2) {
            return false;
        }

        SortedSet<Long> set = new TreeSet<Long>();

        for (int j = 0; j < nums.length; j++) {

            SortedSet<Long> subSet = set.subSet((long) nums[j] - t,
                    (long) nums[j] + t + 1);

            // 集合不爲空,則表示找到解
            if (!subSet.isEmpty()) {
                return true;
            }

            if (j >= k) {
                set.remove((long) nums[j - k]);
            }

            set.add((long) nums[j]);
        }

        return false;
    }

Find Minimum in Rotated Sorted Array

Suppose a sorted array 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.


參考:LeetCode 153 Find Minimum in Rotated Sorted Array

數列基本有序,則使用二分查找。假設數列是n,s是起始下標,e是最後下標,m是中間元素下標。分爲三種情況:

  1. n[s] < n[e]
  2. n[m] > n[s] > n[e]
  3. n[m] < n[e] < n[s]

情況1:n[s] < n[e]

0 1 2 4 5 6 7

這種情況,直接返回n[s]。因爲數列是有序的,或者只是旋轉過一次。如果n[s] < n[e],則表明沒有旋轉。最小元素是n[s]。

情況2:n[m] > n[s] > n[e]

4 5 6 7 0 1 2

只需要滿足n[m] > n[s]即可,因爲第一種情況排除後,n[s]就一定會 > n[e]。

在本例中:

n[s] = 4
n[m] = 7
n[e] = 2

則最小值肯定在7之後,到2之間,即 [m+1, e]。

情況3:n[m] < n[e] < n[s]

6 7 0 1 2 4 5

n[m] < n[e],在本例中:

n[s] = 6
n[m] = 1
n[e] = 5

則表明,從m到e,數組已經是上升的,所以最小值在[s, m]。

    public int findMin(int[] nums) {

        if (nums.length == 1) {
            return nums[0];
        }

        if (nums.length == 2) {
            return Math.min(nums[0], nums[1]);
        }

        int s = 0, e = nums.length - 1;

        int m = (s + e) / 2;

        if (nums[s] < nums[e]) {
            return nums[s];
        }

        if (nums[m] > nums[s]) {
            return findMin(Arrays.copyOfRange(nums, m + 1, e + 1));
        }

        return findMin(Arrays.copyOfRange(nums, s, m + 1));

    }

Find Peak Element

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.

You may imagine that num[-1] = num[n] = -∞.

For example, in array [1, 2, 3, 1], 3 is a peak element and your function should return the index number 2.

Note:

Your solution should be in logarithmic complexity.

Credits:
Special thanks to @ts for adding this problem and creating all test cases.


參考:LeetCode 162 Find Peak Element

    public int findPeakElement(int[] nums) {

        int low = 0;
        int high = nums.length - 1;

        while (low < high) {
            int mid = low + (high - low) / 2;
            if (nums[mid] > nums[mid + 1]) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        return low;
    }

Game of Life

According to the Wikipedia’s article: “The Game of Life, also known simply as Life, is a cellular automaton devised by the British mathematician John Horton Conway in 1970.”

Given a board with m by n cells, each cell has an initial state live (1) or dead (0). Each cell interacts with its eight neighbors (horizontal, vertical, diagonal) using the following four rules (taken from the above Wikipedia article):

  1. Any live cell with fewer than two live neighbors dies, as if caused by under-population.
  2. Any live cell with two or three live neighbors lives on to the next generation.
  3. Any live cell with more than three live neighbors dies, as if by over-population..
  4. Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.

Write a function to compute the next state (after one update) of the board given its current state.

Follow up:

  1. Could you solve it in-place? Remember that the board needs to be updated at the same time: You cannot update some cells first and then use their updated values to update other cells.
  2. In this question, we represent the board using a 2D array. In principle, the board is infinite, which would cause problems when the active area encroaches the border of the array. How would you address these problems?

Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.


參考:LeetCode 289 Game of Life

題目中說最好是in-place,因爲board是int型的,所以要區分四種狀態(dead是0,live是1):

dead->live    01
dead->dead    00
live->dead    10
live->live    11

或者直接用0,1,2,3四個數字表示四種狀態都可以,然後通過移位進行結果的更新。

下面的圖片,是一個Game of Life變化圖。

這裏寫圖片描述

    public void gameOfLife(int[][] board) {

        if (board == null || board.length == 0 || board[0] == null
                || board[0].length == 0)
            return;

        int m = board.length;
        int n = board[0].length;

        // 判斷每個點,下一時刻的狀態
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                int x = getLiveNum(board, i, j);
                if (board[i][j] == 0) {
                    if (x == 3)
                        board[i][j] += 10;
                } else {
                    if (x == 2 || x == 3)
                        board[i][j] += 10;
                }
            }
        }

        // 更新每個點的狀態
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                board[i][j] /= 10;
            }
        }
    }

    // 獲取board[x][y]鄰居live的數量
    private int getLiveNum(int[][] board, int x, int y) {
        int c = 0;
        for (int i = x - 1; i <= x + 1; i++) {
            for (int j = y - 1; j <= y + 1; j++) {
                if (i < 0 || j < 0 || i > board.length - 1
                        || j > board[0].length - 1 || (i == x && j == y))
                    continue;
                if (board[i][j] % 10 == 1)
                    c++;
            }
        }
        return c;
    }

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.

For example:

A = [2,3,1,1,4], return true.

A = [3,2,1,0,4], return false.


參考:LeetCode 055 Jump Game

設變量maxStep爲當前能夠跳躍的最大步數,超過數組長度,就表示能夠跳出;否則不能跳出。

那麼maxStep怎麼求得呢?nums[i] + i 就代表:從當前位置起跳,所能跳躍的最遠位置

maxStep=max{nums[i]+i maxStep
    public boolean canJump(int[] nums) {

        if (nums == null || nums.length == 0) {
            return false;
        }

        int maxStep = 0;

        for (int i = 0; i < nums.length; i++) {

            if (maxStep >= nums.length - 1) {
                return true;
            }

            if (nums[i] == 0 && maxStep == i) {
                return false;
            }

            maxStep = Math.max(maxStep, nums[i] + i);
        }

        return true;
    }

Majority Element

Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.

You may assume that the array is non-empty and the majority element always exist in the array.

Credits:
Special thanks to @ts for adding this problem and creating all test cases.


參考:LeetCode 169 Majority Element

A Linear Time Majority Vote Algorithm 一個典型的算法,可以在一次遍歷,時間複雜度是O(1),空間複雜度是O(1)的情況下完成。

    public int majorityElement(int[] nums) {

        int m = nums[0];
        int c = 1;

        for (int i = 1; i < nums.length; i++) {
            if (m == nums[i]) {
                c++;
            } else if (c > 1) {
                c--;
            } else {
                m = nums[i];
            }
        }

        return m;
    }

Majority Element II

Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The algorithm should run in linear time and in O(1) space.

Hint:

  1. How many majority elements could it possibly have?
  2. Do you have a better hint? Suggest it!

參考:LeetCode 229 Majority Element II

因爲題目中說是大於⌊ n/3 ⌋次數的元素,這樣的元素最多隻能有2個。

    public List<Integer> majorityElement(int[] nums) {

        List<Integer> rt = new ArrayList<Integer>();

        if (nums == null || nums.length == 0) {
            return rt;
        }

        int m1 = nums[0];
        int m2 = 0;

        int c1 = 1;
        int c2 = 0;

        for (int i = 1; i < nums.length; i++) {
            int x = nums[i];
            if (x == m1) {
                c1++;
            } else if (x == m2) {
                c2++;
            } else if (c1 == 0) {
                m1 = x;
                c1 = 1;
            } else if (c2 == 0) {
                m2 = x;
                c2 = 1;
            } else {
                c1--;
                c2--;
            }
        }

        c1 = 0;
        c2 = 0;

        for (int i = 0; i < nums.length; i++) {
            if (m1 == nums[i]) {
                c1++;
            } else if (m2 == nums[i]) {
                c2++;
            }
        }

        if (c1 > nums.length / 3) {
            rt.add(m1);
        }

        if (c2 > nums.length / 3) {
            rt.add(m2);
        }

        return rt;
    }

Maximum Subarray

Find the contiguous subarray within an array (containing at least one number) which has the largest sum.

For example, given the array [−2,1,−3,4,−1,2,1,−5,4],
the contiguous subarray [4,−1,2,1] has the largest sum = 6.

More practice:

If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.


參考:LeetCode 053 Maximum Subarray

curSum存儲數組當前的和,maxSum存儲數組中連續最大的和。

假設數組是[−2,1,−3,4,−1,2,1,−5,4],首先curSum = -2, maxSum = -2。

  1. 當i=1時,對於數組[-2,1],curSum + nums[1] = -1, 小於nums[1] = 1。所以以後-2就可以捨棄,計算curSum時就從i=1開始。
  2. 當i=2時,對於數組[-2,1,-3],curSum + nums[2] = -2, 大於nums[2] = -3。雖然沒有比原來大,但是至少比nums[2]大,對於以後計算更接近最優解。
  3. 以此類推。

本題只是返回連續最大和,並沒有返回數組,所以沒有必要記錄下標。curSum和maxSum 的計算公式如下:

curSum={curSum+nums[i] nums[i]

maxSum={maxSum curSum
    public int maxSubArray(int[] nums) {

        if (nums == null || nums.length == 0) {
            return 0;
        }

        int curSum = nums[0];
        int maxSum = nums[0];

        for (int i = 1; i < nums.length; i++) {
            curSum = Math.max(curSum + nums[i], nums[i]);
            maxSum = Math.max(curSum, maxSum);
        }

        return maxSum;
    }

Maximum Product Subarray

Find the contiguous subarray within an array (containing at least one number) which has the largest product.

For example, given the array [2,3,-2,4],
the contiguous subarray [2,3] has the largest product = 6.


參考:LeetCode 152 Maximum Product Subarray

LeetCode第53題Maximum Subarray是求連續和最大的子數組,本題是求連續乘積最大的子數組。

在解法上是一樣的,只是在求和時,是負就捨棄。但是在乘積中,因爲負數*負數=正數,所以連續乘積爲負數時,並不能捨棄這個數,因爲如果數組的元素是負數,它可能成爲乘積最大的數。

所以LeetCode第53題Maximum Subarray,只需要定義一個變量,用來記錄和;本題要定義兩個變量:positive和negative,分別記錄當前乘積最大值和最小值。

max=Math.max(max,positive)
    public int maxProduct(int[] nums) {

        int max = nums[0];
        int positive = nums[0];
        int negative = nums[0];

        for (int i = 1; i < nums.length; i++) {

            positive *= nums[i];
            negative *= nums[i];

            if (positive < negative) {
                int t = positive;
                positive = negative;
                negative = t;
            }

            positive = Math.max(positive, nums[i]);
            negative = Math.min(negative, nums[i]);

            max = Math.max(max, positive);
        }

        return max;
    }

Merge Sorted Array

Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.

Note:
You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2. The number of elements initialized in nums1 and nums2 are m and n respectively.


參考:LeetCode 088 Merge Sorted Array

    public int help(int[] nums, int k) {

        if (k < 0) {
            return Integer.MIN_VALUE;
        }

        return nums[k];
    }

    public void merge(int[] nums1, int m, int[] nums2, int n) {

        if (nums1 == null || nums2 == null) {
            return;
        }

        int t = m + n - 1;

        while (t >= 0) {

            int n1 = help(nums1, m - 1);
            int n2 = help(nums2, n - 1);

            if (n1 > n2) {
                nums1[t] = n1;
                m--;
            } else {
                nums1[t] = n2;
                n--;
            }

            t--;
        }
    }

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.


參考:LeetCode 064 Minimum Path Sum

建立一個揹包dp[m][n],其中dp[i][j]表示從grid[0][0]到grid[i][j]的最小和。

dp[x][y]=min(dp[x1][y],dp[x][y1])+grid[x][y]
    public int minPathSum(int[][] grid) {

        if (grid == null || grid[0] == null) {
            return 0;
        }

        int m = grid.length;
        int n = grid[0].length;

        int[][] dp = new int[m][n];
        dp[0][0] = grid[0][0];

        for (int y = 1; y < n; y++) {
            dp[0][y] = dp[0][y - 1] + grid[0][y];
        }

        for (int x = 1; x < m; x++) {
            dp[x][0] = dp[x - 1][0] + grid[x][0];
        }

        for (int y = 1; y < n; y++) {
            for (int x = 1; x < m; x++) {
                int min = Math.min(dp[x - 1][y], dp[x][y - 1]);
                dp[x][y] = min + grid[x][y];
            }
        }

        return dp[m - 1][n - 1];
    }

Minimum Size Subarray Sum

Given an array of n positive integers and a positive integer s, find the minimal length of a subarray of which the sum ≥ s. If there isn’t one, return 0 instead.

For example, given the array [2,3,1,2,4,3] and s = 7,
the subarray [4,3] has the minimal length under the problem constraint.

More practice:

If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n).

Credits:
Special thanks to @Freezen for adding this problem and creating all test cases.


參考:LeetCode 209 Minimum Size Subarray Sum

定義兩個指針,st和ed。如果sum>=s,sum從前面元素開始減;如果sum< s,ed++。

    public int minSubArrayLen(int s, int[] nums) {

        int sum = 0;
        int st = 0;
        int min = Integer.MAX_VALUE;

        for (int i = 0; i < nums.length; i++) {

            sum += nums[i];

            if (sum >= s) {
                while (sum - nums[st] >= s) {
                    sum -= nums[st++];
                }
                min = Math.min(min, i - st + 1);
            }
        }

        if (min > nums.length) {
            return 0;
        }

        return min;
    }

Missing Number

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

For example,
Given nums = [0, 1, 3] return 2.

Note:
Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity?

Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.


參考:LeetCode 268 Missing Number

既然是0~n只差其中一個數,不如再次加入0~n的序列,這樣就和LeetCode 136 Single Number一樣了,missing number只出現一次,其餘都是出現兩次。

    public int missingNumber(int[] nums) {

        int rt = nums.length;

        for (int i = 0; i < nums.length; i++) {
            rt = rt ^ nums[i] ^ i;
        }

        return rt;
    }

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.

For example, given nums = [0, 1, 0, 3, 12], after calling your function, nums should be [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.

Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.


參考:LeetCode 283 Move Zeroes

    public void moveZeroes(int[] nums) {

        int t = 0;

        // 把非0元素移到前面
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] != 0) {
                nums[t++] = nums[i];
            }
        }

        // 把後面元素值0
        for (int i = t; i < nums.length; i++) {
            nums[i] = 0;
        }
    }

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, do not allocate 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,31,3,2
3,2,11,2,3
1,1,51,5,1


參考:LeetCode 031 Next Permutation

    public void nextPermutation(int[] nums) {

        if (nums == null || nums.length < 2) {
            return;
        }

        int p = 0;
        for (int i = nums.length - 2; i >= 0; i--) {
            if (nums[i] < nums[i + 1]) {
                p = i;
                break;
            }
        }

        int q = 0;
        for (int i = nums.length - 1; i > p; i--) {
            if (nums[i] > nums[p]) {
                q = i;
                break;
            }
        }

        if (p == 0 && q == 0) {
            reverse(nums, 0, nums.length - 1);
            return;
        }

        int temp = nums[p];
        nums[p] = nums[q];
        nums[q] = temp;

        if (p < nums.length - 1) {
            reverse(nums, p + 1, nums.length - 1);
        }

    }

    private void reverse(int[] nums, int left, int right) {

        while (left < right) {
            int temp = nums[left];
            nums[left] = nums[right];
            nums[right] = temp;
            left++;
            right--;
        }
    }

Pascal’s Triangle

Given numRows, generate the first numRows of Pascal’s triangle.

For example, given numRows = 5,
Return

[
     [1],
    [1,1],
   [1,2,1],
  [1,3,3,1],
 [1,4,6,4,1]
]

參考:LeetCode 118 Pascal’s Triangle

    public List<List<Integer>> generate(int numRows) {

        ArrayList<List<Integer>> rt = new ArrayList<List<Integer>>();

        Integer[] pre = null;

        for (int i = 1; i <= numRows; i++) {

            //must be defined as Integer[]
            Integer[] row = new Integer[i];

            row[0] = 1;
            row[i - 1] = 1;

            for (int j = 1; j < i - 1; j++) {
                row[j] = pre[j] + pre[j - 1];
            }

            rt.add(new ArrayList<Integer>(Arrays.asList(row)));
            pre = row;
        }

        return rt;
    }

Pascal’s Triangle II

Given an index k, return the kth row of the Pascal’s triangle.

For example, given k = 3,
Return [1,3,3,1].

Note:
Could you optimize your algorithm to use only O(k) extra space?


參考:LeetCode 119 Pascal’s Triangle II

    public List<Integer> getRow(int rowIndex) {

        Integer[] row = new Integer[rowIndex + 1];
        Arrays.fill(row, 1);

        for (int i = 0; i < rowIndex - 1; i++) {
            for (int j = i + 1; j >= 1; j--) {
                row[j] = row[j] + row[j - 1];
            }
        }

        return Arrays.asList(row);
    }

Plus One

Given a non-negative number represented as an array of digits, plus one to the number.

The digits are stored such that the most significant digit is at the head of the list.


參考:LeetCode 066 Plus One

    public int[] plusOne(int[] digits) {

        if (digits == null || digits.length == 0) {
            return null;
        }

        int[] rt = new int[digits.length + 1];
        digits[digits.length - 1]++;

        for (int i = digits.length - 1; i >= 0; i--) {
            rt[i + 1] += digits[i];
            rt[i] += rt[i + 1] / 10;
            rt[i + 1] %= 10;
        }

        if (rt[0] == 0) {
            return Arrays.copyOfRange(rt, 1, rt.length);
        } else {
            return rt;
        }
    }

Product of Array Except Self

Given an array of n integers where n > 1, nums, return an array output such that output[i] is equal to the product of all the elements of nums except nums[i].

Solve it without division and in O(n).

For example, given [1,2,3,4], return [24,12,8,6].

Follow up:
Could you solve it with constant space complexity? (Note: The output array does not count as extra space for the purpose of space complexity analysis.)


參考:LeetCode 238 Product of Array Except Self

可以定義兩個輔助數組,left和right。

left[i]:存放nums[i]之前的乘積
right[i]:存放nums[i]之後的乘積

但是分析一下,空間可以優化,因爲我們先從右向左算,再從左向右算,只需要返回的那一個數組就夠了。

    public int[] productExceptSelf(int[] nums) {

        int[] rt = new int[nums.length];
        rt[nums.length - 1] = 1;

        for (int i = nums.length - 2; i >= 0; i--) {
            rt[i] = rt[i + 1] * nums[i+1];
        }

        int left = 1;
        for (int i = 0; i < nums.length; i++) {
            rt[i] *= left;
            left *= nums[i];
        }

        return rt;
    }

Remove Duplicates from Sorted Array

Given a sorted array, 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 in place with constant memory.

For example,
Given input array 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 new length.


參考:LeetCode 026 Remove Duplicates from Sorted Array

    public int removeDuplicates(int[] nums) {

        if (nums == null) {
            return -1;
        }

        if (nums.length < 2) {
            return nums.length;
        }

        int len = 0;

        for (int i = 1; i < nums.length; i++) {
            if (nums[len] != nums[i]) {
                nums[++len] = nums[i];
            }
        }

        return len + 1;
    }

Remove Duplicates from Sorted Array II

Follow up for “Remove Duplicates”:
What if duplicates are allowed at most twice?

For example,
Given sorted array nums = [1,1,1,2,2,3],

Your function should return length = 5, with the first five elements of nums being 1, 1, 2, 2 and 3. It doesn’t matter what you leave beyond the new length.


參考:LeetCode 080 Remove Duplicates from Sorted Array II

    public int removeDuplicates(int[] nums) {

        int cur = 2;
        for (int i = cur; i < nums.length; i++) {
            // 一個數字,最多出現2次
            if (!(nums[i] == nums[cur - 1] && nums[i] == nums[cur - 2])) {
                nums[cur++] = nums[i];
            }
        }

        return Math.min(cur, nums.length);
    }

Remove Element

Given an array and a value, remove all instances of that value in place and return the new length.

The order of elements can be changed. It doesn’t matter what you leave beyond the new length.


參考:LeetCode 027 Remove Element

    public int removeElement(int[] nums, int val) {

        if (nums == null || nums.length == 0) {
            return 0;
        }

        int len = 0;

        for (int i = 0; i < nums.length; i++) {
            if (nums[i] != val) {
                nums[len++] = nums[i];
            }
        }

        return len;
    }

Rotate Array

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].

Note:
Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.

[show hint]

Hint:
Could you do it in-place with O(1) extra space?

Related problem: Reverse Words in a String II

Credits:
Special thanks to @Freezen for adding this problem and creating all test cases.


參考:LeetCode 189 Rotate Array

    void reverse(int[] nums, int st, int ed) {

        while (st < ed) {
            int t = nums[st];
            nums[st] = nums[ed];
            nums[ed] = t;
            st++;
            ed--;
        }
    }

    public void rotate(int[] nums, int k) {

        int length = nums.length;

        k = k % length;

        if (length == 1 || k == 0)
            return;

        reverse(nums, 0, length - k - 1);
        reverse(nums, length - k, length - 1);
        reverse(nums, 0, length - 1);
    }

Rotate Image

You are given an n x n 2D matrix representing an image.

Rotate the image by 90 degrees (clockwise).

Follow up:
Could you do this in-place?


參考:LeetCode 048 Rotate Image

這裏寫圖片描述

    public void rotate(int[][] matrix) {

        if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
            return;
        }

        final int mx = matrix.length;
        final int my = matrix[0].length;
        int x, y;

        int t;

        int _my = my - 1;
        for (x = 0; x < mx - 1; x++) {
            for (y = 0; y < _my; y++) {
                int ny = mx - 1 - x;
                int nx = my - 1 - y;

                t = matrix[y][x];
                matrix[y][x] = matrix[ny][nx];
                matrix[ny][nx] = t;

            }
            _my--;
        }

        for (x = 0; x < mx; x++) {
            for (y = 0; y < my / 2; y++) {
                int ny = my - 1 - y;
                int nx = x;

                t = matrix[y][x];
                matrix[y][x] = matrix[ny][nx];
                matrix[ny][nx] = t;
            }
        }

    }

Search a 2D Matrix

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 from left to right.
  • The first integer of each row is greater than the last integer of the previous row.

For example,

Consider the following matrix:

[
  [1,   3,  5,  7],
  [10, 11, 16, 20],
  [23, 30, 34, 50]
]

Given target = 3, return true.


參考:LeetCode 074 Search a 2D Matrix

    public boolean searchMatrix(int[][] matrix, int target) {

        int mx = matrix.length;
        int my = matrix[0].length;

        int l = 0;
        int r = mx * my;

        while (l < r) {

            int m = l + (r - l) / 2;

            // 將m轉換成x、y
            int x = m / my;
            int y = m % my;

            // 二分查找:matrix[x][y]轉換成一維數組,座標就是m
            if (matrix[x][y] == target) {
                return true;
            } else if (matrix[x][y] < target) {
                l = m + 1;
            } else {
                r = m;
            }
        }

        return false;
    }

Search for a Range

Given a sorted array of integers, find the starting and ending position of a given target value.

Your algorithm’s runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

For example,
Given [5, 7, 7, 8, 8, 10] and target value 8,
return [3, 4].


參考:LeetCode 034 Search for a Range

    public int[] searchRange(int[] nums, int target) {

        int l = 0, r = nums.length;

        while (l < r) {

            int m = l + (r - l) / 2;

            if (nums[m] == target) {

                int s = m, e = m;

                while (s - 1 >= 0 && nums[s - 1] == target) {
                    s--;
                }

                while (e + 1 < nums.length && nums[e + 1] == target) {
                    e++;
                }

                return new int[] { s, e };

            } else if (nums[m] > target) {
                r = m;
            } else {
                l = m + 1;
            }
        }

        return new int[] { -1, -1 };
    }

Search in Rotated Sorted Array

Suppose a sorted array 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.


參考:LeetCode 033 Search in Rotated Sorted Array

    public int search(int[] nums, int target) {

        int l = 0, r = nums.length - 1;

        while (l <= r) {

            int m = (l + r) / 2;

            if (nums[m] == target)
                return m;
            if (nums[l] < nums[m]) {
                if (target <= nums[m] && target >= nums[l])
                    r = m - 1;
                else
                    l = m + 1;
            } else if (nums[l] > nums[m]) {
                if (target >= nums[l] || target <= nums[m])
                    r = m - 1;
                else
                    l = m + 1;
            } else
                l++;
        }
        return -1;
    }

Search in Rotated Sorted Array II

Follow up for “Search in Rotated Sorted Array”:
What if duplicates are allowed?

Would this affect the run-time complexity? How and why?

Write a function to determine if a given target is in the array.


參考:LeetCode 081 Search in Rotated Sorted Array II

    public boolean search(int[] nums, int target) {

        int l = 0, r = nums.length - 1;

        while (l <= r) {

            int m = (l + r) / 2;

            if (nums[m] == target)
                return true;

            if (nums[l] < nums[m]) {
                if (target <= nums[m] && target >= nums[l])
                    r = m - 1;
                else
                    l = m + 1;
            } else if (nums[l] > nums[m]) {
                if (target >= nums[l] || target <= nums[m])
                    r = m - 1;
                else
                    l = m + 1;
            } else
                l++;
        }

        return false;
    }

Search Insert Position

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.

You may assume no duplicates in the array.

Here are few examples.
[1,3,5,6], 5 → 2
[1,3,5,6], 2 → 1
[1,3,5,6], 7 → 4
[1,3,5,6], 0 → 0


參考:LeetCode 035 Search Insert Position

    public int searchInsert(int[] nums, int target) {

        if (nums == null || nums.length == 0) {
            return 0;
        }

        for (int i = 0; i < nums.length; i++) {
            if (target <= nums[i]) {
                return i;
            }
        }

        return nums.length;
    }

Set Matrix Zeroes

Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place.

click to show follow up.

Follow up:

Did you use extra space?
A straight forward solution using O(m__n) space is probably a bad idea.
A simple improvement uses O(m + n) space, but still not the best solution.
Could you devise a constant space solution?


參考:LeetCode 073 Set Matrix Zeroes

    public void setZeroes(int[][] matrix) {

        if (matrix == null || matrix.length == 0) {
            return;
        }

        int mx = matrix.length;
        int my = matrix[0].length;

        // 兩個變量,判斷第一行和第一列是否有0
        boolean xflag = false, yflag = false;

        // 判斷第一行是否有0
        for (int i = 0; i < mx; i++) {
            if (matrix[i][0] == 0) {
                xflag = true;
                break;
            }
        }

        // 判斷第一列是否有0
        for (int i = 0; i < my; i++) {
            if (matrix[0][i] == 0) {
                yflag = true;
                break;
            }
        }

        // 其它行、列是否有0
        for (int i = 1; i < mx; i++) {
            for (int j = 1; j < my; j++) {
                if (matrix[i][j] == 0) {
                    matrix[i][0] = 0;
                    matrix[0][j] = 0;
                }
            }
        }

        // 對於第一列,爲0,則將所在行變成0
        for (int i = 1; i < mx; i++) {
            if (matrix[i][0] == 0) {
                for (int j = 0; j < my; j++) {
                    matrix[i][j] = 0;
                }
            }
        }

        // 對於第一行,爲0,則將所在列變成0
        for (int i = 0; i < my; i++) {
            if (matrix[0][i] == 0) {
                for (int j = 0; j < mx; j++) {
                    matrix[j][i] = 0;
                }
            }
        }

        // 若原來第一行中有0,則將整行置0
        if (xflag) {
            for (int i = 0; i < mx; i++) {
                matrix[i][0] = 0;
            }
        }

        // 若原來第一列中有0,則將整列置0
        if (yflag) {
            for (int i = 0; i < my; i++) {
                matrix[0][i] = 0;
            }
        }

    }

Sort Colors

Given an array with n objects colored red, white or blue, sort them 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.

click to show follow up.

Follow up:
A rather straight forward solution is a two-pass algorithm using counting sort.
First, iterate the array counting number of 0’s, 1’s, and 2’s, then overwrite array with total number of 0’s, then 1’s and followed by 2’s.

Could you come up with an one-pass algorithm using only constant space?


參考:LeetCode 075 Sort Colors

    public void sortColors(int[] nums) {

        if (nums == null || nums.length == 0) {
            return;
        }

        // 定義三個變量,存儲三種顏色出現次數
        int red = 0;
        int white = 0;
        int blue = 0;

        // 循環一次,記錄每種顏色出現次數
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == 0) {
                red++;
            } else if (nums[i] == 1) {
                white++;
            } else {
                blue++;
            }
        }

        // 對nums數組重新賦值
        int i = 0;
        while (red-- > 0) {
            nums[i++] = 0;
        }
        while (white-- > 0) {
            nums[i++] = 1;
        }
        while (blue-- > 0) {
            nums[i++] = 2;
        }
    }

Spiral Matrix

Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.

For example,
Given the following matrix:

[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]

You should return [1,2,3,6,9,8,7,4,5].


參考:LeetCode 054 Spiral Matrix

    public List<Integer> spiralOrder(int[][] matrix) {

        List<Integer> rt = new ArrayList<Integer>();

        if (matrix == null || matrix.length == 0) {
            return rt;
        }

        int startx = 0, endx = matrix.length - 1;
        int starty = 0, endy = matrix[0].length - 1;

        while (startx <= endx && starty <= endy) {

            // 上邊的行,從左向右
            for (int y = starty; y <= endy; y++) {
                rt.add(matrix[startx][y]);
            }

            // 右邊的列,從上到下
            for (int x = startx + 1; x <= endx; x++) {
                rt.add(matrix[x][endy]);
            }

            // 如果行或列遍歷完,則退出循環
            if (startx == endx || starty == endy) {
                break;
            }

            // 下邊的行,從右向左
            for (int y = endy - 1; y >= starty; y--) {
                rt.add(matrix[endx][y]);
            }

            // 左邊的列,從下到上
            for (int x = endx - 1; x >= startx + 1; x--) {
                rt.add(matrix[x][starty]);
            }

            startx++;
            starty++;
            endx--;
            endy--;
        }

        return rt;
    }

Spiral Matrix II

Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order.

For example,
Given n = 3,

You should return the following matrix:

[
 [ 1, 2, 3 ],
 [ 8, 9, 4 ],
 [ 7, 6, 5 ]
]

參考:LeetCode 059 Spiral Matrix II

    public int[][] generateMatrix(int n) {

        if (n <= 0) {
            return new int[0][0];
        }

        int[][] matrix = new int[n][n];

        int num = 1;

        int startx = 0, endx = n - 1;
        int starty = 0, endy = n - 1;

        while (startx <= endx && starty <= endy) {

            // 上邊的行,從左向右
            for (int y = starty; y <= endy; y++) {
                matrix[startx][y] = num++;
            }

            // 右邊的列,從上到下
            for (int x = startx + 1; x <= endx; x++) {
                matrix[x][endy] = num++;
            }

            // 如果行或列遍歷完,則退出循環
            if (startx == endx || starty == endy) {
                break;
            }

            // 下邊的行,從右向左
            for (int y = endy - 1; y >= starty; y--) {
                matrix[endx][y] = num++;
            }

            // 左邊的列,從下到上
            for (int x = endx - 1; x >= startx + 1; x--) {
                matrix[x][starty] = num++;
            }

            startx++;
            starty++;
            endx--;
            endy--;
        }

        return matrix;
    }

Subsets

Given a set of distinct integers, nums, return all possible subsets.

Note:

  • Elements in a subset must be in non-descending order.
  • The solution set must not contain duplicate subsets.

For example,
If nums = [1,2,3], a solution is:

[
  [3],
  [1],
  [2],
  [1,2,3],
  [1,3],
  [2,3],
  [1,2],
  []
]

參考:LeetCode 078 Subsets

    int target;// 次數
    Integer[] stack;// 存儲每次排列

    List<List<Integer>> rt;// 存儲結果

    public void search(int p, int[] nums) {

        // 若長度爲k,則stack是其中一個結果,保存結果
        if (p == target) {
            rt.add(new ArrayList<Integer>(Arrays.asList(stack)));
            return;
        }

        for (int i = 0; i < nums.length; i++) {

            if (p > 0 && nums[i] <= stack[p - 1]) {
                continue;
            }

            stack[p] = nums[i];
            search(p + 1, nums);
        }
    }

    public List<List<Integer>> subsets(int[] nums) {

        Arrays.sort(nums);

        rt = new ArrayList<List<Integer>>();

        // 分別做0~num.length長度的組合
        for (int i = 0; i <= nums.length; i++) {
            target = i;
            stack = new Integer[i];
            search(0, nums);
        }

        return rt;
    }

Subsets II

Given a collection of integers that might contain duplicates, nums, return all possible subsets.

Note:

  • Elements in a subset must be in non-descending order.
  • The solution set must not contain duplicate subsets.

For example,
If nums = [1,2,2], a solution is:

[
  [2],
  [1],
  [1,2,2],
  [2,2],
  [1,2],
  []
]

參考:LeetCode 090 Subsets II

使用二進制,不需要遞歸。對於二進制中的每一位,0表示不選擇,1表示選擇。則有2^n種情況。
使用HashSet,能夠直接過濾重複情況(先對數組排序,題目中也要求每個list非降序排列)。

    public List<List<Integer>> subsetsWithDup(int[] nums) {

        if (nums == null) {
            return null;
        }

        if (nums.length == 0) {
            return new ArrayList<List<Integer>>();
        }

        Set<List<Integer>> set = new HashSet<List<Integer>>();

        // 題目中要求每個list是非降序,所以要先從小到大排序
        Arrays.sort(nums);

        // 對於n位,有2^n種情況
        for (int i = 0; i < Math.pow(2, nums.length); i++) {

            List<Integer> list = new ArrayList<Integer>();
            int tmp = i;

            // 對於每種情況,分別求得二進制中1的個數
            // 0代表不選擇,1代表選擇
            for (int j = 0; j < nums.length; j++) {
                int bit = tmp & 1;
                tmp >>= 1;
                if (bit == 1) {
                    list.add(nums[j]);
                }
            }
            set.add(list);
        }

        return new ArrayList<List<Integer>>(set);
    }

Summary Ranges

Given a sorted integer array without duplicates, return the summary of its ranges.

For example, given [0,1,2,4,5,7], return ["0->2","4->5","7"].

Credits:
Special thanks to @jianchao.li.fighter for adding this problem and creating all test cases.


參考:LeetCode 228 Summary Ranges

    public List<String> summaryRanges(int[] nums) {

        List<String> rt = new ArrayList<String>();

        if (nums == null || nums.length == 0) {
            return rt;
        }

        for (int i = 0; i < nums.length; i++) {
            int st = nums[i];
            int ed = st;

            while (i + 1 < nums.length && nums[i + 1] - ed == 1) {
                i++;
                ed++;
            }

            if (ed == st) {
                rt.add(st + "");
            } else {
                rt.add(st + "->" + ed);
            }
        }

        return rt;
    }

Unique Paths

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?

Above is a 3 x 7 grid. How many possible unique paths are there?

Note: m and n will be at most 100.


參考:LeetCode 062 Unique Paths

構造二維數組dp[m][n],其中:

dp[i][j]=dp[i1][j]+dp[i][j1]
    public int uniquePaths(int m, int n) {

        if (m <= 0 || n <= 0) {
            return 0;
        }

        int[][] dp = new int[m][n];

        for (int y = 1; y < n; y++) {
            dp[0][y] = 1;
        }

        for (int x = 1; x < m; x++) {
            dp[x][0] = 1;
        }

        for (int y = 1; y < n; y++) {
            for (int x = 1; x < m; x++) {
                dp[x][y] = dp[x - 1][y] + dp[x][y - 1];
            }
        }

        return dp[m - 1][n - 1];
    }

Unique Paths II

Follow up for “Unique Paths”:

Now consider if some obstacles are added to the grids. How many unique paths would there be?

An obstacle and empty space is marked as 1 and 0 respectively in the grid.

For example,

There is one obstacle in the middle of a 3x3 grid as illustrated below.

[
  [0,0,0],
  [0,1,0],
  [0,0,0]
]

The total number of unique paths is 2.

Note: m and n will be at most 100.


參考:LeetCode 063 Unique Paths II

和上一題一樣,只是有障礙物的時候(obstacleGrid[i][j]==1),將對應的dp置0(dp[i][j]=0)

    public int uniquePathsWithObstacles(int[][] obstacleGrid) {

        if (obstacleGrid == null || obstacleGrid[0] == null) {
            return 0;
        }

        if (obstacleGrid[0][0] == 1) {
            return 0;
        }

        int m = obstacleGrid.length;
        int n = obstacleGrid[0].length;

        int[][] dp = new int[m][n];

        for (int y = 1; y < n; y++) {
            if (obstacleGrid[0][y] == 0) {
                dp[0][y] = 1;
            } else {
                break;
            }
        }

        for (int x = 1; x < m; x++) {
            if (obstacleGrid[x][0] == 0) {
                dp[x][0] = 1;
            } else {
                break;
            }
        }

        for (int y = 1; y < n; y++) {
            for (int x = 1; x < m; x++) {
                if (obstacleGrid[x][y] == 1) {
                    dp[x][y] = 0;
                } else {
                    dp[x][y] = dp[x - 1][y] + dp[x][y - 1];
                }

            }
        }

        return dp[m - 1][n - 1];
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章