LeetCode 热题 HOT 100
1. 两数之和
1 class Solution { 2 public int[] twoSum(int[] nums, int target) { 3 Map<Integer, Integer> mapping = new HashMap<>(); 4 for (int i = 0; i < nums.length; i++) { 5 int key = target - nums[i]; 6 if (mapping.containsKey(key)) { 7 return new int[]{mapping.get(key), i}; 8 } 9 mapping.put(nums[i], i); 10 } 11 return new int[]{-1, -1}; 12 } 13 }
2. 两数相加
1 /** 2 * Definition for singly-linked list. 3 * public class ListNode { 4 * int val; 5 * ListNode next; 6 * ListNode() {} 7 * ListNode(int val) { this.val = val; } 8 * ListNode(int val, ListNode next) { this.val = val; this.next = next; } 9 * } 10 */ 11 class Solution { 12 public ListNode addTwoNumbers(ListNode l1, ListNode l2) { 13 ListNode head = new ListNode(-1); 14 ListNode l = head; 15 int sum = 0; 16 boolean carry = false; 17 while (l1 != null || l2 != null) { 18 sum = 0; 19 if (l1 != null) { 20 sum += l1.val; 21 l1 = l1.next; 22 } 23 if (l2 != null) { 24 sum += l2.val; 25 l2 = l2.next; 26 } 27 if (carry) { 28 sum++; 29 } 30 l.next = new ListNode(sum % 10); 31 l = l.next; 32 carry = sum / 10 == 0 ? false : true; 33 } 34 if (carry) { 35 l.next = new ListNode(1); 36 } 37 return head.next; 38 } 39 }
3. 无重复字符的最长子串
1 class Solution { 2 public int lengthOfLongestSubstring(String s) { 3 // 滑动窗口 4 if (s.length() <= 0) { 5 return 0; 6 } 7 int left = 0; 8 int max = 0; 9 Map<Character, Integer> mapping = new HashMap<>(); 10 for (int i = 0; i < s.length(); i++) { 11 if (mapping.containsKey(s.charAt(i))) { 12 left = Math.max(left, mapping.get(s.charAt(i)) + 1); 13 } 14 mapping.put(s.charAt(i), i); 15 max = Math.max(max, i - left + 1); 16 } 17 return max; 18 } 19 }
76. 最小覆盖子串
很难,看解答理解后敲出来的
1 class Solution { 2 public String minWindow(String s, String t) { 3 if (s == null || s.length() == 0 || t == null || t.length() == 0) { 4 return ""; 5 } 6 int[] need = new int[128]; 7 for (int i = 0; i < t.length(); i++) { 8 need[t.charAt(i)]++; 9 } 10 int l = 0, r = 0, size = Integer.MAX_VALUE, count = t.length(), start = 0; 11 while (r < s.length()) { 12 char c = s.charAt(r); 13 if (need[c] > 0) { 14 count--; 15 } 16 need[c]--; 17 if (count == 0) { 18 while (l < r && need[s.charAt(l)] < 0) { 19 need[s.charAt(l)]++; 20 l++; 21 } 22 if (r - l + 1 < size) { 23 size = r - l + 1; 24 start = l; 25 } 26 need[s.charAt(l)]++; 27 l++; 28 count++; 29 } 30 r++; 31 } 32 return size == Integer.MAX_VALUE ? "" : s.substring(start, start + size); 33 } 34 }
30. 串联所有单词的子串
1 class Solution { 2 public List<Integer> findSubstring(String s, String[] words) { 3 List<Integer> res = new ArrayList<>(); 4 if (words == null || words.length == 0) { 5 return res; 6 } 7 Map<String, Integer> allWords = new HashMap<>(); 8 for (String word : words) { 9 int wordCount = allWords.getOrDefault(word, 0); 10 allWords.put(word, wordCount + 1); 11 } 12 int wordNum = words.length; 13 int wordLen = words[0].length(); 14 for (int i = 0; i < s.length() - wordNum * wordLen + 1; i++) { 15 int num = 0; 16 Map<String, Integer> hasWords = new HashMap<>(); 17 while (num < wordNum) { 18 String word = s.substring(i + num * wordLen, i + (num + 1) * wordLen); 19 if (allWords.containsKey(word)) { 20 int wordCount = hasWords.getOrDefault(word, 0); 21 hasWords.put(word, wordCount + 1); 22 if (hasWords.get(word) > allWords.get(word)) { 23 break; 24 } 25 num++; 26 } else { 27 break; 28 } 29 } 30 if (num == wordNum) { 31 res.add(i); 32 } 33 } 34 return res; 35 } 36 }
解法二看答案,思路理解,代码好难、好难
209. 长度最小的子数组
暴力解法
1 class Solution { 2 public int minSubArrayLen(int target, int[] nums) { 3 int min = Integer.MAX_VALUE; 4 for (int i = 0; i < nums.length; i++) { 5 int sum = nums[i]; 6 if (sum >= target) { 7 return 1; 8 } 9 for (int j = i + 1; j < nums.length; j++) { 10 sum += nums[j]; 11 if (sum >= target) { 12 min = Math.min(min, j - i + 1); 13 break; 14 } 15 } 16 } 17 return min == Integer.MAX_VALUE ? 0 : min; 18 } 19 }
滑动窗口
1 class Solution { 2 public int minSubArrayLen(int target, int[] nums) { 3 int l = 0, r = 0, sum = 0, min = Integer.MAX_VALUE; 4 while (r < nums.length) { 5 sum += nums[r++]; 6 while (sum >= target) { 7 min = Math.min(min, r - l); 8 sum -= nums[l++]; 9 } 10 } 11 return min == Integer.MAX_VALUE ? 0 : min; 12 } 13 }
1 class Solution { 2 public int minSubArrayLen(int target, int[] nums) { 3 int l = 0, r = 0, min = Integer.MAX_VALUE; 4 while (r < nums.length) { 5 target -= nums[r++]; 6 while (target <= 0) { 7 min = Math.min(min, r - l); 8 target += nums[l++]; 9 } 10 } 11 return min == Integer.MAX_VALUE ? 0 : min; 12 } 13 }
窗口大小的方式
1 class Solution { 2 public int minSubArrayLen(int target, int[] nums) { 3 int l = 1, h = nums.length, min = 0; 4 while (l <= h) { 5 int mid = (l + h) >> 1; 6 if (helper(target, nums, mid)) { 7 min = mid; 8 h = mid - 1; 9 } else { 10 l = mid + 1; 11 } 12 } 13 return min; 14 } 15 16 private boolean helper(int target, int[] nums, int size) { 17 int sum = 0; 18 for (int i = 0; i < nums.length; i++) { 19 if (i >= size) { 20 sum -= nums[i - size]; 21 } 22 sum += nums[i]; 23 if (sum >= target) { 24 return true; 25 } 26 } 27 return false; 28 } 29 }
4. 寻找两个正序数组的中位数
1 class Solution { 2 public double findMedianSortedArrays(int[] nums1, int[] nums2) { 3 int n = nums1.length; 4 int m = nums2.length; 5 // 求中位数的技巧 6 int left = (n + m + 1) / 2; 7 int right = (n + m + 2) / 2; 8 return (findKth(nums1, 0, n - 1, nums2, 0, m - 1, left) + findKth(nums1, 0, n - 1, nums2, 0, m - 1, right)) * 0.5; 9 } 10 11 private int findKth(int[] nums1, int start1, int end1, int[] nums2, int start2, int end2, int k) { 12 int len1 = end1 - start1 + 1; 13 int len2 = end2 - start2 + 1; 14 // 保证nums1是短数组 15 if (len1 > len2) { 16 return findKth(nums2, start2, end2, nums1, start1, end1, k); 17 } 18 // nums1已遍历完毕,则一定存在与nums2中,直接返回 19 if (len1 == 0) { 20 return nums2[start2 + k - 1]; 21 } 22 // k=1表示两个数组第一个数字,则直接返回最小的即可 23 if (k == 1) { 24 return Math.min(nums1[start1], nums2[start2]); 25 } 26 int i = start1 + Math.min(len1, k / 2) - 1; 27 int j = start2 + Math.min(len2, k / 2) - 1; 28 if (nums1[i] > nums2[j]) { 29 return findKth(nums1, start1, end1, nums2, j + 1, end2, k - Math.min(len2, k / 2)); 30 } else { 31 return findKth(nums1, i + 1, end1, nums2, start2, end2, k - Math.min(len1, k / 2)); 32 } 33 } 34 }
1 class Solution { 2 public double findMedianSortedArrays(int[] nums1, int[] nums2) { 3 int len = nums1.length + nums2.length; 4 if (len % 2 == 0) { 5 return (findKth(nums1, 0, nums2, 0, len / 2) + findKth(nums1, 0, nums2, 0, len / 2 + 1)) / 2.0; 6 } else { 7 return findKth(nums1, 0, nums2, 0, len / 2 + 1); 8 } 9 } 10 11 private int findKth(int[] nums1, int start1, int[] nums2, int start2, int k) { 12 if (start1 >= nums1.length) { 13 return nums2[start2 + k - 1]; 14 } 15 if (start2 >= nums2.length) { 16 return nums1[start1 + k - 1]; 17 } 18 if (k == 1) { 19 return Math.min(nums1[start1], nums2[start2]); 20 } 21 int i = start1 + k / 2 - 1 < nums1.length ? nums1[start1 + k / 2 - 1] : Integer.MAX_VALUE; 22 int j = start2 + k / 2 - 1 < nums2.length ? nums2[start2 + k / 2 - 1] : Integer.MAX_VALUE; 23 // 一定要是k - k / 2 24 if (i > j) { 25 return findKth(nums1, start1, nums2, start2 + k / 2, k - k / 2); 26 } else { 27 return findKth(nums1, start1 + k / 2, nums2, start2, k - k / 2); 28 } 29 } 30 }
5. 最长回文子串
暴力法
1 class Solution { 2 public String longestPalindrome(String s) { 3 int len = s.length(); 4 if (len < 2) { 5 return s; 6 } 7 char[] chars = s.toCharArray(); 8 int start = 0; 9 int maxLen = 1; 10 for (int i = 0; i < len - 1; i++) { 11 for (int j = i + 1; j < len; j++) { 12 if (j - i + 1 > maxLen && helper(chars, i, j)) { 13 maxLen = j - i + 1; 14 start = i; 15 } 16 } 17 } 18 return s.substring(start, start + maxLen); 19 } 20 21 private boolean helper(char[] chars, int start, int end) { 22 while (start < end) { 23 if (chars[start] == chars[end]) { 24 start++; 25 end--; 26 } else { 27 return false; 28 } 29 } 30 return true; 31 } 32 }
动态规划
1 class Solution { 2 public String longestPalindrome(String s) { 3 int len = s.length(); 4 if (len < 2) { 5 return s; 6 } 7 char[] chars = s.toCharArray(); 8 int start = 0; 9 int maxLen = 1; 10 boolean[][] dp = new boolean[len][len]; 11 for (int i = 0; i < len; i++) { 12 dp[i][i] = true; 13 } 14 for (int j = 1; j < len; j++) { 15 for (int i = 0; i < j; i++) { 16 if (chars[i] != chars[j]) { 17 dp[i][j] = false; 18 } else { 19 if (j - i < 3) { 20 dp[i][j] = true; 21 } else { 22 dp[i][j] = dp[i + 1][j - 1]; 23 } 24 } 25 26 if (j - i + 1 > maxLen && dp[i][j]) { 27 start = i; 28 maxLen = j - i + 1; 29 } 30 } 31 } 32 return s.substring(start, start + maxLen); 33 } 34 }
10. 正则表达式匹配
20. 有效的括号
1 class Solution { 2 public boolean isValid(String s) { 3 if (s.isEmpty()) { 4 return true; 5 } 6 if (s.length() % 2 == 1) { 7 return false; 8 } 9 LinkedList<Character> stack = new LinkedList<>(); 10 for (char c : s.toCharArray()) { 11 if (c == '(') { 12 stack.push(')'); 13 } else if (c == '{') { 14 stack.push('}'); 15 } else if (c == '[') { 16 stack.push(']'); 17 } else if (stack.isEmpty() || c != stack.pop()) { 18 return false; 19 } 20 } 21 return stack.isEmpty(); 22 } 23 }