1. How to write the correct algorithm: clarify the definition of variables.
public int binarySearch(int[] a){ int l = 0, r = n - 1; // Find target in the range of [l...r] while( l <= r){ // When l == r, the interval [l...r] is still valid int mid = l + (r - l) / 2; if(a[mid] == target){ return mid; } if(target > a[mid]) l = mid + 1; // target in [mid+1...r] else r = mid - 1; // target in [l...mid-1] } }
public int binarySearch(int[] a){ int l = 0, r = n; // Find target in the range of [l...r) while( l < r){ // When square l == r, the interval [l...r) is invalid int mid = l + (r - l) / 2; if(a[mid] == target){ return mid; } if(target > a[mid]) l = mid + 1; // target in [mid+1...r) else r = mid; // target in [l...mid) } }
283. Move zero
Given an array num, write a function to move all zeros to the end of the array while maintaining the relative order of non-zero elements.
Example:
input: [0,1,0,3,12] output: [1,3,12,0,0]
explain:
- You must operate on the original array and cannot copy additional arrays.
- Minimize the number of operations.
Solution:
Definition [0,k) represents non-zero elements in the num array, and k is initialized to 0;
Traverse the entire array. If it is a non-zero element, add it to the k-th position, and then K + +;
Finally, K ~ num The element of length can be filled with 0.
class Solution { public void moveZeroes(int[] nums) { int k = 0;//[0,k) represents non-0 elements in nums for(int i = 0; i < nums.length; i++){ if(nums[i] != 0){ nums[k++] = nums[i]; } } for(int i = k; i < nums.length; i++){ nums[i] = 0; } } }
26. Delete duplicates in the ordered array
Give you an ordered array nums, please In situ Delete the repeated elements so that each element appears only once, and return the new length of the deleted array.
Do not use additional array space, you must In situ Modify the input array and do it with O(1) extra space.
explain:
Why is the returned value an integer, but the output answer is an array?
Note that the input array is passed by reference, which means that modifying the input array in the function is visible to the caller.
You can imagine the internal operation as follows:
// nums is passed by reference. That is, no copy of the arguments is made int len = removeDuplicates(nums); // Modifying the input array in the function is visible to the caller. // According to the length returned by your function, it will print all elements within that length range in the array. for (int i = 0; i < len; i++) { print(nums[i]); }
Example 1:
Input: nums = [1,1,2] Output: 2, nums = [1,2] Explanation: the function should return a new length of 2 and the original array nums The first two elements of are modified to 1, 2 . There is no need to consider the elements in the array that exceed the new length.
Example 2:
Input: nums = [0,0,1,1,1,2,2,3,3,4] Output: 5, nums = [0,1,2,3,4] Explanation: the function should return a new length of 5 and the original array nums The first five elements of are modified to 0, 1, 2, 3, 4 . There is no need to consider the elements in the array that exceed the new length.
Tips:
- 0 <= nums.length <= 3 * 104
- -104 <= nums[i] <= 104
- nums is arranged in ascending order
Solution:
Definition [0,i) represents non repeating elements in the num array, and k is initialized to 0;
Traverse the entire array. If it is the current element (num[j]) and the ith element, it is added to the position of i+1, and i is updated to i+1.
class Solution { public int removeDuplicates(int[] nums) { int i = 0; for(int j = 1; j < nums.length; j++){ if(nums[j] != nums[i]){ i++; nums[i] = nums[j]; } } return i + 1; } }
80. Delete duplicates in ordered array II
Give you an ordered array nums, please** In situ **Delete the repeated elements, make each element appear twice at most, and return the new length of the deleted array.
Do not use additional array space, you must In situ Modify the input array and do it with O(1) extra space.
explain:
Why is the returned value an integer, but the output answer is an array?
Note that the input array is passed by * * reference * *, which means that modifying the input array in the function is visible to the caller.
You can imagine the internal operation as follows:
// nums is passed by reference. That is, no copy of the arguments is made int len = removeDuplicates(nums); // Modifying the input array in the function is visible to the caller. // According to the length returned by your function, it will print out all elements within that length range in the array. for (int i = 0; i < len; i++) { print(nums[i]); }
Example 1:
Input: nums = [1,1,1,2,2,3] Output: 5, nums = [1,1,2,2,3] Explanation: the function should return a new length length = 5, And the first five elements of the original array are modified to 1, 1, 2, 2, 3 . There is no need to consider the elements in the array that exceed the new length.
Example 2:
Input: nums = [0,0,1,1,1,1,2,3,3] Output: 7, nums = [0,0,1,1,2,3,3] Explanation: the function should return a new length length = 7, And the first five elements of the original array are modified to 0, 0, 1, 1, 2, 3, 3 . There is no need to consider the elements in the array that exceed the new length.
Tips:
- 1 <= nums.length <= 3 * 104
- -104 <= nums[i] <= 104
- nums is arranged in ascending order
Solution:
No matter whether the first two elements are different, they are first counted into the meaning of the question; Corresponding I < 2
Then, each element is compared with the first two, and if it is greater than, it is calculated into the result. (for example, 001111 will only retain 0011).
class Solution { public int removeDuplicates(int[] nums) { int i = 0; for(int n : nums) { if(i < 2 || n > nums[i - 2]) { nums[i++] = n; } } return i; } }
75. Color classification
Given an array of n elements including red, white and blue, In situ They are sorted so that elements of the same color are adjacent and arranged in red, white and blue order.
In this problem, we use integers 0, 1 and 2 to represent red, white and blue respectively.
Example 1:
Input: nums = [2,0,2,1,1,0] Output:[0,0,1,1,2,2]
Example 2:
Input: nums = [2,0,1] Output:[0,1,2]
Example 3:
Input: nums = [0] Output:[0]
Example 4:
Input: nums = [1] Output:[1]
Tips:
- n == nums.length
- 1 <= n <= 300
- Num [i] is 0, 1, or 2
Advanced:
- Can you solve this problem without using the sorting function in the code base?
- Can you think of a one pass scan algorithm that uses only constant space?
Solution:
nums[0,zero] == 0;
nums[two, n - 1] == 2;
The middle ones are all 1. For this setting, zero is initialized to - 1 and two is initialized to n, indicating that there are no elements in these two ranges at the beginning.
class Solution { public void sortColors(int[] nums) { int zero = -1; //nums[0,zero] == 0; int two = nums.length; //nums[two,n - 1] == 2; for(int i = 0; i < two;) { if(nums[i] == 0) { zero++; int temp = nums[zero]; nums[zero] = nums[i]; nums[i] = temp; i++; }else if(nums[i] == 2) { two--; int temp = nums[two]; nums[two] = nums[i]; nums[i] = temp; }else i++; } } }
215. The kth largest element in the array
The kth largest element was found in an unordered array. Please note that you need to find the K largest element after the array is sorted, not the k different element.
Example 1:
input: [3,2,1,5,6,4] and k = 2 output: 5
Example 2:
input: [3,2,3,1,2,4,5,5,6] and k = 4 output: 4
explain:
You can assume that k is always valid and 1 ≤ k ≤ the length of the array.
Solution:
It's a quick platoon. Look for nums Length - k elements.
class Solution { Random random = new Random(); public int findKthLargest(int[] nums, int k) { int left = 0; int right = nums.length - 1; int target = nums.length - k; while(true) { int index = partition(nums, left, right); if(index < target) { left = index + 1; }else if(index > target) { right = index - 1; }else { return nums[index]; } } } public int partition(int nums[], int left, int right) { if(right > left) { int randomIndex = left + random.nextInt(right - left + 1); swap(nums, left, randomIndex); } int pivot = nums[left]; int j = left; //[0,j] < pivot; for(int i = left + 1; i <= right; i++) { if(nums[i] < pivot) { j++; swap(nums, j, i); } } swap(nums, j, left); return j; } public void swap(int nums[], int a, int b) { int temp = nums[a]; nums[a] = nums[b]; nums[b] = temp; } }
167. Sum of two II - input ordered array
Given an integer array numbers arranged in ascending order, please find two numbers from the array. The sum of the two numbers is equal to the target number target.
The function should return the subscript value * of these two numbers as an array of integers of length 2* The subscript of numbers starts counting from 1, so the answer array should meet 1 < = answer [0] < answer [1] < = numbers length .
You can assume that each input only corresponds to a unique answer, and you can't reuse the same elements.
Example 1:
Input: numbers = [2,7,11,15], target = 9 Output:[1,2] Explanation: the sum of 2 and 7 is equal to the target number 9. therefore index1 = 1, index2 = 2 .
Example 2:
Input: numbers = [2,3,4], target = 6 Output:[1,3]
Example 3:
Input: numbers = [-1,0], target = -1 Output:[1,2]
Tips:
- 2 <= numbers.length <= 3 * 104
- -1000 <= numbers[i] <= 1000
- numbers are arranged in ascending order
- -1000 <= target <= 1000
- Only one valid answer exists
Solution:
Because the array is ordered, you only need to move the double pointer to the middle to search.
class Solution { public int[] twoSum(int[] numbers, int target) { int left = 0; int right = numbers.length - 1; while(left < right) { int sum = numbers[left] + numbers[right]; if(sum < target) { left++; }else if(sum > target) { right--; }else { return new int[] {left + 1, right + 1}; } } return new int[] {0, 0}; } }
125. Validate palindrome string
Given a string, verify whether it is a palindrome string. Only alphanumeric characters are considered, and the case of letters can be ignored.
**Note: * * in this question, we define an empty string as a valid palindrome string.
Example 1:
input: "A man, a plan, a canal: Panama" output: true
Example 2:
input: "race a car" output: false
Double pointer traversal. If a non space array is encountered, it will be skipped.
class Solution { public boolean isPalindrome(String s) { int left = 0; int right = s.length() - 1; while(left < right) { while(left < right && !Character.isLetterOrDigit(s.charAt(left))) ++left; while(left < right && !Character.isLetterOrDigit(s.charAt(right))) --right; if(left < right) { if(Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))) return false; ++left; --right; } } return true; } }
345. Invert the vowels in the string
Write a function that takes a string as input and inverts the vowels in the string.
Example 1:
Input:"hello" Output:"holle"
Example 2:
Input:"leetcode" Output:"leotcede"
Tips:
- The vowel does not contain the letter "y".
Same as double pointer
class Solution { public String reverseVowels(String s) { List list = new ArrayList(); list.add('a'); list.add('e'); list.add('i'); list.add('o'); list.add('u'); list.add('A'); list.add('E'); list.add('I'); list.add('O'); list.add('U'); StringBuilder str = new StringBuilder(s); int left = 0; int right = str.length() - 1; while(left < right) { while(left < right && !list.contains(str.charAt(left))) left++; while(left < right && !list.contains(str.charAt(right))) right--; if(left < right) { char c = str.charAt(left); str.setCharAt(left, str.charAt(right)); str.setCharAt(right, c); left++; right--; } } return str.toString(); } }
11. Container containing the most water
Give you n nonnegative integers a1, a2, a``n, each number represents a point (i, ai) in the coordinate. Draw n vertical lines in the coordinates. The two endpoints of the vertical line i are (i, ai) and (i, 0). Find the two lines so that the container formed by them and the x-axis can hold the most water.
**Note: * * you cannot tilt the container.
Example 1:
Input:[1,8,6,2,5,4,8,3,7] Output: 49 Explanation: the vertical line in the figure represents the input array [1,8,6,2,5,4,8,3,7]. In this case, the maximum value that the container can hold water (represented by the blue part) is 49.
Example 2:
Input: height = [1,1] Output: 1
Example 3:
Input: height = [4,3,2,1,4] Output: 16
Example 4:
Input: height = [1,2,1] Output: 2
Tips:
- n = height.length
- 2 <= n <= 3 * 104
- 0 <= height[i] <= 3 * 104
Solution:
Double pointer, calculate the current area and compare sum;
The problem of pointer movement: because the pointer moves inward, the length of the bottom will become smaller, so we have to move the shorter straight line inward and try to find a higher one, so that the area can become larger.
class Solution { public int maxArea(int[] height) { int left = 0; int right = height.length - 1; int sum = 0; while(left < right) { int temp = Math.min(height[left], height[right]) * (right - left); if(temp > sum) sum = temp; if(height[left] < height[right]) { left++; }else { right--; } } return sum; } }
209. Minimum length subarray
Given an array containing n positive integers and a positive integer target.
Find out the continuous sub array [numsl, numsl + 1,..., numsr-1, numsr] with the smallest length satisfying its sum ≥ target in the array, and return its length * *** If there is no eligible subarray, 0 is returned.
Example 1:
Input: target = 7, nums = [2,3,1,2,4,3] Output: 2 Explanation: subarray [4,3] Is the subarray with the smallest length under this condition.
Example 2:
Input: target = 4, nums = [1,4,4] Output: 1
Example 3:
Input: target = 11, nums = [1,1,1,1,1,1,1,1] Output: 0
Tips:
- 1 <= target <= 109
- 1 <= nums.length <= 105
- 1 <= nums[i] <= 105
Advanced:
- If you have implemented the solution of O(n) time complexity, please try to design a solution of O(n log(n)) time complexity.
Solution:
Use the sliding window to solve problems, define left and right, and maintain a window with > = target.
class Solution { public int minSubArrayLen(int target, int[] nums) { // Define a sliding window int left = 0; int right = 0; int n = nums.length; int sum = 0; int len = 100001; while(right < n){ sum += nums[right]; right++; while(sum >= target){ if(right - left < len){ len = right - left; } sum -= nums[left]; left ++; } } if(len == 100001) return 0; return len; } }
3. Longest substring without repeated characters
Given a string, please find the length of the longest substring that does not contain duplicate characters.
Example 1:
input: s = "abcabcbb" output: 3 explain: Because the longest substring without duplicate characters is "abc",So its length is 3.
Example 2:
input: s = "bbbbb" output: 1 explain: Because the longest substring without duplicate characters is "b",So its length is 1.
Example 3:
input: s = "pwwkew" output: 3 explain: Because the longest substring without duplicate characters is "wke",So its length is 3. Please note that your answer must be the length of the substring,"pwke" It's a subsequence, not a substring.
Example 4:
input: s = "" output: 0
Tips:
- 0 <= s.length <= 5 * 104
- s consists of English letters, numbers, symbols and spaces
class Solution { public int lengthOfLongestSubstring(String s) { int sLen = s.length(); if(sLen == 0) return 0; Map<Character, Integer> cur = new HashMap<>(); // Define sliding window int left = 0; int right = 0; int len = -1; while(right < sLen){ char c = s.charAt(right); if(cur.containsKey(c)){ // Special circumstances: e.g. abba left = Math.max(left, cur.get(c) + 1); } cur.put(c, right); len = Math.max(len, right - left + 1); right ++; } return len; } }
438. Find all letter words in the string
Given a string s and a non empty string P, find all the substrings of letter ectopic words in s that are p, and return the starting indexes of these substrings.
The string contains only lowercase English letters, and the length of strings s and p does not exceed 20100.
explain:
- Alphabetic words refer to strings with the same letters but arranged differently.
- The order in which answers are output is not considered.
Example 1:
input: s: "cbaebabacd" p: "abc" output: [0, 6] explain: The substring with the starting index equal to 0 is "cba", It is "abc" Letter ectopic words. The substring with a starting index equal to 6 is "bac", It is "abc" Letter ectopic words.
Example 2:
input: s: "abab" p: "ab" output: [0, 1, 2] explain: The substring with the starting index equal to 0 is "ab", It is "ab" Letter ectopic words. The substring with the starting index equal to 1 is "ba", It is "ab" Letter ectopic words. The substring with the starting index equal to 2 is "ab", It is "ab" Letter ectopic words.
Problem solution: this problem is consistent with the solution of the following problem.
- The idea of this problem is to slide the window, because we want to judge whether the number of elements meets the requirements and can store them in map. So how to judge whether all the elements we want are complete? You can use an int variable to record.
- Two pointers of the window. When the elements in the window meet the needs, move the left pointer to remove the first relevant element on the left of the window. Then continue to move the right pointer to try to find the smallest window containing all elements.
class Solution { public List<Integer> findAnagrams(String s, String p) { Map<Character,Integer> need = new HashMap<>(); Map<Character,Integer> windows = new HashMap<>(); List<Integer> list = new ArrayList<>(); if(s.length() < p.length()) return new ArrayList<>(); for(int i = 0; i < p.length(); i++){ char c = p.charAt(i); need.put(c, need.getOrDefault(c,0)+ 1); } int left = 0; //[0,0) int right = 0; int valid = 0; while(right < s.length()){ char c = s.charAt(right); right++; if(need.containsKey(c)){ windows.put(c, windows.getOrDefault(c, 0) + 1); if(need.get(c).intValue() == windows.get(c).intValue()) valid ++; } while(right - left == p.length()){ if(valid == need.size()) { list.add(left); } char cc = s.charAt(left); left ++; if(need.containsKey(cc)){ if(need.get(cc).intValue() == windows.get(cc).intValue()) valid --; windows.put(cc, windows.get(cc) - 1); } } } return list; } }
76. Minimum coverage substring
Give you a string s and a string t. Returns the smallest substring of s covering t all characters. If there is no substring covering t all characters in s, the empty string "" is returned.
**Note: * * if there is such a substring in s, we guarantee that it is the only answer.
Example 1:
Input: s = "ADOBECODEBANC", t = "ABC" Output:"BANC"
Example 2:
Input: s = "a", t = "a" Output:"a"
Tips:
- 1 <= s.length, t.length <= 105
- s and t consist of English letters
Solution:
- The idea of this problem is to slide the window, because we need to judge whether the number of certain elements meets the requirements and can use map to store them. So how to judge whether all the elements we want are complete? You can use an int variable to record.
- Two pointers of the window. When the elements in the window meet the needs, move the left pointer to remove the first relevant element on the left of the window. Then continue to move the right pointer to try to find the smallest window containing all elements.
class Solution { public String minWindow(String s, String t) { Map<Character, Integer> need = new HashMap<>(); Map<Character, Integer> windows = new HashMap<>(); int tLen = t.length(); int sLen = s.length(); if(tLen == 0 || sLen == 0) return ""; for(int i = 0; i < tLen; i++){ char c = t.charAt(i); need.put(c, need.getOrDefault(c, 0) + 1); } // Define window left and right pointers int left = 0; int right = 0; int len = Integer.MAX_VALUE; // How to judge that we have all the elements we want, use a variable to record int valid = 0; // To intercept a segment, record the starting position with a variable int start = 0; while(right < sLen){ char c = s.charAt(right); right ++; if(need.containsKey(c)){ windows.put(c, windows.getOrDefault(c, 0) + 1); if(windows.get(c).intValue() == need.get(c).intValue()){ valid ++; } } while(valid == need.size()){ if(right - left < len){ start = left; len = right - left; } char cc = s.charAt(left); left++; if(need.containsKey(cc)){ if(need.get(cc).intValue() == windows.get(cc).intValue()){ valid --; } windows.put(cc, windows.get(cc) - 1); } } } return len == Integer.MAX_VALUE ? "" : s.substring(start, start + len); } }