LeetCode Top Interview Questions(0 - 50)

前言

每天刷一刷,5050發。

LeetCode Top Interview Questions(0 - 50)

1 Tow Sum

找出數組中和爲target的兩個數的下標。你可以確保有且僅有一個解。

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

Two Sum

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int res[] = new int[2];
        HashMap<Integer, Integer> map = new HashMap<>();
        for(int i = 0; i < nums.length; i ++) {
            //存入 (nums[i], 下標) 如果存在則說明匹配
            if(map.get(target - nums[i]) != null) {
                res[0] = map.get(target - nums[i]);
                res[1] = i;
                return res;
            }
            map.put(nums[i], i);
        }
        return res;
    }
}

2 Add Two Numbers

將獲得兩個表示兩個非負整數的非空鏈表。這些數字以相反的順序存儲,並且它們的每個節點都包含一個數字。將兩個數字相加,並將其作爲鏈表返回。您可能會假設兩個數字除了數字0本身以外都不包含任何前導零。

Example:

Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
Explanation: 342 + 465 = 807.

Add Two Numbers

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        if(l1 == null || l2 == null)return l1 == null ? l1 : l2;
        ListNode res = new ListNode(0);
        ListNode pre = res;;
        int flag = 0;
        int sum = 0;
        while(l1 != null || l2 != null) {
          	//可能有長短不一的鏈表
            if(l1 != null){sum += l1.val; l1 = l1.next;}
            if(l2 != null){sum += l2.val; l2 = l2.next;}
            sum += flag;
            res.next = new ListNode(sum % 10);
            flag = sum / 10;
            sum = 0;
            res = res.next;
        }
      	//如果進位標記爲一,則要多添加一個節點
        if(flag == 1)
            res.next = new ListNode(1);
        return pre.next;
    }
}

3 Longest Substring Without Repeating Characters

給定一個字符串,找到最長子字符串的長度而不重複字符。

Example 1:

Input: "abcabcbb"
Output: 3 
Explanation: The answer is "abc", with the length of 3. 

Example 2:

Input: "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.

Longest Substring Without Repeating Characters

class Solution {
    public int lengthOfLongestSubstring(String s) {
        // 使用滑動窗口
        int l = 0, r = -1;
        // 設置還未移動最大的間距
        int minIndex = 0;
        int[] freq = new int[256];
        for (int i = 0; i < freq.length; i++) {
            freq[i] = 0;
        }
        while (l <= s.length() - 1) {
            if (r + 1 < s.length() && freq[s.charAt(r + 1)] == 0) {
                freq[s.charAt(++r)]++;
            } else {
                freq[s.charAt(l++)]--;
            }
            if (minIndex < r - l + 1)
                minIndex = r - l + 1;
        }
        if (minIndex == s.length() + 1)
            return 0;
        return minIndex;
    }
}

4 Median of Two Sorted Arrays(Hard)

找到兩個排序數組的中位數

Example 1:

nums1 = [1, 3]
nums2 = [2]

The median is 2.0

Median of Two Sorted Arrays


5 Longest Palindromic Substring

求最長子迴文串

Example 1:

Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.

Longest Palindromic Substring

思路:中心迴文算法

class Solution {
    public String longestPalindrome(String s) {
        if (s.length() <= 1) return s;
        
        char[] ch = s.toCharArray();
        int[] max = new int[2];
        for (int i = 0; i < ch.length - 1; i++) {
            dp(ch, i, i, max);
            dp(ch, i, i+1, max);
        }
        
        return s.substring(max[0], max[0] + max[1]);
    }
    
    private void dp(char[] ch, int i, int j, int[] max) {
        while (i >= 0 && j < ch.length && ch[i] == ch[j]) {
            i--;
            j++;
        }
        if (j - i - 1 > max[1]) {
            max[0] = i + 1;
            max[1] = j - i - 1;
        }
    }
}

6 Reverse Integer

反轉數字 輸入範圍爲 [Integer.MIN_VALUE ~ Integer.MAX_VALUE ] ,如果反轉後益處,則返回0

Example 1:

Input: 123
Output: 321

Input: -123
Output: -321
class Solution {
    public int reverse(int x) {
        int rev = 0;
        while (x != 0) {
            int pop = x % 10;
            x /= 10;
            if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0;
            if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0;
          	//唯一可能溢出的地方,前面需要判斷是否溢出
            rev = rev * 10 + pop;
        }
        return rev;
    }
}

7 String to Integer (atoi)

實現一個字符串轉int,但是有許多限制

Example 1:

Input: "42"
Output: 42
  
Input: "   -42"
Output: -42
Explanation: The first non-whitespace character is '-', which is the minus sign.
             Then take as many numerical digits as possible, which gets 42.

Input: "4193 with words"
Output: 4193
Explanation: Conversion stops at digit '3' as the next character is not a numerical digit.

Input: "words and 987"
Output: 0
Explanation: The first non-whitespace character is 'w', which is not a numerical 
             digit or a +/- sign. Therefore no valid conversion could be performed.
 
Input: "-91283472332"
Output: -2147483648
Explanation: The number "-91283472332" is out of the range of a 32-bit signed integer.
             Thefore INT_MIN is returned.

String to Integer (atoi)

