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);
    }
}

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