Hashtable second 50
957. Prison Cells After N Days If a cell has two adjacent neighbors that are both occupied or both vacant, then the cell becomes occupied. Otherwise, it becomes vacant. Input: cells = [0,1,0,1,1,0,0,1], N = 7 Output: [0,0,1,1,0,0,0,0]
after n rounds, the cell status will repeat. we use map<cell, ind> and map<ind, cell> to record the status and index. class Solution { public: vector<int> prisonAfterNDays(vector<int>& cells, int N) { map<int, vector<int>> dayMap; map<vector<int>, int> indMap; dayMap[0] = cells; indMap[cells] = 0; vector<int> prev = cells; int round = -1; for(int i = 1; i<= N; i ++) { vector<int> next(8); for(int j = 1; j < 7; j ++) { if((prev[j-1] == 1) ^ (prev[j+1] == 1) == 0) next[j] = 1; } if(indMap.find(next) != indMap.end()) { int start = indMap[next]; round = i - start; return dayMap[start + (N - start) % round]; } dayMap[i] = next; indMap[next] = i; prev = next; } return prev; } };
760. Find Anagram Mappings Given two lists Aand B, and B is an anagram of A. B is an anagram of A means B is made by randomizing the order of the elements in A. We want to find an index mapping P, from A to B. A mapping P[i] = j means the ith element in A appears in B at index j. [12,28,46,32,50] [50,12,32,46,28]
as there may be duplicates, we use pair(num, count) as key of map. class Solution { public: vector<int> anagramMappings(vector<int>& A, vector<int>& B) { map<pair<int,int>, int> indMap; unordered_map<int, int> counts; for(int i = 0; i < B.size(); i ++) { counts[B[i]] ++; indMap[pair(B[i], counts[B[i]])] = i; } counts.clear(); vector<int> res(A.size()); for(int i = 0; i< A.size(); i ++) { counts[A[i]] ++; res[i] = indMap[pair(A[i], counts[A[i]])]; } return res; } };
930. Binary Subarrays With Sum In an array A of 0s and 1s, how many non-empty subarrays have sum S? Input: A = [1,0,1,0,1], S = 2 Output: 4
class Solution { public: int numSubarraysWithSum(vector<int>& A, int S) { int sum = 0; int res = 0; unordered_map<int, int> counts; counts[0] = 1; for(auto& num: A) { sum += num; res += counts[sum - S]; counts[sum] ++; } return res; } };
575. Distribute Candies Given an integer array with even length, where different numbers in this array represent different kinds of candies. Each number means one candy of the corresponding kind. You need to distribute these candies equally in number to brother and sister. Return the maximum number of kinds of candies the sister could gain. Input: candies = [1,1,2,2,3,3] Output: 3
each person can get size /2 candies, if kinds of candies > size / 2, answer is size/2, else answer is map size. class Solution { public: int distributeCandies(vector<int>& candies) { int size = candies.size(); unordered_map<int,int> counts; for(auto& num: candies) counts[num] ++; if(counts.size() > size / 2) return size / 2; else return counts.size(); } };
711. Number of Distinct Islands II Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water. Count the number of distinct islands. An island is considered to be the same as another if they have the same shape, or have the same shape after rotation (90, 180, or 270 degrees only) or reflection (left/right direction or up/down direction).
for each island found by dfs, we get the transformed string in 8 directions. class Solution { private: int rows; int cols; vector< vector<int> > delta = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; public: int numDistinctIslands2(vector<vector<int>>& grid) { rows = grid.size(); if(rows == 0) return 0; cols = grid[0].size(); set<string> strSet; vector<vector<bool>> visited(rows, vector<bool>(cols,false)); for(int r = 0; r < rows; r ++) { for(int c = 0; c < cols; c ++) { if(!visited[r][c] && grid[r][c] == 1) { vector<vector<int>> island; dfs(r, c, grid, visited, island); string translated = translate(island); strSet.insert(translated); } } } return strSet.size(); } string translate(vector<vector<int>>& island) { int size = island.size(); vector<int> xs(size); vector<int> ys(size); int factor = rows + cols; vector<int> out(size); string res = ""; for(int dir = 0; dir < 8; dir ++) { int xmin = INT_MAX; int ymin = INT_MAX; for(int i = 0; i < size; i ++) { // x y, x -y, -x y, -x -y, y x, y -x, -y x, -y -x int r = island[i][0]; int c = island[i][1]; xs[i] = dir <= 1? r: (dir <= 3? -r: (dir <= 5? c: -c)); ys[i] = dir <= 3? (dir % 2 == 0? c: -c): (dir % 2 == 0? r: -r); xmin = min(xmin, xs[i]); ymin = min(ymin, ys[i]); } for(int i = 0; i < size; i ++) { out[i] = (xs[i] - xmin) * factor + (ys[i] - ymin); } sort(out.begin(), out.end()); string curr = ""; for(auto& num: out) curr += to_string(num); if(res < curr) res = curr; } return res; } void dfs(int row, int col, vector<vector<int>>& grid, vector<vector<bool>>& visited, vector<vector<int>>& island) { island.push_back({row, col}); visited[row][col] = true; for(auto& arr: delta) { int x = row + arr[0]; int y = col + arr[1]; if(x >= 0 && x < rows && y >= 0 && y < cols && !visited[x][y] && grid[x][y] == 1) { dfs(x, y, grid, visited, island); } } } };
645. Set Mismatch The set S originally contains numbers from 1 to n. But unfortunately, due to the data error, one of the numbers in the set got duplicated to another number in the set, which results in repetition of one number and loss of another number. Input: nums = [1,2,2,4] Output: [2,3]
record the counts. class Solution { public: vector<int> findErrorNums(vector<int>& nums) { int n = nums.size(); unordered_map<int,int> counts; vector<int> res(2); for(auto& num: nums) counts[num] ++; for(int i = 1; i <= n; i ++) { if(counts[i] == 0) res[1] = i; if(counts[i] == 2) res[0] = i; } return res; } };
954. Array of Doubled Pairs Given an array of integers A with even length, return true if and only if it is possible to reorder it such that A[2 * i + 1] = 2 * A[2 * i] for every 0 <= i < len(A) / 2. Input: [4,-2,2,-4] Output: true
the rule is: A[1] = 2 * A[0], A[3] = 2 * A[2].... so we need to find how many double pairs. struct comparer { bool operator() (const int v1, const int v2) const { return abs(v1) < abs(v2); } }; class Solution { public: bool canReorderDoubled(vector<int>& A) { map<int, int, comparer> counts; for(auto& num: A) counts[num] ++; int size = A.size(); int pair = 0; for(auto& [num, cnt]: counts) { if(num == 0) { pair += (cnt / 2); } else { if(counts.find(num * 2) != counts.end()) { int minCnt = min(cnt, counts[num * 2]); pair += minCnt; cnt -= minCnt; counts[num * 2] -= minCnt; } } } return pair == size / 2; } };
734. Sentence Similarity Given two sentences words1, words2 (each represented as an array of strings), and a list of similar word pairs pairs, determine if two sentences are similar. For example, "great acting skills" and "fine drama talent" are similar, if the similar word pairs are pairs = [["great", "fine"], ["acting","drama"], ["skills","talent"]]. Note that the similarity relation is not transitive. For example, if "great" and "fine" are similar, and "fine" and "good" are similar, "great" and "good" are not necessarily similar.
the similarity relation is not transitive, so we can use map to record the pair relation. if it's transitive, we use union find to do. class Solution { public: bool areSentencesSimilar(vector<string>& words1, vector<string>& words2, vector<vector<string>>& pairs) { unordered_map<string, unordered_set<string>> simMap; for(auto& arr: pairs) { simMap[arr[0]].insert(arr[1]); simMap[arr[1]].insert(arr[0]); } int size1 = words1.size(); int size2 = words2.size(); if(size1 != size2) return false; for(int i = 0; i < size1; i ++) { string s1 = words1[i]; string s2 = words2[i]; if(s1 == s2) continue; if(simMap[s1].find(s2) == simMap[s1].end()) return false; } return true; } };
966. Vowel Spellchecker For a given query word, the spell checker handles two categories of spelling mistakes: Capitalization: If the query matches a word in the wordlist (case-insensitive), then the query word is returned with the same case as the case in the wordlist. Example: wordlist = ["yellow"], query = "YellOw": correct = "yellow" Example: wordlist = ["Yellow"], query = "yellow": correct = "Yellow" Example: wordlist = ["yellow"], query = "yellow": correct = "yellow" Vowel Errors: If after replacing the vowels ('a', 'e', 'i', 'o', 'u') of the query word with any vowel individually, it matches a word in the wordlist (case-insensitive), then the query word is returned with the same case as the match in the wordlist. Example: wordlist = ["YellOw"], query = "yollow": correct = "YellOw" Example: wordlist = ["YellOw"], query = "yeellow": correct = "" (no match) Example: wordlist = ["YellOw"], query = "yllw": correct = "" (no match) ["KiTe","kite","hare","Hare"] ["kite","Kite","KiTe","Hare","HARE","Hear","hear","keti","keet","keto"]
there are three rules: 1. if word itself is found, append word. 2. if ignore case, word is found, append min ind word. 3. if update vowel and word is found, append min ind. class Solution { private: set<char> vowels = {'a', 'e', 'i', 'o', 'u'}; public: vector<string> spellchecker(vector<string>& wordlist, vector<string>& queries) { unordered_map<string, set<int>> dict; unordered_set<string> words; unordered_map<string, set<int>> match; for(int i = 0; i< wordlist.size(); i ++) { string str = wordlist[i]; words.insert(str); string tmp; string matched; for(auto& ch: str) { tmp += tolower(ch); if(isvowel(tolower(ch))) matched +='#'; else matched += tolower(ch); } match[matched].insert(i); dict[tmp].insert(i); } vector<string> res; for(auto& str: queries) { string tmp; bool found = false; for(auto& ch: str) tmp += tolower(ch); if(words.find(str) != words.end()) { found = true; res.push_back(str); } else if(dict.find(tmp) != dict.end()) { int idx = *dict[tmp].begin(); res.push_back(wordlist[idx]); found = true; } else { set<int> inds; string updated; for(int i = 0; i < tmp.length(); i ++) { if(isvowel(tmp[i])) { updated += '#'; } else updated += tmp[i]; } if(match.find(updated) != match.end()) inds.insert(*match[updated].begin()); if(inds.size() > 0) { res.push_back(wordlist[*inds.begin()]); found = true; } } if(!found) res.push_back(""); } return res; } bool isvowel(char ch) { return vowels.find(ch) != vowels.end(); } };
884. Uncommon Words from Two Sentences We are given two sentences A and B. (A sentence is a string of space separated words. Each word consists only of lowercase letters.) A word is uncommon if it appears exactly once in one of the sentences, and does not appear in the other sentence. Input: A = "this apple is sweet", B = "this apple is sour" Output: ["sweet","sour"]
use count map. class Solution { public: vector<string> uncommonFromSentences(string A, string B) { unordered_map<string, int> counts1 = getMap(A); unordered_map<string, int> counts2 = getMap(B); vector<string> res; for(auto& [str, cnt]: counts1) { if(cnt == 1 && counts2.find(str) == counts2.end()) res.push_back(str); } for(auto& [str, cnt]: counts2) { if(cnt == 1 && counts1.find(str) == counts1.end()) res.push_back(str); } return res; } unordered_map<string, int> getMap(string s) { unordered_map<string, int> res; int pos = s.find(" "); while(pos != -1) { res[s.substr(0, pos)] ++; s.erase(0, pos+1); pos = s.find(" "); } res[s] ++; return res; } };
771. Jewels and Stones You're given strings J representing the types of stones that are jewels, and S representing the stones you have. Each character in S is a type of stone you have. You want to know how many of the stones you have are also jewels. Input: J = "aA", S = "aAAbbbb" Output: 3
use hash set and hash map class Solution { public: int numJewelsInStones(string J, string S) { unordered_set<char> jewels; for(auto& ch: J) jewels.insert(ch); int res = 0; unordered_map<char, int> counts; for(auto& ch: S) counts[ch] ++; for(auto& [ch, cnt]: counts) if(jewels.find(ch) != jewels.end()) res += cnt; return res; } };
961. N-Repeated Element in Size 2N Array In a array A of size 2N, there are N+1 unique elements, and exactly one of these elements is repeated N times. Input: [1,2,3,3] Output: 3
we can use map to record the counts or set to record visited or not. class Solution { public: int repeatedNTimes(vector<int>& A) { unordered_map<int, int> counts; for(auto& num: A) {counts[num] ++; if(counts[num] == A.size() / 2) return num; } return 0; } };
463. Island Perimeter You are given a map in form of a two-dimensional integer grid where 1 represents land and 0 represents water. Grid cells are connected horizontally/vertically (not diagonally). The grid is completely surrounded by water, and there is exactly one island (i.e., one or more connected land cells). [[0,1,0,0], [1,1,1,0], [0,1,0,0], [1,1,0,0]] Output: 16
we count the number of grid 1 and overlapping edges. class Solution { private: int rows; int cols; vector<vector<int>> delta = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; public: int islandPerimeter(vector<vector<int>>& grid) { rows = grid.size(); if(rows == 0) return 0; cols = grid[0].size(); int count = 0; int overlapping = 0; for(int r = 0; r < rows; r ++) for(int c = 0; c < cols; c ++) { if(grid[r][c] == 1) { count ++; for(auto& arr: delta) { int x = r + arr[0]; int y = c + arr[1]; if(x >= 0 && x < rows && y >= 0 && y < cols && grid[x][y] == 1) overlapping += 2; } } } return count * 4 - overlapping / 2; } };
781. Rabbits in Forest n a forest, each rabbit has some color. Some subset of rabbits (possibly all of them) tell you how many other rabbits have the same color as them. Those answers are placed in an array. Return the minimum number of rabbits that could be in the forest. Input: answers = [1, 1, 2] Output: 5
we first get the count map of the answer array. then if key is 0, add the cnt to result. if cnt > (key + 1) mean even if answer is same, they are different color. class Solution { //different answer means different color public: int numRabbits(vector<int>& answers) { unordered_map<int, int> counts; for(auto& num: answers) counts[num] ++; int res = 0; for(auto& [num, cnt]: counts) { if(num == 0) { res += cnt; continue; } if(cnt > num + 1) { int factor = cnt / (num + 1); res += factor * (num + 1); cnt -= factor * (num + 1); } if(cnt > 0) res += num + 1; } return res; } };
648. Replace Words In English, we have a concept called root, which can be followed by some other words to form another longer word - let's call this word successor. For example, the root an, followed by other, which can form another word another. Now, given a dictionary consisting of many roots and a sentence. You need to replace all the successor in the sentence with the root forming it. If a successor has many roots can form it, replace it with the root with the shortest length. Input: dict = ["cat", "bat", "rat"] sentence = "the cattle was rattled by the battery" Output: "the cat was rat by the bat"
we get the map from first char to the set of dict words, then for each word in sentense, we find the match . struct comparer { bool operator() (const string s1, const string s2) const { return s1.length() < s2.length() || (s1.length() == s2.length() && s1 < s2); } }; class Solution { public: string replaceWords(vector<string>& dict, string sentence) { unordered_map<char, set<string, comparer>> dictMap; for(auto& str: dict) dictMap[str[0]].insert(str); vector<string> tokens = getTokens(sentence); string res; for(auto& str: tokens) { set<string, comparer> strSet = dictMap[str[0]]; bool found = false; for(auto& ss: strSet) if(str.substr(0, ss.length()) == ss) { res += res.empty()? ss: (" " + ss); found = true; break; } if(!found) res += res.empty()? str: (" " + str); } return res; } vector<string> getTokens(string s) { int pos = s.find(" "); vector<string> res; while(pos != -1) { res.push_back(s.substr(0, pos)); s.erase(0, pos+1); pos = s.find(" "); } res.push_back(s); return res; } };
554. Brick Wall There is a brick wall in front of you. The wall is rectangular and has several rows of bricks. The bricks have the same height but different width. You want to draw a vertical line from the top to the bottom and cross the least bricks. The brick wall is represented by a list of rows. Each row is a list of integers representing the width of each brick in this row from left to right.
we get the map of the brick length sums. the max count will be the answer. class Solution { public: int leastBricks(vector<vector<int>>& wall) { int size = wall.size(); unordered_map<int, int> sumMap; for(auto& arr: wall) { int val = 0; for(int i = 0; i < arr.size() -1; i ++) { val += arr[i]; sumMap[val] ++; } } map<int, int, greater<int>> counts; for(auto& [num, cnt]: sumMap) counts[cnt] = num; return size - counts.begin()->first; } };
970. Powerful Integers Given two positive integers x and y, an integer is powerful if it is equal to x^i + y^j for some integers i >= 0 and j >= 0. Return a list of all powerful integers that have value less than or equal to bound. Input: x = 2, y = 3, bound = 10 Output: [2,3,4,5,7,9,10]
we get the power num of x within bound an of y. class Solution { public: vector<int> powerfulIntegers(int x, int y, int bound) { vector<int>arr1 = getSqrs(x, bound); vector<int>arr2 = getSqrs(y, bound); set<int> res; for(auto& num: arr1) for(auto& num1: arr2) { if(num + num1 <= bound) res.insert(num + num1); else break; } vector<int> ans(res.begin(), res.end()); return ans; } vector<int> getSqrs(int val, int bound) { vector<int> res; if(val == 1) return {1}; else if(val == 0) return {0}; else { int num = 1; while(num <= bound) { res.push_back(num); num *= val; } } return res; } };
939. Minimum Area Rectangle Given a set of points in the xy-plane, determine the minimum area of a rectangle formed from these points, with sides parallel to the x and y axes. If there isn't any rectangle, return 0. Input: [[1,1],[1,3],[3,1],[3,3],[2,2]] Output: 4
we groups the points into map using same x, then iterate the x to find x1 which has same y. class Solution { public: int minAreaRect(vector<vector<int>>& points) { unordered_map<int, set<int>> xMap; for(auto& arr: points) { xMap[arr[0]].insert(arr[1]); } int res = INT_MAX; for(auto& [x1, ys1]: xMap) { if(ys1.size() < 2) continue; for(auto& [x2, ys2]: xMap) if(x1 != x2 && ys2.size() >= 2) { vector<int> same; for(auto& y: ys1) if(ys2.find(y) != ys2.end()) { same.push_back(y); } if(same.size() >= 2) { int dx = abs(x2 - x1); for(int i = 1; i < same.size(); i ++) { int dy = abs(same[i] - same[i-1]); res = min(res, dx * dy); } } } } return res == INT_MAX? 0: res; } };
609. Find Duplicate File in System A group of duplicate files consists of at least two files that have exactly the same content. A single directory info string in the input list has the following format: "root/d1/d2/.../dm f1.txt(f1_content) f2.txt(f2_content) ... fn.txt(fn_content)" ["root/a 1.txt(abcd) 2.txt(efgh)", "root/c 3.txt(abcd)", "root/c/d 4.txt(efgh)", "root 4.txt(efgh)"] Output: [["root/a/2.txt","root/c/d/4.txt","root/4.txt"],["root/a/1.txt","root/c/3.txt"]]
we record the content map. class Solution { public: vector<vector<string>> findDuplicate(vector<string>& paths) { unordered_map<string, unordered_set<string> > contentMap; for(auto& str: paths) { getContent(str, contentMap); } vector<vector<string>> res; for(auto& [content, files]: contentMap) if(files.size() > 1) { vector<string> tmp(files.begin(), files.end()); res.push_back(tmp); } return res; } void getContent(string s, unordered_map<string, unordered_set<string> >& contents) { int pos = s.find(" "); string dir = s.substr(0, pos); s.erase(0, pos+1); pos = s.find(" "); string file; string content; while(pos != -1) { string str = s.substr(0, pos); s.erase(0, pos+1); pos = s.find(" "); getFileContent(str, file, content); contents[content].insert(dir + "/" + file); } getFileContent(s, file, content); contents[content].insert(dir + "/" + file); } void getFileContent(string str, string& file, string& content) { int pos1 = str.find("("); file = str.substr(0, pos1); content = str.substr(pos1+1, str.length() - 1 - pos1); } };
594. Longest Harmonious Subsequence We define a harmounious array as an array where the difference between its maximum value and its minimum value is exactly 1. Now, given an integer array, you need to find the length of its longest harmonious subsequence among all its possible subsequences. Input: [1,3,2,2,5,2,3,7] Output: 5
we record the count map class Solution { public: int findLHS(vector<int>& nums) { unordered_map<int, int> counts; for(auto& num: nums) counts[num] ++; int res = 0; for(auto& [num, cnt]: counts) { if(counts.find(num+1) != counts.end()) res = max(res, cnt + counts[num+1]); } return res; } };
599. Minimum Index Sum of Two Lists You need to help them find out their common interest with the least list index sum. If there is a choice tie between answers, output all of them with no order requirement. You could assume there always exists an answer. ["Shogun", "Tapioca Express", "Burger King", "KFC"] ["Piatti", "The Grill at Torrey Pines", "Hungry Hunter Steakhouse", "Shogun"] Output: ["Shogun"]
we record the ind map. class Solution { public: vector<string> findRestaurant(vector<string>& list1, vector<string>& list2) { unordered_map<string, int> indMap1; unordered_map<string, int> indMap2; for(int i = 0; i < list1.size(); i ++) indMap1[list1[i]] = i; for(int i = 0; i < list2.size(); i ++) indMap2[list2[i]] = i; int indSum = INT_MAX; vector<string> res; for(auto& [str, ind]: indMap1) { if(indMap2.find(str) != indMap2.end()) { int currSum = ind + indMap2[str]; if(currSum < indSum) { res = {str}; indSum = currSum; } else if(currSum == indSum) res.push_back(str); } } return res; } };
525. Contiguous Array Given a binary array, find the maximum length of a contiguous subarray with equal number of 0 and 1. Example 1: Input: [0,1] Output: 2
we record the num of ones and zeros until current index. class Solution { public: int findMaxLength(vector<int>& nums) { int size = nums.size(); if(size == 0) return 0; vector<int> zeros(size); vector<int> ones(size); unordered_map<int, vector<int>> diffMap; int res = 0; for(int i = 0; i < size; i ++) { if(nums[i] == 0) { zeros[i] = i > 0? zeros[i-1] + 1: 1; ones[i] = i >0? ones[i-1]: 0; } else { ones[i] = i > 0? ones[i-1] + 1: 1; zeros[i] = i > 0? zeros[i-1]: 0; } diffMap[zeros[i] - ones[i]].push_back(i); if(zeros[i] == ones[i]) res = max(res, i+1); } for(auto& [diff, arr]: diffMap) { res = max(res, arr.back() - arr[0]); } return res; } };
811. Subdomain Visit Count Now, call a "count-paired domain" to be a count (representing the number of visits this domain received), followed by a space, followed by the address. An example of a count-paired domain might be "9001 discuss.leetcode.com". ["9001 discuss.leetcode.com"] Output: ["9001 discuss.leetcode.com", "9001 leetcode.com", "9001 com"]w
we use count map. class Solution { private: unordered_map<string, int> counts; public: vector<string> subdomainVisits(vector<string>& cpdomains) { for(auto& str: cpdomains) { int pos = str.find(" "); int num = stoi(str.substr(0, pos)); str.erase(0, pos + 1); counts[str] += num; pos = str.find("."); while(pos != -1) { str.erase(0, pos+1); counts[str] += num; pos = str.find("."); } } vector<string> res; for(auto& [str, cnt]: counts) { res.push_back(to_string(cnt) + " " + str); } return res; } };
748. Shortest Completing Word Find the minimum length word from a given dictionary words, which has all the letters from the string licensePlate. Such a word is said to complete the given string licensePlate Here, for letters we ignore case. For example, "P" on the licensePlate still matches "p" on the word. Input: licensePlate = "1s3 PSt", words = ["step", "steps", "stripe", "stepple"] Output: "steps"
we use countmap . class Solution { public: string shortestCompletingWord(string licensePlate, vector<string>& words) { unordered_map<char, int> targetMap = getMap(licensePlate); string res = ""; for(auto& str: words) { unordered_map<char, int> curr = getMap(str); bool valid = true; for(auto& [ch, cnt]: targetMap) if(curr[ch] < cnt) { valid = false; break; } if(valid) { if(res == "" || str.length() < res.length()) res = str; } } return res; } unordered_map<char, int> getMap(string str) { unordered_map<char, int> res; for(auto& ch: str) if(isalpha(ch)) res[tolower(ch)] ++; return res; } };
508. Most Frequent Subtree Sum Given the root of a tree, you are asked to find the most frequent subtree sum. The subtree sum of a node is defined as the sum of all the node values formed by the subtree rooted at that node (including the node itself). So what is the most frequent subtree sum value? If there is a tie, return all the values with the highest frequency in any order. 5 / \ 2 -5 return [2], since 2 happens twice, however -5 only occur once.
we use countmap to record the counts of sum. class Solution { private: unordered_map<int, int> countMap; public: vector<int> findFrequentTreeSum(TreeNode* root) { if(root == NULL) return {}; dfs(root); map<int,vector<int>, greater<int>> counts; for(auto& [num, cnt]: countMap) counts[cnt].push_back(num); return counts.begin()->second; } int dfs(TreeNode* root) { if(root == NULL) return 0; int l = dfs(root -> left); int r = dfs(root->right); countMap[root->val + l + r] ++; return root->val + l + r; } };
694. Number of Distinct Islands Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water. Count the number of distinct islands. An island is considered to be the same as another if and only if one island can be translated (and not rotated or reflected) to equal the other. 11000 11000 00011 00011 Given the above grid map, return 1.
we use dfs to find the island, and use string to record the search directions. class Solution { private: int rows; int cols; vector<vector<int>> delta = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; public: int numDistinctIslands(vector<vector<int>>& grid) { rows = grid.size(); if(rows == 0) return 0; cols = grid[0].size(); vector<vector<bool>> visited(rows,vector<bool>(cols, false)); unordered_set<string> islands; for(int r = 0; r < rows; r ++) for(int c = 0; c < cols; c ++) { if(grid[r][c] == 1 && !visited[r][c]) { string path = ""; dfs(r, c, visited, grid, path); islands.insert(path); } } return islands.size(); } void dfs(int row, int col, vector<vector<bool>>& visited, vector<vector<int>>& grid, string& path) { visited[row][col] = true; for(int dir = 0; dir < 4; dir ++) { vector<int> arr = delta[dir]; int x = row + arr[0]; int y = col + arr[1]; if(x>= 0 && x < rows && y >= 0 && y < cols && !visited[x][y] && grid[x][y] == 1) { path += to_string(dir); dfs(x, y, visited, grid, path); } else path += '#'; } } };
718. Maximum Length of Repeated Subarray Given two integer arrays A and B, return the maximum length of an subarray that appears in both arrays. A: [1,2,3,2,1] B: [3,2,1,4,7] Output: 3
we use dynamic programming to cal from end to start. dp[i][j] stands for from size1 to i of array A, size2 to j of array B, the max repeated len. class Solution { public: int findLength(vector<int>& A, vector<int>& B) { int size1 = A.size(); int size2 = B.size(); vector<vector<int>> dp(size1 + 1, vector<int>(size2 + 1)); int res = 0; for(int i = size1-1; i >= 0; i --) { for(int j = size2 - 1; j >= 0; j --) { if(A[i] == B[j]) { dp[i][j] =dp[i+1][j+1] + 1; res = max(res, dp[i][j]); } } } return res; } };
535. Encode and Decode TinyURL TinyURL is a URL shortening service where you enter a URL such as https://leetcode.com/problems/design-tinyurl and it returns a short URL such as http://tinyurl.com/4e9iAk. Design the encode and decode methods for the TinyURL service. There is no restriction on how your encode/decode algorithm should work. You just need to ensure that a URL can be encoded to a tiny URL and the tiny URL can be decoded to the original URL.
we use ind to indicate the id of url, then use 62 decimal to encode the url. class Solution { private: unordered_map<int, pair<string,string>> codeMap; string chs = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; string tinyURL = "http://tinyurl.com/"; int ind; public: // Encodes a URL to a shortened URL. string encode(string longUrl) { ind ++; int val = ind; string res = ""; while(val > 0) { res += chs[val % 62]; val /= 62; } reverse(res.begin(), res.end()); codeMap[ind] = pair(res, longUrl); return tinyURL + res; } // Decodes a shortened URL to its original URL. string decode(string shortUrl) { string code = shortUrl.substr(19); int id = 0; for(auto& ch: code) { if(ch >= 'a' && ch<= 'z') id = id * 62 + ch - 'a'; else if(ch >= 'A' && ch <= 'Z') id = id * 62 + ch - 'A' + 26; else if(ch >= '0' && ch <= '9') id = id * 62 + ch - '0' + 52; } return codeMap[id].second; } };
953. Verifying an Alien Dictionary In an alien language, surprisingly they also use english lowercase letters, but possibly in a different order. The order of the alphabet is some permutation of lowercase letters. Given a sequence of words written in the alien language, and the order of the alphabet, return true if and only if the given words are sorted lexicographicaly in this alien language. Input: words = ["hello","leetcode"], order = "hlabcdefgijkmnopqrstuvwxyz" Output: true
we use map to record the priority of each order char. then compare i and i+1 of the words. class Solution { private: unordered_map<char, int> charMap; public: bool isAlienSorted(vector<string>& words, string order) { for(int i = 0; i < order.length(); i ++) charMap[order[i]] = i; for(int i = 0; i + 1 < words.size(); i ++) { if(!smaller(words[i], words[i+1])) return false; } return true; } bool smaller(string s1, string s2) { int len1 = s1.length(); int len2 = s2.length(); int i = 0; int j = 0; for(; i < len1 && j < len2; i ++, j ++) { if(charMap[s1[i]] > charMap[s2[j]]) return false; else if(charMap[s1[i]] < charMap[s2[j]]) return true; } if(i == len1) return true; else if(j == len2) return false; return true; } };
974. Subarray Sums Divisible by K Given an array A of integers, return the number of (contiguous, non-empty) subarrays that have a sum divisible by K. Input: A = [4,5,0,-2,-3,1], K = 5 Output: 7
we use map to record the sum % K. class Solution { public: int subarraysDivByK(vector<int>& A, int K) { int sum = 0; map<int, int> counts; counts[0] = 1; for(int i = 0; i< A.size(); i ++) { sum += A[i]; counts[(sum % K + K) % K] ++; } int res = 0; for(auto& [num, cnt]: counts) { if(cnt >= 0) res += (cnt-1) * cnt / 2; } return res; } };
987. Vertical Order Traversal of a Binary Tree Given a binary tree, return the vertical order traversal of its nodes values. For each node at position (X, Y), its left and right children respectively will be at positions (X-1, Y-1) and (X+1, Y-1). Running a vertical line from X = -infinity to X = +infinity, whenever the vertical line touches some nodes, we report the values of the nodes in order from top to bottom (decreasing Y coordinates).
we use map to record the x value as key, and need to sort the array in y and value order. /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */ typedef tuple<int,int,int> tu; struct compare { bool operator() (const tu& t1, const tu& t2) const { if(get<1>(t1) != get<1>(t2)) return get<1>(t1) > get<1>(t2); return get<2>(t1) < get<2>(t2); } }; class Solution { private: map<int, set<tu, compare>> xMap; public: vector<vector<int>> verticalTraversal(TreeNode* root) { if(root == NULL) return {}; queue<tuple<int, int, TreeNode*>> q; q.push(tuple(0,0, root)); while(! q.empty()) { tuple<int, int, TreeNode*> curr = q.front(); q.pop(); int x = get<0>(curr); int y = get<1>(curr); TreeNode* node = get<2>(curr); if(node == NULL) continue; xMap[x].insert(tuple(x, y, node->val) ); q.push(tuple(x-1, y-1, node->left)); q.push(tuple(x+1, y-1, node->right)); } vector<vector<int>> res; for(auto& [x, arr]: xMap) { vector<int> tmp; for(auto& tuple: arr) tmp.push_back(get<2>(tuple)); res.push_back(tmp); } return res; } };
981. Time Based Key-Value Store Create a timebased key-value store class TimeMap, that supports two operations. 1. set(string key, string value, int timestamp) Stores the key and value, along with the given timestamp. 2. get(string key, int timestamp) Returns a value such that set(key, value, timestamp_prev) was called previously, with timestamp_prev <= timestamp.
we use map<string, map<int,string>> as the structure. class TimeMap { private: map<string, map<int, string> > keyVal; public: /** Initialize your data structure here. */ TimeMap() { keyVal.clear(); } void set(string key, string value, int timestamp) { keyVal[key][timestamp] = value; } string get(string key, int timestamp) { map<int, string>& valMap = keyVal[key]; auto ite = valMap.lower_bound(timestamp); if(ite == valMap.end()) { if(ite == valMap.begin()) return ""; --ite; return ite->second; } if(ite->first == timestamp) return ite->second; if(ite == valMap.begin()) return ""; --ite; return ite->second; } }; /** * Your TimeMap object will be instantiated and called as such: * TimeMap* obj = new TimeMap(); * obj->set(key,value,timestamp); * string param_2 = obj->get(key,timestamp); */
676. Implement Magic Dictionary Implement a magic directory with buildDict, and search methods. For the method buildDict, you'll be given a list of non-repetitive words to build a dictionary. For the method search, you'll be given a word, and judge whether if you modify exactly one character into another character in this word, the modified word is in the dictionary you just built. ["MagicDictionary", "buildDict", "search", "search", "search", "search"] [[], [["hello","leetcode"]], ["hello"], ["hhllo"], ["hell"], ["leetcoded"]]
we use set to record the dict and then change one char in search word, and find . class MagicDictionary { private: unordered_set<string> strSet; int minLen = INT_MAX; int maxLen = -1; public: /** Initialize your data structure here. */ MagicDictionary() { strSet.clear(); minLen = INT_MAX; maxLen = -1; } /** Build a dictionary through a list of words */ void buildDict(vector<string> dict) { for(auto& str: dict) { minLen = min(minLen, int(str.length()) ); maxLen = max(maxLen, int(str.length()) ); strSet.insert(str); } } /** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */ bool search(string word) { int len = word.length(); if(len < minLen || len > maxLen) return false; for(int i = 0; i < len ; i ++) { string tmp = word; for(char ch = 'a'; ch <= 'z'; ch ++ ) if(word[i] != ch) { tmp[i] = ch; if(strSet.find(tmp) != strSet.end()) return true; } } return false; } };
720. Longest Word in Dictionary Given a list of strings words representing an English Dictionary, find the longest word in words that can be built one character at a time by other words in words. If there is more than one possible answer, return the longest word with the smallest lexicographical order. words = ["a", "banana", "app", "appl", "ap", "apply", "apple"] Output: "apple"
we use trie to record the words. if current node is end, then add to string. struct Trie { char val; bool end = false; unordered_map<char, Trie*> children; Trie() {}; Trie(char val): val(val) {}; }; class Solution { private: Trie* root; string res; public: string longestWord(vector<string>& words) { if(words.size() == 0) return ""; root = new Trie('$'); buildTrie(words); dfs(root, ""); return res; } void dfs(Trie* root, string tmp) { if(root->children.size() == 0) { if(tmp.length() > res.length() || (tmp.length() == res.length() && tmp < res)) res = tmp; return; } for(auto& [ch, node]: root->children) { if(node ->end) { tmp += ch; dfs(node, tmp); tmp.pop_back(); } else { if(tmp.length() > res.length() || (tmp.length() == res.length() && tmp < res)) res = tmp; } } } void buildTrie(vector<string>& words) { for(auto& str: words) { Trie* curr = root; for(auto& ch: str) { if(curr->children.count(ch) == 0) curr->children[ch] = new Trie(ch); curr = curr->children[ch]; } curr->end = true; } } };
992. Subarrays with K Different Integers Given an array A of positive integers, call a (contiguous, not necessarily distinct) subarray of A good if the number of different integers in that subarray is exactly K. (For example, [1,2,3,1,2] has 3 different integers: 1, 2, and 3.) Return the number of good subarrays of A. Input: A = [1,2,1,2,3], K = 2 Output: 7
we use two window to record the unique num > k and unique num >= k, then the diff is == k. struct Window { map<int, int> counts; Window() {}; void add(int val) { counts[val] ++; } void erase(int val) { counts[val] --; if(counts[val] == 0) counts.erase(val); } int size() { return counts.size(); } }; class Solution { public: int subarraysWithKDistinct(vector<int>& A, int K) { Window win1; Window win2; int ind1 = 0; int ind2 = 0; int res = 0; for(int i = 0; i < A.size(); i ++) { win1.add(A[i]); win2.add(A[i]); while(win1.size() > K) { win1.erase(A[ind1 ++]); } while(win2.size() >= K) { win2.erase(A[ind2 ++]); } res += ind2 - ind1; } return res; } };
500. Keyboard Row Given a List of words, return the words that can be typed using letters of alphabet on only one row's of American keyboard like the image below. Input: ["Hello", "Alaska", "Dad", "Peace"] Output: ["Alaska", "Dad"]
we write the map of char to row map. class Solution { private: unordered_map<char, int> chars = {{'q', 0}, {'w', 0},{'e', 0},{'r', 0},{'t', 0},{'y', 0},{'u', 0},{'i', 0},{'o', 0},{'p', 0}, {'a', 1}, {'s', 1},{'d', 1},{'f', 1},{'g', 1},{'h', 1},{'j', 1},{'k', 1},{'l', 1}, {'z', 2}, {'x', 2},{'c', 2},{'v', 2},{'b', 2},{'n', 2},{'m', 2}}; public: vector<string> findWords(vector<string>& words) { vector<string> res; for(auto& str: words) { int row = chars[tolower(str[0])]; bool valid = true; for(auto& ch: str) { if(chars[tolower(ch)] != row) { valid = false; break; } } if(valid) res.push_back(str); } return res; } };