class Solution {
    public int myAtoi(String str) {
        str = str.trim();
        
        StringBuilder sb = new StringBuilder();
        
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            boolean isDigit = Character.isDigit(c);
            
            if (i == 0) {
                if (c != '+' && c != '-' && !isDigit) {
                    return 0;
                } else {             
                    sb.append(c);
                    continue;
                }
            } 
            
            if (isDigit) {
                sb.append(c);
            } else {
                break;
            }
        }
        
        String resultAsString = sb.toString();
        
        if (resultAsString.isEmpty()) {
            return 0;
        }
        
        char firstCharacter = resultAsString.charAt(0);
        
        if (resultAsString.length() == 1 && !Character.isDigit(firstCharacter)) {
            return 0;
        }
        
        try {
            return Integer.parseInt(resultAsString);    
        } catch (NumberFormatException e) {
            return firstCharacter == '-' ? Integer.MIN_VALUE : Integer.MAX_VALUE;
        }
    }
}

8 Regular Expression Matching(Hard)

正則表達式匹配

Regular Expression Matching


9 Container With Most Water

類似木桶原理,找到最大面積的兩個座標

思路:從數組兩端收縮,保證底是最大值,之後爲們收縮高度較低的板(因爲這樣才能確保面積可能擴大,因爲面積受最小板的限制)

Container With Most Water

public class Solution {
    public int maxArea(int[] height) {
        int maxarea = 0, l = 0, r = height.length - 1;
        while (l < r) {
            maxarea = Math.max(maxarea, Math.min(height[l], height[r]) * (r - l));
            if (height[l] < height[r])
                l++;
            else
                r--;
        }
        return maxarea;
    }
}

10 Roman to Integer

輸入一個字符串,按照下列的規則轉化成數字

Symbol       Value
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

Example:

Input: "LVIII"
Output: 58
Explanation: L = 50, V= 5, III = 3.

Roman to Integer

class Solution {
    public int romanToInt(String s) {
        if(s == null || "".equals(s)) return 0;
        int dic[] =new int[24];
        dic[8] = 1;
        dic[21] = 5;
        dic[23] = 10;
        dic[11] = 50;
        dic[2] = 100;
        dic[3] = 500;
        dic[12] = 1000;
        char[] chars = s.toCharArray();
        //如果只有一個字符 則返回相應的值
        if(chars.length == 1)return dic[chars[0] - 'A'];
        int sum = 0;
        for(int i = 0; i < chars.length; i ++) {
            //如果前一個小於後一個,則sum加上後一個減去前一個
            if(i + 1 < chars.length && dic[chars[i] - 'A'] < dic[chars[i + 1] - 'A']) {
                sum += dic[chars[i + 1] - 'A'] -  dic[chars[i] - 'A'];
                //向後多移動一個位置
                i ++;
            } else {
                sum += dic[chars[i] - 'A'];
            }
        }
        return sum;
    }
}

11 Longest Common Prefix

返回給定數組的最長子前綴,如果沒有則返回空串

Example 1:

Input: ["flower","flow","flight"]
Output: "fl"

Input: ["dog","racecar","car"]
Output: ""
Explanation: There is no common prefix among the input strings.

Longest Common Prefix

class Solution {
    public String longestCommonPrefix(String[] strs) {
        if(strs == null || strs.length == 0)return "";
        
        for(int i = 0; i < strs[0].length(); i ++) {
          	//使用第一個元素進行匹配
            for(int j = 1; j < strs.length; j ++) {
              	//如果後面長度不夠了,直接返回
                if(strs[j].length() == i ||
                   strs[j].charAt(i) != strs[0].charAt(i)) {
                    return strs[0].substring(0, i);
                }
            }
        }
      	//如果沒有執行第二層循環,代表只有一個元素
        return strs[0];
    }
}

12 3Sum

找到3個數相加等於0 返回值,且結果不重複

3Sum

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        //首先如果要去重複值可以使用排序,重複的數字跳過
        //已經排序後使用指針碰撞和第3個數匹配
        List<List<Integer>> res = new ArrayList<>();
        if(nums == null ||nums.length == 0)return res;
        Arrays.sort(nums);
        //遍歷到只剩3個數爲止
        for(int i = 0; i < nums.length - 2; i ++) {
            if(i > 0 && nums[i] == nums[i - 1])continue;
            
            //找到後面的兩個數字和爲nums[i]
            int l = i + 1, r = nums.length - 1;
            while(l < r) {
                if(nums[i] + nums[l] + nums[r] == 0) {
                    res.add(Arrays.asList(nums[i],nums[l],nums[r]));
                    while(l < r && nums[l] == nums[l + 1])l ++;
                    while(l < r && nums[r] == nums[r - 1])r --;
                    l ++;
                    r --;
                } else if(nums[i] + nums[l] + nums[r] > 0)r --;
                else l ++;
            }
            
        }
        return res;
    }
}

13 Letter Combinations of a Phone Number

給一個包含0 ~ 9的字符串,輸出所有手機鍵盤上有可能組成的字符串

Letter Combinations of a Phone Number

//標準回溯算法
class Solution {
    public List<String> letterCombinations(String digits) {
        String[] let = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
        
        List<String> res = new ArrayList<>();
        if(digits == null || "".equals(digits))return res;
        
        helper(res, new StringBuffer(""), 0, let, digits);
        return res;
    }
    
