Open hon9g opened 4 years ago
for all method
N =the range of values, I use 1000001 size array,
/**
* Initialize your data structure here.
*/
const MyHashSet = function() {
this.hashSet = new Array(1000001).fill(0);
};
/**
/**
/**
### Array of Array as Bucket
- The common choice of hash function is `%`
- Generally advisable to use a prime number as the base of modulo operator to reduce collisions
- `N = the range of values, It is 1000001`
- `K = the number for hash function, I use 769`
- Time complexity: **O(1)** `for add` **O(N/K)** `for remove and search`
- Space complexity: **O(N)**
```JavaScript
const MyHashSet = function() {
this.hashSet = new Array(769);
};
/**
/**
/**
%
N = the range of values, It is 1000001
K = the number for hash function, I use 769
for add, remove and search
/** Binary Search Tree
* @param {number} x
* @return {void}
*/
function Node(x) {
this.val = x;
this.left = null;
this.right = null;
}
/**
/**
/**
/**
/**
/**
/** Hash Set
};
/**
/**
N
% prime number
N = range of key
const MyHashMap = function() {
this.map = new Array(1000001).fill(-1);
};
/**
/**
/**
constant prime number
% prime number
/**
* Node for Binary Search Tree
* @return {void}
*/
const Node = function(key, val) {
this.key = key;
this.val = val;
this.left = null;
this.right = null;
}
/**
/**
/**
/**
/**
/**
/**
/**
/**
N = range of key
/**
* Hash Map
* @return {void}
*/
var MyHashMap = function() {
this.map = new Map();
};
/**
/**
/**
/**
* @param {number[]} nums
* @return {boolean}
*/
const containsDuplicate = nums => {
const hashSet = new Set();
for(let i = 0; i < nums.length; i++) {
if (hashSet.has(nums[i])) return true;
hashSet.add(nums[i])
}
return false;
};
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
hashSet = set()
for i in range(len(nums)):
if nums[i] in hashSet:
return True
hashSet.add(nums[i])
return False
/**
* @param {number[]} nums
* @return {number}
*/
const singleNumber = nums => {
const hashSet = new Set();
nums.forEach(x => {
if (hashSet.has(x)) {
hashSet.delete(x);
} else {
hashSet.add(x);
}
})
return [...hashSet][0];
};
class Solution:
def singleNumber(self, nums: List[int]) -> int:
hashSet = set()
for i in range(len(nums)):
if nums[i] in hashSet:
hashSet.remove(nums[i])
else:
hashSet.add(nums[i])
return hashSet.pop()
/**
* @param {number[]} nums
* @return {number}
*/
const singleNumber = nums => {
nums.sort()
for (let i = 0; i + 1 < nums.length; i += 2) {
if (nums[i] !== nums[i+1]) {
return nums[i-1] === nums[i] ? nums[i+1] : nums[i];
}
}
return nums[nums.length - 1];
};
class Solution:
def singleNumber(self, nums: List[int]) -> int:
nums.sort()
for i in range(1, len(nums), 2):
if nums[i-1] != nums[i]:
return nums[i-1] if nums[i] == nums[i+1] else nums[i]
return nums[-1]
2(a + b) - ( a + a + b ) = b
/**
* @param {number} a
* @param {number} b
* @return {number}
*/
const sum = (a, b) => a + b;
/**
```Python
class Solution:
def singleNumber(self, nums: List[int]) -> int:
return sum(set(nums)) * 2 - sum(nums)
/**
* @param {number[]} nums
* @return {number}
*/
const singleNumber = nums => nums.reduce((acc, curr) => acc^curr);
class Solution:
def singleNumber(self, nums: List[int]) -> int:
res = 0
for n in nums:
res ^= n
return res
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var intersection = function(nums1, nums2) {
const [a, b] = [new Set(nums1), new Set(nums2)];
return [...a].filter(x => b.has(x));
};
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
return set(nums1) & set(nums2)
/**
* @param {number} n
* @return {boolean}
*/
const isHappy = n => {
const seen = new Set();
let m;
while (n !== 1) {
if (seen.has(n)) return false;
seen.add(n);
[m, n] = [n, 0];
while (m > 0) {
n += (m % 10) ** 2;
m = (m - m % 10) / 10;
}
}
return true;
}
/**
* @param {string} s
* @return {number}
*/
const toInt = s => parseInt(s);
/**
/**
```Python
class Solution:
def isHappy(self, n: int) -> bool:
seen = set()
while n != 1:
if n in seen:
return False
seen.add(n)
n = sum([int(s) ** 2 for s in str(n)])
return True
/**
/**
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
const twoSum = (nums, target) => {
const memo = new Map();
for (let i = 0; i < nums.length; i++) {
if (memo.has(target - nums[i])) {
return [memo.get(target - nums[i]), i];
}
memo.set(nums[i], i);
}
};
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/
const twoSum = (nums, target) => {
const memo = {};
for (let i = 0; i < nums.length; i++) {
if (memo[target - nums[i]] !== undefined) {
return [memo[target - nums[i]], i];
}
memo[nums[i]] = i;
}
};
/**
* @param {string} s
* @param {string} t
* @return {boolean}
*/
const isIsomorphic = (s, t) => {
const [memo, seen] = [new Map(), new Set()];
for (let i = 0; i < s.length; i++) {
if (!memo.get(s[i]) && !seen.has(t[i])) {
memo.set(s[i], t[i]);
seen.add(t[i]);
}
if (memo.get(s[i]) !== t[i]) return false;
}
return true;
};
/**
* @param {string[]} list1
* @param {string[]} list2
* @return {string[]}
*/
const findRestaurant = (list1, list2) => {
const seen = {};
for (let i = 0; i < list1.length; i++) {
seen[list1[i]] = i;
}
const commons = new Array(2001);
let minVal = Infinity;
for (let i = 0; i < list2.length; i++) {
if (seen[list2[i]] !== undefined) {
const idx = seen[list2[i]] + i;
if (commons[idx] === undefined) {
commons[idx] = [];
}
commons[idx].push(list2[i]);
if (idx < minVal) minVal = idx;
}
}
return commons[minVal];
};
/**
* @param {string[]} list1
* @param {string[]} list2
* @return {string[]}
*/
const findRestaurant = (list1, list2) => {
let [seen, commons, minVal] = [{}, [], Infinity];
for (let i = 0; i < list1.length; i++) seen[list1[i]] = i;
for (let i = 0; i < list2.length; i++) {
if (seen[list2[i]] !== undefined) {
const idx = seen[list2[i]] + i;
if (idx < minVal) minVal = idx, commons = [];
if (idx === minVal) commons.push(list2[i]);
}
}
return commons;
};
class Solution:
def findRestaurant(self, list1: List[str], list2: List[str]) -> List[str]:
seen, minVal, common = {}, float("inf"), []
for idx, name in enumerate(list1):
seen[name] = idx
for idx, name in enumerate(list2):
if name in seen:
seen[name] = seen[name] + idx
if minVal > seen[name]:
minVal = seen[name]
common = []
if seen[name] == minVal:
common.append(name)
return common
/**
* @param {string} s
* @return {number}
*/
const firstUniqChar = s => {
const counter = {};
for (const c of s) {
counter[c] ? counter[c]++ : counter[c] = 1;
}
for (let i = 0; i < s.length; i++) {
if (counter[s[i]] === 1) return i;
}
return -1
};
class Solution:
def firstUniqChar(self, s: str) -> int:
counter = {}
for c in s:
if c in counter:
counter[c] += 1
else:
counter[c] = 1
for i in range(len(s)):
if counter[s[i]] == 1:
return i
return -1
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
const intersect = (nums1, nums2) => {
const seen = {};
for (n of nums1) seen[n] ? seen[n]++ : seen[n] = 1;
return nums2.filter(e => seen[e] ? seen[e]-- : false)
};
/**
* @param {number[]} nums
* @param {number} k
* @return {boolean}
*/
const containsNearbyDuplicate = (nums, k) => {
for (let i = 0, seen = new Set(); i < nums.length; i++) {
if (seen.has(nums[i])) return true;
seen.add(nums[i]);
if (k < seen.size) seen.delete(nums[i-k]);
}
return false;
};
var Logger = function() {
this.seen = new Map();
};
/**
/**
* @param {string[]} strs
* @return {string[][]}
*/
const groupAnagrams = strs => {
const map = {};
strs.forEach(s => {
const key = s.split('').sort();
map[key] ? map[key].push(s) : map[key] = [s];
})
return Object.values(map);
};
/**
* @param {string[]} strs
* @return {string[][]}
*/
const groupAnagrams = strs => {
const map = {};
strs.forEach(s => {
const key = new Array(26).fill(0);
for (c of s) key[c.charCodeAt(0) - 97]++;
map[key] ? map[key].push(s) : map[key] = [s];
})
return Object.values(map);
};
/**
* @param {string[]} strs
* @return {string[][]}
*/
const groupStrings = strs => {
const res = {};
strs.forEach(s => {
const key = new Array(s.length).fill(0);
for (let i = 1; i < s.length; i++) {
key[i] = s.charCodeAt(i-1) - (s.charCodeAt(i) + 26);
if (key[i] > 25 || key[i] < -25) key[i] %= 26;
}
res[key] ? res[key].push(s) : res[key] = [s];
})
return Object.values(res);
};
Determine key by the distance between chars.
Assume a = 1, b = 2, ..., y = 25, z = 26
,
// if s === "azb"
const key = new Array(s.length).fill(0); // [0, 0, 0]
for (let i = 1; i < s.length; i++) {
key[i] = s.charCodeAt(i-1) - (s.charCodeAt(i) + 26); // [0, -51, -2]
if (key[i] > 25 || key[i] < -25) key[i] %= 26; // [0, -25, -2]
}
// if s === "bac"
const key = new Array(s.length).fill(0); // [0, 0, 0]
for (let i = 1; i < s.length; i++) {
key[i] = s.charCodeAt(i-1) - (s.charCodeAt(i) + 26); // [0, -25, -28]
if (key[i] > 25 || key[i] < -25) key[i] %= 26; // [0, -25, -2]
}
/**
* @param {character[][]} board
* @return {boolean}
*/
const isValidSudoku = board => {
let rows = [], cols = [], boxes = [];
for (let i = 0; i < 9; i++) {
rows.push({}), cols.push({}), boxes.push({});
}
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
if (board[i][j] === '.') continue;
const n = parseInt(board[i][j]);
const boxIdx = parseInt(i/3) * 3 + parseInt(j/3);
rows[i][n] = rows[i][n] ? rows[i][n] + 1 : 1;
cols[j][n] = cols[j][n] ? cols[j][n] + 1 : 1;
boxes[boxIdx][n] = boxes[boxIdx][n] ? boxes[boxIdx][n] + 1 : 1;
if (rows[i][n] > 1 || cols[j][n] > 1 || boxes[boxIdx][n] > 1) {
return false
}
}
}
return true;
};
/**
* @param {TreeNode} root
* @return {TreeNode[]}
*/
const findDuplicateSubtrees = root => {
const dfs = node => {
if (!node) return '#';
const key = node.val + dfs(node.left) + dfs(node.right);
seen[key] ? seen[key]++ : seen[key] = 1;
if (seen[key] === 2) result.push(node);
return key;
}
const result = [], seen = {};
dfs(root);
return result;
};
/**
* @param {string} J
* @param {string} S
* @return {number}
*/
const numJewelsInStones = (J, S) => {
return S.split('').reduce((a, c) => J.includes(c) ? a + 1 : a, 0);
};
/**
* @param {string} J
* @param {string} S
* @return {number}
*/
const numJewelsInStones = (J, S) => {
const box = new Set(J.split(''));
return S.split('').reduce((a, c) => box.has(c) ? a + 1 : a, 0);
};
/**
* @param {string} s
* @return {number}
*/
const lengthOfLongestSubstring = s => {
let seen = new Set(), temp = '', n = 0;
for (let c of s) {
if (seen.has(c)) {
for (let e of temp.slice(0, temp.indexOf(c))) {
seen.delete(e);
}
temp = temp.slice(temp.indexOf(c) + 1) + c;
} else {
temp += c, seen.add(c);
if (n < temp.length) {
n = temp.length;
}
}
}
return n;
};
/**
* @param {string} s
* @return {number}
*/
const lengthOfLongestSubstring = s => {
let seen = new Set(), i = 0 , j = 0, n = 0;
while (i < s.length && j < s.length) {
if (!seen.has(s[j])) {
seen.add(s[j++]);
if (n < j - i) n = j - i;
} else {
seen.delete(s[i++]);
}
}
return n;
};
var TwoSum = function() {
this.nums = {};
};
/**
/**
/**
* @param {number[]} A
* @param {number[]} B
* @return {number{}}
*/
const buildMap = (A, B) => {
const cnt = {};
for (a of A) {
for (b of B) {
cnt[a+b] ? cnt[a+b]++ : cnt[a+b] = 1;
}
}
return cnt;
}
/**
### One Hash Set (TLE)
- Time complexity: **O(N^3)**
- Space complexity: **O(N)**
```JavaScript
/**
/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/
var topKFrequent = (nums, k) => {
const cnt = {}, res = [];
for (n of nums) cnt[n] ? cnt[n]++ : cnt[n] = 1;
while (k--) {
let e = 0, freq = 0;
for (key of Object.keys(cnt)) {
if (freq < cnt[key]) e = key, freq = cnt[key];
}
res.push(e);
delete cnt[e];
}
return res;
};
/**
* @param {string} w
* @return {string}
*/
const abbr = w => w.length < 3 ? w : [w[0], w.length - 2, w[w.length - 1]].join('');
/**
/**
/**
* Initialize your data structure here.
*/
var RandomizedSet = function() {
this.dict = new Map(), this.arr = [];
};
/**
/**
/**
};
Problems selected by LeetCode for the topic Hash Table 🌐
Click ✔️ to go to each solution. The Link to each problem🌐 is at the top of each solution.
🔗 Design a Hash Table
🔗 Practical Application - Hash Set
🔗 Practical Application - Hash Map
🔗 Practical Application - Design the Key
🔗 Conclusion