This is the 26th day of my participation in the Novembermore Challenge.The final text challenge in 2021
Some of the problems in the LeetCode problem set may have been skipped directly, so clean up the previous brush with LeetCode
211. Add and search words – Data structure design
Design a data structure that supports the following two operations:
void addWord(word)
bool search(word)
Copy the code
Search (word) searches for literal or regular expression strings that contain only letters. Or a – z. . Can represent any letter.
Example:
addWord("bad") addWord("dad") addWord("mad") search("pad") -> false search("bad") -> true search(".ad") -> true search("b.." ) -> trueCopy the code
Description:
You can assume that all words are made up of lowercase letters a-z.
class WordDictionary {
Map<Integer,Set<String>> map = new HashMap<>();// Store them separately according to the length of the string
public WordDictionary(a) {}public void addWord(String word) {
int length = word.length();
if(map.get(length)! =null){
map.get(length).add(word);
}else{
Set<String> set = newHashSet<>(); set.add(word); map.put(length, set); }}public boolean search(String word) {
Set<String> set = map.get(word.length());
if(set==null) {// No string of this length exists, return false;
return false;
}
if(set.contains(word)) return true;
char[] chars = word.toCharArray();
P:for(String s : set){
if(word.length()! =s.length()){continue;
}
char[] cs = s.toCharArray();
for(int i = 0; i< cs.length; i++){// Character-by-character comparison
if(chars[i] ! ='. '&& chars[i] ! = cs[i]){continue P;
}
}
set.add(word);
return true;
}
return false; }}/** * Your WordDictionary object will be instantiated and called as such: * WordDictionary obj = new WordDictionary(); * obj.addWord(word); * boolean param_2 = obj.search(word); * /
Copy the code
212. Word Search II
Given a two-dimensional grid board and a list of words in a dictionary, find all the words that appear in both the two-dimensional grid and the dictionary.
Words must be formed in alphabetical order by letters in adjacent cells, where “adjacent” cells are those that are horizontally or vertically adjacent. Letters in the same cell are not allowed to be used twice in a word.
Example:
Input:
words = ["oath","pea","eat","rain"] and board =
[
['o','a','a','n'],
['e','t','a','e'],
['i','h','k','r'],
['i','f','l','v']
]
Copy the code
Output: [“eat”,”oath”] Note: You can assume that all input consists of lowercase letters A-Z.
Tip:
You need to optimize the backtracking algorithm to pass larger data tests. Could you stop backtracking earlier? If the current word does not exist in all word prefixes, you can stop backtracking immediately. What data structures can effectively perform such operations? Do hash tables work? Why is that? How about a prefix tree? If you want to learn how to implement a basic prefix tree, look at this problem first: Implement Trie (prefix tree).
First build a dictionary tree, and then add a dictionary tree during DFS, and things that end with a certain string reduce the number of searches why don't you use the beginning and the end here, '(● strap ●) the end is just, I'm done searching one, I can compare it directly, and if it isn't, I return the last one,Copy the code
class TrieNode {
private static final int ALPHABET_SIZE = 26;
TrieNode[] children = new TrieNode[ALPHABET_SIZE];
// Determine if the prefix is the end of a string
boolean isEndOfWord = false;
TrieNode() {
isEndOfWord = false;
for (int i = 0; i < ALPHABET_SIZE; i++)
children[i] = null; }}class Trie {
public TrieNode root;
/** Initialize your data structure here. */
public Trie(a) {
root = new TrieNode();
}
/** Inserts a word into the trie. */
public void insert(String word) {
TrieNode curNode = root;
int index;
for (int i = 0; i < word.length(); i++) {
index = word.charAt(i) - 'a';
if (curNode.children[index] == null) {
curNode.children[index] = new TrieNode();
}
curNode = curNode.children[index];
}
curNode.isEndOfWord = true; }}class Solution {
public List<String> findWords(char[][] board, String[] words) {
List<String> result = new ArrayList<>();
if (words == null || words.length == 0 || board == null || board.length == 0 || board[0].length == 0)
return result;
Trie trie = new Trie();
for (String temp : words)
trie.insert(temp);
TrieNode root = trie.root;
boolean[][] visited = new boolean[board.length][board[0].length];
Set<String> tempResult = new HashSet<>();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (root.children[board[i][j] - 'a'] != null ) {
dfs(board, visited, i, j, root.children[board[i][j] - 'a'], tempResult, sb); }}}// We need to copy the tempResult set to the actual result List
Iterator<String> iterator = tempResult.iterator();
while (iterator.hasNext()) {
result.add(iterator.next());
}
return result;
}
private void dfs(char[][] board, boolean[][] visited, int startIInBoard, int startJInBoard
, TrieNode curNode, Set<String> resultSet, StringBuilder curStrBuilder) {
curStrBuilder.append(board[startIInBoard][startJInBoard]);
visited[startIInBoard][startJInBoard] = true;
if (curNode.isEndOfWord) {
resultSet.add(curStrBuilder.toString());
}
// Search up, if the above grid has not been searched
if (startIInBoard > 0 && !visited[startIInBoard - 1][startJInBoard]
&& curNode.children[board[startIInBoard - 1][startJInBoard] - 'a'] != null) {
dfs(board, visited,startIInBoard - 1, startJInBoard
, curNode.children[board[startIInBoard - 1][startJInBoard] - 'a'], resultSet, curStrBuilder);
}
// Search down
if (startIInBoard < board.length - 1 && !visited[startIInBoard + 1][startJInBoard]
&& curNode.children[board[startIInBoard + 1][startJInBoard] - 'a'] != null) {
dfs(board, visited,startIInBoard + 1, startJInBoard
, curNode.children[board[startIInBoard + 1][startJInBoard] - 'a'], resultSet, curStrBuilder);
}
// Search left
if (startJInBoard > 0 && !visited[startIInBoard][startJInBoard - 1]
&& curNode.children[board[startIInBoard][startJInBoard - 1] - 'a'] != null) {
dfs(board, visited, startIInBoard, startJInBoard - 1
, curNode.children[board[startIInBoard][startJInBoard - 1] - 'a'], resultSet, curStrBuilder);
}
// Search right
if (startJInBoard < board[0].length - 1 && !visited[startIInBoard][startJInBoard + 1]
&& curNode.children[board[startIInBoard][startJInBoard + 1] - 'a'] != null) {
dfs(board, visited, startIInBoard, startJInBoard + 1
, curNode.children[board[startIInBoard][startJInBoard + 1] - 'a'], resultSet, curStrBuilder);
}
// Restore the scene
curStrBuilder.setLength(curStrBuilder.length() - 1);
visited[startIInBoard][startJInBoard] = false; }}Copy the code
214. The shortest palindrome string
Given a string s, you can convert it to a palindrome string by preadding characters to the string. Find and return the shortest palindrome string that can be converted in this way.
Example 1:
Input: “aacecAAA” Output: “aaACecAAA” Example 2:
Input: abcd Output: dcbabcd
class Solution {
public static String shortestPalindrome(String s) {
StringBuilder r = new StringBuilder(s).reverse();
String str = s + "#" + r;
int[] next = next(str);
// If it is a palindrome string 1234321 # 1234321
//next[str.length]=7,r.substring(0,0)="
// If 123432 # 234321 next[str.length]=5
//r.substring(0,6-5), just the first digit
String prefix = r.substring(0, r.length() - next[str.length()]);
return prefix + s;
}
/ / next array
// next[j]=x; // next[j]=x
// Maybe so
private static int[] next(String P) {
int[] next = new int[P.length() + 1];
next[0] = -1;
int k = -1;
int i = 1;
//next [k] saves the last time I was equal
// If I am not equal, I will match it from the last time I was equal
// I is a fast pointer, k is a slow pointer
while (i < next.length) {
if (k == -1 || P.charAt(k) == P.charAt(i - 1)) {
next[i++] = ++k;
} else{ k = next[k]; }}returnnext; }}Copy the code
215. The KTH largest element in an array
Finds the KTH largest element in the unsorted array. Note that you need to find the KTH largest element of the sorted array, not the KTH distinct 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
You can assume that k is always valid, and that 1 ≤ k ≤ the length of the array.
class Solution {
public int findKthLargest(int[] nums, int k) {
if(nums.length < 2) {return nums.length == 1 ? nums[0] : -1;
}
return countingSort(nums, k);
}
private int countingSort(int[] nums, int k){
int max = 0;
int min = 0;
for(int i = 0; i < nums.length; i++){
if(nums[i] > max){
max = nums[i];
}
if(nums[i] < min){ min = nums[i]; }}int length = (max - min) + 1;
int[] newArray = new int[length];
// This array records the number of persons that are different from the minimum value
for(int i = 0; i < nums.length; i++){
newArray[nums[i] - min]++;
}
int j = 0;
for(int i = newArray.length - 1; i >= 0; i--){
// Start with the maximum value
if(newArray[i] > 0){
j = newArray[i] + j;
if(j >= k){
returni + min; }}}return -1; }}Copy the code
216. Sum of combinations III
Find all the combinations of k numbers that add up to n. Only positive integers from 1 to 9 are allowed in a combination, and there are no duplicate digits in each combination.
Description:
All numbers are positive integers. The solution set cannot contain repeated combinations. Example 1:
Input: k = 3, n = 7 output: [[1,2,4]] example 2:
Input: k = 3, n = 9 output: [[1,2,6], [1,3,5], [2,3,4]]
class Solution {
/ / the result set
public List<List<Integer>> lists = new ArrayList<>();
/ / temporary set
public List<Integer> list = new ArrayList<>();
public List<List<Integer>> combinationSum3(int k, int n) {
// Backtrace the entry
backTracking(list, 0.1, k, n, 0);
return lists;
}
public void backTracking(List<Integer> list, int index, int c, int k, int n, int sum){
// Backtrace export
// Make sure it is the sum of k numbers, and, and are the specified values
if(index == k && sum == n){
// satisfy the add join set
List<Integer> currentList = new ArrayList<>();
currentList.addAll(list);
lists.add(currentList);
return;
}
// Prune
if(sum > n){
return;
}
// Traceback conditions
for(int i = c; i <= 9; ++i){
list.add(i);
sum += i;
backTracking(list, index + 1, i + 1, k, n, sum);
list.remove(list.size() - 1); sum -= i; }}}Copy the code
217. There are duplicate elements
Given an array of integers, determine whether there are duplicate elements.
The function returns true if any value appears in the array at least twice. Return false if each element in the array is different.
Example 1:
Input: [1,2,3,1] output: true example 2:
Input: [1,2,3,4] output: false
Input: [1,1,1,3,3,4,3,2,4,2] output: true
Set does not hold the contents of the same element, returns false if the same element is added, and is not addedCopy the code
class Solution {
public boolean containsDuplicate(int[] nums) {
Set<Integer> res = new HashSet<Integer>();
for(int i:nums)
res.add(i);
return res.size()<nums.length?true:false; }}Copy the code
218. Skyline problem
The skyline of a city is the outer outline of all the buildings in the city as viewed from a distance. Now, assuming you have the positions and heights of all the buildings shown on the cityscape photo (Figure A), write A program to output the skyline formed by those buildings (Figure B).
Buildings Skyline Contour
The geometric information of each building is represented by a triplet [Li, Ri, Hi], where Li and Ri are the X coordinates of the left and right edges of the ith building, and Hi is its height. 0 ≤ Li, Ri ≤ INT_MAX, 0 < Hi ≤ INT_MAX and Ri-Li > 0 can be guaranteed. You can assume that all buildings are perfect rectangles on absolutely flat surfaces of zero height.
For example, the dimensions of all buildings in Figure A are recorded as follows: [[2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8]].
Output is [[x1,y1], [x2, y2], [x3, y3]… A list of “key points” (red dots in Figure B) of the format that uniquely define the skyline. The key point is the left end of the horizontal segment. Note that the last key point of the building on the far right is only used to mark the end of the skyline and is always zero height. In addition, the ground between any two adjacent buildings should be considered part of the skyline profile.
For example, the skyline in Figure B should be expressed as: [[2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0]].
Description:
The number of buildings in any input list is guaranteed to be within [0, 10000]. The input list is already arranged in ascending order by the left x coordinate Li. The output list must be sorted by x bits. There shall be no consecutive horizontal lines of the same height in the output skyline. For example, […[2 3], [4 5], [7 5], [11 5], [12 7]… Is the wrong answer; Three height is 5 lines should be in the final output into a: [… [2, 3], [4, 5], [7],…
class Solution {
/ / segment tree
public List<List<Integer>> getSkyline(int[][] buildings) {
int len = buildings.length;
if (len == 0) return new ArrayList<>();
return segment(buildings, 0, len - 1);
}
private List<List<Integer>> segment(int[][] buildings, int l, int r) {
// Create the return value
List<List<Integer>> res = new ArrayList<>();
// Find the end condition under the tree -> a building
if (l == r) {
res.add(Arrays.asList(buildings[l][0], buildings[l][2])); // Top left coordinate
res.add(Arrays.asList(buildings[l][1].0)); // Lower right coordinates
return res;
}
int mid = l + (r - l) / 2; // take the middle value
// The left side recurses
List<List<Integer>> left = segment(buildings, l, mid);
// The right side recurses
List<List<Integer>> right = segment(buildings, mid + 1, r);
// Merge left and right
// Create left and right index positions
int m = 0, n = 0;
// Create the current height of left and right
int lpreH = 0, rpreH = 0;
// Two coordinates
int leftX, leftY, rightX, rightY;
while (m < left.size() || n < right.size()) {
// When one side is fully added to the RES, the remaining part is added
if (m >= left.size()) res.add(right.get(n++));
else if (n >= right.size()) res.add(left.get(m++));
else { // Start judging left and right
leftX = left.get(m).get(0); // Null will not appear, can be used directly int
leftY = left.get(m).get(1);
rightX = right.get(n).get(0);
rightY = right.get(n).get(1);
// See which of my two rectangles is on the left
if (leftX < rightX) {
// If the left side is still higher than before, add left side
if (leftY > rpreH) res.add(left.get(m));
// the left side is higher than the right side. I'm going to add the left side and the previous right side because I'm going to have a new height 2,10
else if (lpreH > rpreH) res.add(Arrays.asList(leftX, rpreH));
// Replace the height on my left with the height on my right
lpreH = leftY;
m++;
} else if (leftX > rightX) {
if (rightY > lpreH) res.add(right.get(n));
else if (rpreH > lpreH) res.add(Arrays.asList(rightX, lpreH));
rpreH = rightY;
n++;
} else { // Left and right are equal
if(leftY >= rightY && leftY ! = (lpreH > rpreH ? lpreH : rpreH)) res.add(left.get(m));else if(leftY <= rightY && rightY ! = (lpreH > rpreH ? lpreH : rpreH)) res.add(right.get(n)); lpreH = leftY; rpreH = rightY; m++; n++; }}}returnres; }}Copy the code
219. Repeated element II is present
Given an integer array and an integer k, determine whether there are two different indexes I and j in the array such that nums [I] = nums [j] and the absolute value of the difference between I and j is at most K.
Example 1:
Input: nums = [1,2,3,1], k = 3 output: true example 2:
Input: nums = [1,0,1,1], k = 1 Output: true Example 3:
Input: nums = [1,2,3,1,2,3], k = 2 output: false
The sliding windowCopy the code
class Solution {
public boolean containsNearbyDuplicate(int[] nums, int k) {
Set<Integer> set = new HashSet<>();
for (int i = 0; i < nums.length; i++) {
if(set.contains(nums[i])){
return true;
}
set.add(nums[i]);
if(set.size() == k+1){ set.remove(nums[i - k]); }}return false; }}Copy the code
220. Presence of repeated element III
Given an integer array, judge whether there are two different indexes I and J in array such that the absolute values of the difference between NUMs [I] and nums [j] are maximum k, and the absolute values of the difference between I and J are maximum K.
Example 1:
Input: nums = [1,2,3,1], k = 3, t = 0
Input: nums = [1,0,1,1], k = 1, t = 2
Input: nums = [1,5,9,1,5,9], k = 2, t = 3 output: false
class Solution {
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t) {
// The slider window is the lookup table itself (control the size of the lookup table).
TreeSet<Long> set = new TreeSet<>();
for (int i = 0; i < nums.length; i++) {
// add and find
If nums[I] -t is greater than nums[I] -t and less than nums[I] + t
Long ceiling = set.ceiling((long) nums[i] - (long) t);
if(ceiling ! =null && ceiling <= ((long) nums[i] + (long) t)) {
return true;
}
// Control the size of the lookup table (window) and remove the left-most element of the window
set.add((long) nums[i]);
if (set.size() == k + 1) {
set.remove((long) nums[i - k]); }}return false; }}Copy the code