    private void helper(List<String> res, StringBuffer sb, int index, String[] let, String digits) {
        if(index > digits.length())return;
        if(sb.length() == digits.length()) {
            res.add(sb.toString());
            return;
        }
        
        char[] chars = let[digits.charAt(index) - '0'].toCharArray();
        for(int i = 0; i < chars.length; i ++) {
            sb.append(chars[i]);
            helper(res, sb, index + 1, let, digits);
            sb.deleteCharAt(sb.length() - 1);
        }
    }
}

14 Remove Nth Node From End of List

刪除鏈表的倒數第n個節點

Remove Nth Node From End of List

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        if(head == null || n == 0)return head;
        ListNode node = head;
        ListNode pre = new ListNode(0);
        pre.next = head;
        while(n -- > 0) {
            node = node.next;
        }
        
        while(node != null) {
            node = node.next;
            pre = pre.next;
        }
        if(pre.next == head)return pre.next.next;
        pre.next = pre.next.next;
        return head;
    }
}

15 Valid Parentheses

匹配由{},[],()組成的字符串是否符合格式

Example:

Input: "()"
Output: true

Input: "()[]{}"
Output: true

Input: "(]"
Output: false

Valid Parentheses

class Solution {
    public boolean isValid(String s) {
        if(s == null || s.length() == 1)return false;
        Stack<Character> stack = new Stack<>();
        for(int i = 0; i < s.length(); i ++) {
            char c = s.charAt(i);
            if(c == '(' || c == '{' || c == '[') {
                stack.push(c);
                continue;
            }
            else if(stack.isEmpty())return false;
            else if(c == ')' && stack.pop() != '(')return false;
            else if(c == ']' && stack.pop() != '[')return false;
            else if(c == '}' && stack.pop() != '{')return false;
        }
        return stack.isEmpty();
    }
}

16 Merge Two Sorted Lists

合併兩個排序鏈表

Example:

Input: 1->2->4, 1->3->4
Output: 1->1->2->3->4->4

Merge Two Sorted Lists

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1 == null || l2 == null)return l1 == null ? l2 : l1;
        
        ListNode root;
        if(l1 .val < l2.val) {
            root = l1;
            root.next = mergeTwoLists(l1.next, l2);
        } else {
            root = l2;
            root.next = mergeTwoLists(l1, l2.next);
        }
        return root;
    }
}

17 Generate Parentheses

給定n對括號,編寫一個函數以生成格式正確的括號的所有組合。

Example:

[
  "((()))",
  "(()())",
  "(())()",
  "()(())",
  "()()()"
]

Generate Parentheses

class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> res = new ArrayList<>();
        if(n == 0)return res;
        
        helper(res, "", 0, 0, n);
        return res;
    }
    
    private void helper(List<String> res, String s, int l, int r, int n) {
        if(s.length() == 2 * n) {
            res.add(s);
            return;
        }
        
        if(l < n)
            helper(res, s + "(", l + 1, r, n);
        if(l > r)
            helper(res, s + ")", l, r + 1, n);
    }
}

18 Merge k Sorted Lists

合併k個排序鏈表

Example:

Input:
[
  1->4->5,
  1->3->4,
  2->6
]
Output: 1->1->2->3->4->4->5->6

Merge k Sorted Lists

/**
 * Definition for singly-linked list.
 * public class ListNode {
 * int val;
 * ListNode next;
 * ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        return partition(lists, 0, lists.length - 1);
    }

    public ListNode partition(ListNode[] lists, int i, int j) {
        if (i == j) {
            return lists[i];
        }

        if (i < j) {
            int mid = (i + j) / 2;
            ListNode l1 = partition(lists, i, mid);
            ListNode l2 = partition(lists, mid + 1, j);
            return merge(l1, l2);
        } else {
            return null;
        }

    }

    public ListNode merge(ListNode l1, ListNode l2) {
        if (l1 == null) {
            return l2;
        }
        if (l2 == null) {
            return l1;
        }

        if (l1.val < l2.val) {
            l1.next = merge(l1.next, l2);
            return l1;
        } else {

            l2.next = merge(l2.next, l1);
            return l2;
        }
    }
}

19 Remove Duplicates from Sorted Array

給定一個已排序的數組nums,就地刪除重複項,以使每個元素僅出現一次並返回新的長度。

Example:

Given nums = [1,1,2],

Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively.

It doesn't matter what you leave beyond the returned length.

Remove Duplicates from Sorted Array

class Solution {
    public int removeDuplicates(int[] nums) {
        if(nums == null || nums.length == 0)return 0;
        int len = 0;
      	//因爲是排序的,所以把不重複的數字放到最前
        for(int i = 1; i < nums.length; i ++) {
            if(nums[len] != nums[i]) {
                nums[++ len] = nums[i];
            }
        }
        return len + 1;
    }
}

20 Implement strStr()

找到needle第一次出現的位置

Example:

Input: haystack = "hello", needle = "ll"
Output: 2

Implement strStr()

class Solution {
	public int strStr(String haystack, String needle) {
        if (needle == null || needle.length() == 0) return 0;
        int nLength = needle.length();
        for (int i = 0; i < haystack.length() - nLength + 1; i ++) {
            String possNeedle = haystack.substring(i, i + nLength);
            if (possNeedle.equals(needle)) return i;
        }
        return -1;
    }
}

21 Divide Two Integers

實現除法,不使用 /, *, %

Divide Two Integers

class Solution {
    public int divide(int dividend, int divisor) {
        if (dividend == Integer.MIN_VALUE && divisor == -1) {
            return Integer.MAX_VALUE;
        }
        boolean isNegtive = (dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0);
        
        long up = Math.abs((long)dividend);
        long down = Math.abs((long)divisor);
        
        long res = 0;
        while(down <= up) {
            long count = 1;
            long tmp = down;
            while(tmp <= up) {
                tmp <<= 1;
                count <<= 1;
            }
            
            res += tmp == up ? count : count >> 1;
            up -= (tmp >> 1);
        }
        
        return isNegtive ? (int)(0 - res) : (int)res;
    }
}

22 Search in Rotated Sorted Array

在旋轉數組中查找一個數,如果不存在返回-1。要求時間複雜度爲O(logn)

Example:

Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4

Search in Rotated Sorted Array

class Solution {
    public int search(int[] nums, int target) {
        if(nums == null || nums.length == 0)return -1;
        int l = 0, r = nums.length - 1;
        while(l <= r) {
            int mid = l - (l - r) / 2;
            if(nums[mid] == target) return mid;
            //67012345
            else if (nums[l] > nums[mid]) {
                if(target > nums[r] || target < nums[mid]) r = mid - 1;
                else l = mid + 1;
            }
            //34567012
            else {
                if(target < nums[l] || target > nums[mid]) l = mid + 1;
                else r = mid - 1;
            }
        }
        return -1;
    }
}

23 Find First and Last Position of Element in Sorted Array

在一個排序有重複數組中,找到target的起始和終止下標。時間複雜度要求O(logn),如果沒有找到,返回[-1, -1]

Example 1:

Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]

Find First and Last Position of Element in Sorted Array

class Solution {
    // 返回目標數的開始和結束
    public int[] searchRange(int[] nums, int target) {
        int res[] = {-1, -1};
        if (nums.length == 0)
            return res;
        int left = binarySearch(nums, target - 0.5);
        int right = binarySearch(nums, target + 0.5);
        if (right - left == 0)
            return res;
        res[0] = left;
        res[1] = right - 1;
        return res;
    }

    private int binarySearch(int[] arr, double target) {
        int left = 0;
        int right = arr.length - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (arr[mid] > target)
                right = mid - 1;
            else if (arr[mid] < target)
                left = mid + 1;
        }
        return left;
    }
}

24 Valid Sudoku

驗證9 * 9數獨的正確,每一行,每一列,每一個3 * 3 數組不能有重複

Valid Sudoku

public boolean isValidSudoku(char[][] board) {
    int[][][] freq = new int[3][9][9];
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            if (board[i][j] != '.') {
                int current = board[i][j] - '0';

                int box = ++freq[0][(i / 3) * 3 + j / 3][current - 1];
                int row = ++freq[1][i][current - 1];
                int col = ++freq[2][j][current - 1];

                if (box > 1 || row > 1 || col > 1) return false;
            }
        }
    }

    return true;
}

25 Count and Say

不知道題目啥意思

Count and Say


26 First Missing Positive

給定一個未排序的整數數組,找到最小的缺失正整數。時間複雜度要求O(n),空間複雜度O(1)

Example 1:

Input: [1,2,0]
Output: 3

Input: [3,4,-1,1]
Output: 2

Input: [7,8,9,11,12]
Output: 1

First Missing Positive

class Solution {
    public int firstMissingPositive(int[] nums) {
        for(int i = 0; i < nums.length; i ++) {
            while(nums[i] > 0 && nums[i] <= nums.length) {
                int tmp = nums[i];
                if(tmp == nums[tmp - 1])break;//重複數據不叫喚
                nums[i] = nums[tmp - 1];
                nums[tmp - 1] = tmp;
            }
        }
        
        for(int i = 0; i < nums.length; i ++) {
            if(i + 1 != nums[i])
                return i + 1;
        }
        return nums.length + 1;
    }
}

27 Trapping Rain Water

給一個數組,假設如果下雨了,這個數組在xy座標軸上會存多少水?

Trapping Rain Water

class Solution {
    public int trap(int[] nums) {
        if(nums == null || nums.length < 2)return 0;
        
        int leftMax = 0, rightMax = 0;
        
        int l = 0, r = nums.length - 1;
        int res = 0;
      	//計算每個位置可以存多少水
        while(l < r) {
            if(nums[l] < nums[r]) {
                if(nums[l] > leftMax) 
                    leftMax = nums[l];
                else 
                    res += leftMax - nums[l];
                l ++;
            } else {
                if(nums[r] > rightMax) 
                    rightMax = nums[r] ;
                else 
                    res += rightMax - nums[r];
                r --;
            }
        }
        return res;
    }
}

28 Wildcard Matching(Hard)

字符匹配

'?' Matches any single character.
'*' Matches any sequence of characters (including the empty sequence).

Wildcard Matching


29 Permutations

給定一組不同的整數,返回所有可能的排列。

Example:

Input: [1,2,3]
Output:
[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

Permutations

class Solution {
    List<List<Integer>> res;
    boolean []used;
    public List<List<Integer>> permute(int[] nums) {
        if(nums == null || nums.length == 0)return new ArrayList<>();
        res = new ArrayList<>();
        used = new boolean[nums.length];
        helper(nums, new ArrayList<>());
        return res;
    }
    //回溯
    private void helper(int[] nums, List<Integer> list) {
        if(nums.length == list.size()) {
            res.add(new ArrayList<>(list));
            return;
        }
        
        for(int i = 0; i < nums.length; i ++) {
            if(!used[i]) {
                used[i] = true;
                list.add(nums[i]);
                helper(nums, list);
                list.remove(list.size() - 1);
                used[i] = false;
            }
        }
    }
}

30 Rotate Image

您會得到一個表示圖像的n x n 2D矩陣。將圖像旋轉90度(順時針)。

Example 1:

Given input matrix = 
[
  [1,2,3],
  [4,5,6],
  [7,8,9]
],

rotate the input matrix in-place such that it becomes:
[
  [7,4,1],
  [8,5,2],
  [9,6,3]
]

Rotate Image

class Solution {
    public void rotate(int[][] matrix) {
        if(matrix.length == 0)return;
      	//對角線互換
        for(int i = 0; i < matrix.length; i ++){
            for(int j = i; j < matrix[0].length; j ++){
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        }
      	//中豎線互換
        for(int i = 0; i < matrix.length; i ++){
            for(int j = 0; j < matrix[0].length / 2; j ++){
                int temp = matrix[i][j];
                matrix[i][j] = matrix[i][matrix[0].length - j - 1];
                matrix[i][matrix[0].length - j - 1] = temp;
            }
        }
    }
}

31 Group Anagrams

給定一個字符串數組,將相同字符分組在一起。

Example:

Input: ["eat", "tea", "tan", "ate", "nat", "bat"],
Output:
[
  ["ate","eat","tea"],
  ["nat","tan"],
  ["bat"]
]

Group Anagrams

思路:利用hashmap的特性,相同hash值的字符串分配到一起

class Solution {
    public List<List<String>> groupAnagrams(String[] strs) {
        if (strs.length == 0)
            return new ArrayList<>();
        List<List<String>> listAll = new ArrayList<>();
        HashMap<String, List<String>> map = new HashMap<>();

        for (String s : strs) {
            String hash = hash(s);
            if (!map.containsKey(hash))
                map.put(hash, new ArrayList<String>());
            map.get(hash).add(s);
        }
        listAll.addAll(map.values());
        return listAll;
    }

    private String hash(String s) {
        int arr[] = new int[26];
        for (int i = 0; i < s.length(); i++) {
            arr[s.charAt(i) - 'a']++;
        }
        return Arrays.toString(arr);
    }
}

32 Pow(x, n)

實現pow函數

Example 1:

Input: 2.00000, 10
Output: 1024.00000

Pow(x, n)

class Solution {
    public double myPow(double x, int n) {
        if(n == 0)return 1;
        int pn = Math.abs(n);
        
        double res = myPow(x, pn >> 1);
        res *= res;
      	//防止溢出
        if(res > Double.MAX_VALUE / res)return 0.0;
        if((n & 1) == 1)res *= x;
        
        if(n < 0)res = 1 / res;
        
        return res;
    }
}

33 Spiral Matrix

循環打印矩陣

Spiral Matrix

class Solution {
    public List < Integer > spiralOrder(int[][] matrix) {
        List ans = new ArrayList();
        if (matrix.length == 0)
            return ans;
        int r1 = 0, r2 = matrix.length - 1;
        int c1 = 0, c2 = matrix[0].length - 1;
        while (r1 <= r2 && c1 <= c2) {
            for (int c = c1; c <= c2; c++) ans.add(matrix[r1][c]);
            for (int r = r1 + 1; r <= r2; r++) ans.add(matrix[r][c2]);
            if (r1 < r2 && c1 < c2) {
                for (int c = c2 - 1; c > c1; c--) ans.add(matrix[r2][c]);
                for (int r = r2; r > r1; r--) ans.add(matrix[r][c1]);
            }
            r1++;
            r2--;
            c1++;
            c2--;
        }
        return ans;
    }
}

34 Jump Game

給定一個非負整數數組,您最初位於該數組的第一個索引處。數組中的每個元素代表該位置的最大跳轉長度。確定您是否能夠達到最後一個索引。

Example 1:

Input: [2,3,1,1,4]
Output: true
Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.
  
Input: [3,2,1,0,4]
Output: false
Explanation: You will always arrive at index 3 no matter what. Its maximum
             jump length is 0, which makes it impossible to reach the last index.

思路:如果從該位置開始,我們可以到達最後一個索引,則我們將該數組中的位置稱爲“良好索引”。否則,該索引稱爲“不良索引”。然後問題減少到索引0是否爲“良好索引”。

Jump Game

O(n^2)

public class Solution {
    public boolean canJump(int[] nums) {
        Index[] memo = new Index[nums.length];
        for (int i = 0; i < memo.length; i++) {
            memo[i] = Index.UNKNOWN;
        }
        memo[memo.length - 1] = Index.GOOD;

        for (int i = nums.length - 2; i >= 0; i--) {
            int furthestJump = Math.min(i + nums[i], nums.length - 1);
          	//如果能跳轉到good節點,直接結束循環
            for (int j = i + 1; j <= furthestJump; j++) {
                if (memo[j] == Index.GOOD) {
                    memo[i] = Index.GOOD;
                    break;
                }
            }
        }

        return memo[0] == Index.GOOD;
    }
}

O(n)

class Solution {
    public boolean canJump(int[] nums) {
        int len = nums.length;
        int max = 0;
        for(int i=0; i<=max; i++){
            max = Math.max(max, i+nums[i]);
            if(max >= len-1)  return true;
        }
        return false;
    }
}

O(n)

class Solution {
    public boolean canJump(int[] nums) {
        int lastValidIndex = nums.length - 1;
        int i = nums.length - 1;

        while (i >= 0) {
            if (nums[i] + i >= lastValidIndex) {
                lastValidIndex = i;
            }

            i--;
        }

        return lastValidIndex == 0;
    }
}

35 Merge Intervals

給定間隔的集合,合併所有重疊的間隔。

Example:

Input: [[1,3],[2,6],[8,10],[15,18]]
Output: [[1,6],[8,10],[15,18]]
Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].

Merge Intervals

class Solution {
    private class IntervalComparator implements Comparator<int[]> {
        @Override
        public int compare(int[] a, int[] b) {
            return a[0] - b[0];
        }
    }

    public int[][] merge(int[][] intervals) {
        Collections.sort(Arrays.asList(intervals), new IntervalComparator());

        LinkedList<int[]> merged = new LinkedList<>();
        for (int[] interval : intervals) {
            if (merged.isEmpty() || merged.getLast()[1] < interval[0]) {
                merged.add(interval);
            } else {
                merged.getLast()[1] = Math.max(merged.getLast()[1], interval[1]);
            }
        }

        return merged.toArray(new int[merged.size()][]);
    }
}

36 Unique Paths

機器人位於m x n網格的左上角(在下圖中標記爲“開始”)。機器人只能在任何時間點上下移動。機器人試圖到達網格的右下角(在下圖中標記爲“完成”)。有多少可能的唯一路徑?

Unique Paths

class Solution {
    public int uniquePaths(int m, int n) {
        if(m == 0)return 0;
        if(n == 0)return 1;
        int res[][] = new int[m][n];
        res[0][0] = 1;
        for(int i = 0; i < m; i ++) {
            for(int j = 0; j < n; j ++) {
              	//到這個位置的路徑數 = 上一步往下走的路徑數 + 上一步往右走的步數
                if(i > 0)res[i][j] += res[i - 1][j];
                if(j > 0)res[i][j] += res[i][j - 1];
                
            }
        }
        return res[m - 1][n - 1];
    }
}

37 Plus One

給一個整數數組,返回這個數組轉化成int值 在加一的結果。

Example 1:

Input: [1,2,3]
Output: [1,2,4]
Explanation: The array represents the integer 123.

Plus One

class Solution {
    public int[] plusOne(int[] digits) {
        if (digits == null) {
            return null;
        }
        for (int i = digits.length - 1; i >= 0; i--) {
            if (digits[i] < 9) {
                digits[i]++;
                return digits;
            } else {
                digits[i] = 0;
            }
        }

        // [9, 9, 9]
        int[] result = new int[digits.length + 1];
        result[0] = 1;
        return result;
    }
}

38 Sqrt(x)

實現Sqrt(x)

Sqrt(x)

思路:使用二分搜索

class Solution {
    public int mySqrt(int x) {
        int l = 1, r = x;
        while(l < r) {
            int mid = l - (l - r) / 2 + 1;
            if(mid > x / mid) r = mid - 1;
            else l = mid;
        }
        return r;
    }
}


39 Climbing Stairs

類似跳臺階,使用斐波那契數列實現

Climbing Stairs

class Solution {
    public int climbStairs(int n) {
        if(n == 1)return 1;
        if(n == 2)return 2;
        int first = 1;
        int secend = 2;
        int res = 0;
        for(int i = 2; i < n; i ++){
            res = first + secend;
            first = secend;
            secend = res;
        }
        return res;
    }
}

40 Set Matrix Zeroes

給定一個m x n矩陣,如果一個元素是0,設置它的行和列爲0

Example:

Input: 
[
  [1,1,1],
  [1,0,1],
  [1,1,1]
]
Output: 
[
  [1,0,1],
  [0,0,0],
  [1,0,1]
]

Set Matrix Zeroes

class Solution {
    public void setZeroes(int[][] matrix) {
        if(matrix == null || matrix.length == 0)return;
        int m = matrix.length, n = matrix[0].length;
        boolean flag = false;
        //把0的標記都放到第一行第一列
        for(int i = 0; i < m; i ++) {
            if(!flag && matrix[i][0] == 0) {
                //標記第一列是否要設置爲0
                flag = true;
            }
            for(int j = 1; j < n; j ++) {
                if(matrix[i][j] == 0) {
                    matrix[0][j] = 0;
                    matrix[i][0] = 0;
                }
            }
        }
        
        for(int i = 1; i < m; i ++) {
            for(int j = 1; j < n; j ++) {
                if(matrix[i][0] == 0 || matrix[0][j] == 0) {
                    matrix[i][j] = 0;
                }
            }
        }
        
        //判斷第一列是否要置0
        if(matrix[0][0] == 0) {
            for(int i = 0; i < n; i ++) {
                matrix[0][i] = 0;
            }
        }
        //判斷第一列是否要置0
        if(flag) {
            for(int i = 0; i < m; i ++) {
                matrix[i][0] = 0;
            }
        }
    }   
}

41 Sort Colors

給定一個包含n個紅色、白色或藍色對象的數組,對它們進行排序,使相同顏色的對象相鄰,顏色按紅、白、藍的順序排列。這裏,我們將使用整數0、1和2分別表示紅色、白色和藍色。

Example:

Input: [2,0,2,1,1,0]
Output: [0,0,1,1,2,2]

Sort Colors

class Solution {
    public void sortColors(int[] nums) {
        if(nums == null && nums.length == 0)return;
        int l = 0, r = nums.length - 1;
        for(int i = 0; i <= r; i ++) {
            if(nums[i] == 1)continue;
            if(nums[i] == 0) {
                int tmp = nums[i];
                nums[i] = nums[l];
                nums[l] = tmp;
                //和前面的換不管換0 和 1都要往前走 所以i不用減1,和前面換不可能換來2
                l ++;
            } else {
                int tmp = nums[i];
                nums[i] = nums[r];
                nums[r] = tmp;
                //因爲和最後換可能換來0 或 2則 i --;
                r --;
                i --;
            }
        }
    }
}

42 Minimum Window Substring

給定一個字符串S和一個字符串T,找出S中的最小窗口,該窗口將包含T中的所有字符。 複雜度O(n)

思路:使用滑動窗口

Minimum Window Substring

class Solution {
    	public String minWindow(String s, String t) {
		if(s.length() < t.length())return "";
		HashMap<Character,Integer> mapT = new HashMap<>();
		HashMap<Character,Integer> mapS = new HashMap<>();
		for(int i = 0 ; i < t.length() ; i ++) {
			char c = t.charAt(i);
			int count = mapT.getOrDefault(c, 0);
			mapT.put(c, count + 1);
		}
		int formed = 0;
		int requested = mapT.size();
		int minL = s.length() + 1;
		int left = 0,right = 0;
		String result = "";
		while(right < s.length()) {
			char c = s.charAt(right);
			int count = mapS.getOrDefault(c, 0);
			mapS.put(c, count + 1);
			if(mapT.containsKey(c) && mapT.get(c).intValue() == mapS.get(c).intValue())
				formed++;
			while(left <= right && formed == requested) {
				if(minL > right - left + 1) {
					result = s.substring(left, right + 1);
					minL = right - left + 1;
				}
				mapS.put(s.charAt(left),mapS.get(s.charAt(left)) - 1);
				if(mapT.containsKey(s.charAt(left)) && mapT.get(s.charAt(left)).intValue() > mapS.get(s.charAt(left)).intValue()) {
					formed --;
				}
				left ++;
			}
			right++;
		}
		if(minL == s.length() + 1)
			return "";
		return result;
	}
}

43 Subsets

輸出素組的所有子集

Subsets

class Solution {
    List<List<Integer>> res;
    public List<List<Integer>> subsets(int[] nums) {
        res = new ArrayList<>();
        if(nums == null || nums.length == 0) return res;
        //找到長度爲i的子集
        for(int i = 0; i <= nums.length; i ++)
            helper(new ArrayList<>(), nums, 0, i);
        return res;
    }
    
    private void helper(List<Integer> list, int[]nums, int index, int k) {
        if(list.size() == k) {
            res.add(new ArrayList<>(list));
            return;
        }
        
        for(int i = index; i < nums.length; i ++) {
            list.add(nums[i]);
            //避免重複  從i + 1之後添加
            helper(list, nums, i + 1, k);
            list.remove(list.size() - 1);
        }
    }
}

44 Word Search

給定一個2D板和一個單詞,找出這個單詞是否存在於網格中。

這個詞可以由連續相鄰單元格的字母構成,其中“相鄰”單元格是水平或垂直相鄰的單元格。同一個字母單元格不能使用多次。

Example:

board =
[
  ['A','B','C','E'],
  ['S','F','C','S'],
  ['A','D','E','E']
]

Given word = "ABCCED", return true.
Given word = "SEE", return true.
Given word = "ABCB", return false.

Word Search

class Solution {
    boolean [][] used;//記錄已經訪問過的元素
    public boolean exist(char[][] board, String word) {
        if(board == null || board.length == 0)return false;
        if(word == null || word.equals(""))return false;
        int m = board.length, n = board[0].length;
        
        used = new boolean[m][n];
        
        for(int i = 0; i < m; i ++) {
            for(int j = 0; j < n; j ++) {
                //匹配第一個字符
                if(board[i][j] == word.charAt(0) && helper(board, word, i, j, 0)) 
                    return true;
            }
        }
        return false;
    }
    
    private boolean helper(char[][]board, String word, int x, int y, int len) {
        if(x < 0 || x > board.length - 1 || y < 0 || y > board[0].length - 1 || used[x][y]
          || len > word.length() || board[x][y] != word.charAt(len)) return false;
        
        if(len + 1 == word.length()) {
            return true;
        }
        used[x][y] = true;
        //如果有一條路徑找到直接返回
        if(helper(board, word, x + 1, y, len + 1) 
            || helper(board, word, x, y + 1, len + 1)
            || helper(board, word, x - 1, y, len + 1)
            || helper(board, word, x, y - 1, len + 1))
            return true;
        used[x][y] = false;
        return false;
    }
}

45 Largest Rectangle in Histogram

給定n個非負整數表示直方圖的條高,其中每個條的寬度爲1,在直方圖中找到最大矩形的區域。

Largest Rectangle in Histogram

class Solution {
    public int largestRectangleArea(int[] heights) {
        if(heights == null || heights.length == 0)return 0;
        int []lessFromLeft = new int[heights.length];//存儲大於等於當前長度的最小座標
        int []lessFromRight = new int[heights.length];//存儲大於等於當前長度的最大座標
        
        lessFromRight[heights.length - 1] = heights.length;
        lessFromLeft[0] = -1;
        for(int i = 1; i < heights.length; i ++) {
            int p = i - 1;
            while(p >= 0 && heights[p] >= heights[i]) {
                p = lessFromLeft[p];
            }
            lessFromLeft[i] = p;
        }
        
        for(int i = heights.length - 2; i >= 0; i --) {
            int p = i + 1;
            while(p < heights.length && heights[p] >= heights[i]) {
                p = lessFromRight[p];
            }
            lessFromRight[i] = p;
        }
        int max = 0;
        for(int i = 0; i < heights.length; i ++) {
            max = Math.max(max, heights[i] * (lessFromRight[i] - lessFromLeft[i] - 1));
        }
        return max;
    }
}

46 Merge Sorted Array

給定兩個排序整數數組nums1和nums2,將nums2合併爲一個排序數組nums1。

Example:

Input:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6],       n = 3

Merge Sorted Array

思路:歸併排序最後一步合併

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        m -= 1;
        n -= 1;
        int l = nums1.length - 1;
        while(m >= 0 && n >= 0){
            nums1[l --] = nums1[m] > nums2[n] ? nums1[m --] : nums2[n --];
        }
        while(n >= 0)
            nums1[l --] = nums2[n --];
    }
}

47 Decode Ways

使用以下映射將包含A-Z字母的郵件編碼爲數字:

“A”->1

“B”->2

“Z”->26

給定一個只包含數字的非空字符串,確定解碼該字符串的方法總數。

Example:

Input: "12"
Output: 2
Explanation: It could be decoded as "AB" (1 2) or "L" (12).

思路:類似青蛙跳臺階的斐波那契數列。只是f(n - 2)需要滿足條件

Decode Ways

class Solution {
    public int numDecodings(String s) {
		if(s.length() == 0)return 0;
		int []dp = new int[s.length() + 1];
		
		dp[0] = 1;
		dp[1] = s.charAt(0) == '0' ? 0 : 1;
		
		for(int i = 2; i <= s.length(); i ++) {
			int f = Integer.valueOf(s.substring(i - 1, i));
			int se = Integer.valueOf(s.substring(i - 2,i));
			
			if(f >= 1 && f <= 9)
				dp[i] += dp[i - 1];
			if(se >= 10 && se <= 26)
				dp[i] += dp[i - 2];
		}
		return dp[s.length()];
	}
}

48 Binary Tree Inorder Traversal

返回二叉樹的中序排序

Binary Tree Inorder Traversal

  • 1 遞歸
class Solution {
    private List<Integer> res;
    public List<Integer> inorderTraversal(TreeNode root) {
        res = new ArrayList<>();
        if(root == null)return res;
        helper(root);
        return res;
    }
    
    private void helper(TreeNode node) {
        if(node != null) {
            helper(node.left);
            res.add(node.val);
            helper(node.right);
        }
    }
}
  • 2 非遞歸
class Solution {
    List<Integer> res; 
    public List<Integer> inorderTraversal(TreeNode root) {
        res = new ArrayList<>();
        if(root == null)return res;
        
        Stack<TreeNode> stack = new Stack<>();
        
        while(!stack.isEmpty() || root != null) {
            while(root != null) {
                stack.push(root);
                root = root.left;
            }
            root = stack.pop();
            res.add(root.val);
            root = root.right;
        }
        return res;
    }
}

49 Validate Binary Search Tree

驗證一棵樹是否是二分搜素樹

思路:二分搜索樹的中序遍歷是遞增的,所以使用非遞歸方式遍歷判斷是否是遞增即可

Validate Binary Search Tree

class Solution {
    public boolean isValidBST(TreeNode root) {
        if(root == null)return true;
        
        Long temp = Long.MIN_VALUE;
        Stack<TreeNode> stack = new Stack<>();
        while(root != null || !stack.isEmpty()){
            while(root != null){
                stack.push(root);
                root = root.left;
            }
            root = stack.pop();
            if(temp >= root.val)
                return false;
            else
                temp = (long)root.val;
            root = root.right;
        }
        return true;
    }
}

50 Symmetric Tree

判斷一棵樹是否是對稱的

    1
   / \
  2   2
 / \ / \
3  4 4  3

Symmetric Tree

class Solution {
    public boolean isSymmetric(TreeNode root) {
        if(root == null)return true;
        return isSymmetric(root.left, root.right);
    }
    
    public boolean isSymmetric(TreeNode node1, TreeNode node2) {
        if(node1 == null)return node2 == null;
        if(node2 == null)return node1 == null;
        return node1.val == node2.val && isSymmetric(node1.left, node2.right)  && isSymmetric(node2.left, node1.right);
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章