Compare commits
7 Commits
344731ed23
...
fb6e386479
Author | SHA1 | Date | |
---|---|---|---|
fb6e386479 | |||
80245886a1 | |||
d86e3334b1 | |||
7386344b2e | |||
25fe22ae23 | |||
1578bc52d6 | |||
4c4bf0bd5f |
49
0036_valid-sudoku/README.md
Normal file
49
0036_valid-sudoku/README.md
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
Determine if a `9 x 9` Sudoku board is valid. Only the filled cells need to be validated **according to the following rules**:
|
||||||
|
|
||||||
|
1. Each row must contain the digits `1-9` without repetition.
|
||||||
|
2. Each column must contain the digits `1-9` without repetition.
|
||||||
|
3. Each of the nine `3 x 3` sub-boxes of the grid must contain the digits `1-9` without repetition.
|
||||||
|
|
||||||
|
**Note:**
|
||||||
|
|
||||||
|
* A Sudoku board (partially filled) could be valid but is not necessarily solvable.
|
||||||
|
* Only the filled cells need to be validated according to the mentioned rules.
|
||||||
|
|
||||||
|
**Example 1:**
|
||||||
|
|
||||||
|
![](https://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Sudoku-by-L2G-20050714.svg/250px-Sudoku-by-L2G-20050714.svg.png)
|
||||||
|
|
||||||
|
Input: board =
|
||||||
|
[["5","3",".",".","7",".",".",".","."]
|
||||||
|
,["6",".",".","1","9","5",".",".","."]
|
||||||
|
,[".","9","8",".",".",".",".","6","."]
|
||||||
|
,["8",".",".",".","6",".",".",".","3"]
|
||||||
|
,["4",".",".","8",".","3",".",".","1"]
|
||||||
|
,["7",".",".",".","2",".",".",".","6"]
|
||||||
|
,[".","6",".",".",".",".","2","8","."]
|
||||||
|
,[".",".",".","4","1","9",".",".","5"]
|
||||||
|
,[".",".",".",".","8",".",".","7","9"]]
|
||||||
|
Output: true
|
||||||
|
|
||||||
|
|
||||||
|
**Example 2:**
|
||||||
|
|
||||||
|
Input: board =
|
||||||
|
[["8","3",".",".","7",".",".",".","."]
|
||||||
|
,["6",".",".","1","9","5",".",".","."]
|
||||||
|
,[".","9","8",".",".",".",".","6","."]
|
||||||
|
,["8",".",".",".","6",".",".",".","3"]
|
||||||
|
,["4",".",".","8",".","3",".",".","1"]
|
||||||
|
,["7",".",".",".","2",".",".",".","6"]
|
||||||
|
,[".","6",".",".",".",".","2","8","."]
|
||||||
|
,[".",".",".","4","1","9",".",".","5"]
|
||||||
|
,[".",".",".",".","8",".",".","7","9"]]
|
||||||
|
Output: false
|
||||||
|
Explanation: Same as Example 1, except with the 5 in the top left corner being modified to 8. Since there are two 8's in the top left 3x3 sub-box, it is invalid.
|
||||||
|
|
||||||
|
|
||||||
|
**Constraints:**
|
||||||
|
|
||||||
|
* `board.length == 9`
|
||||||
|
* `board[i].length == 9`
|
||||||
|
* `board[i][j]` is a digit `1-9` or `'.'`.
|
54
0036_valid-sudoku/python3/solution.py
Normal file
54
0036_valid-sudoku/python3/solution.py
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
class Solution:
|
||||||
|
def isValidSudoku(self, board: List[List[str]]) -> bool:
|
||||||
|
#
|
||||||
|
# NOTE: **READ THE PROBLEM DESCRIPTION ALWAYS!!**
|
||||||
|
#
|
||||||
|
# Even though it mentions Sudoku, it doesn't mean the
|
||||||
|
# rules are the same as the real world. Which is the case
|
||||||
|
# here — we need to only look at the filled cell and the rules
|
||||||
|
# provided.
|
||||||
|
|
||||||
|
size = len(board)
|
||||||
|
|
||||||
|
# 1. Check if rows and cols are valid
|
||||||
|
#
|
||||||
|
# We can iterate both rows and cols at the same time since
|
||||||
|
# the sudoku board has 9 rows and 9 cols
|
||||||
|
for i in range(size):
|
||||||
|
row = set()
|
||||||
|
col = set()
|
||||||
|
|
||||||
|
for j in range(size):
|
||||||
|
# ith row check
|
||||||
|
if board[i][j] != '.':
|
||||||
|
if board[i][j] in row:
|
||||||
|
return False
|
||||||
|
|
||||||
|
row.add(board[i][j])
|
||||||
|
|
||||||
|
# ith col check
|
||||||
|
if board[j][i] != '.':
|
||||||
|
if board[j][i] in col:
|
||||||
|
return False
|
||||||
|
|
||||||
|
col.add(board[j][i])
|
||||||
|
|
||||||
|
# 2. Check if squares are valid
|
||||||
|
#
|
||||||
|
# We can do normal row * col iteration and use `// 3` to figure
|
||||||
|
# out which square a cell belongs to
|
||||||
|
|
||||||
|
squares = [[set(), set(), set()] for _ in range(3)]
|
||||||
|
for i in range(size):
|
||||||
|
for j in range(size):
|
||||||
|
cell = board[i][j]
|
||||||
|
if cell == '.':
|
||||||
|
continue
|
||||||
|
|
||||||
|
square = squares[i // 3][j // 3]
|
||||||
|
if cell in square:
|
||||||
|
return False
|
||||||
|
|
||||||
|
square.add(cell)
|
||||||
|
|
||||||
|
return True
|
27
0049_group-anagrams/README.md
Normal file
27
0049_group-anagrams/README.md
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Given an array of strings `strs`, group **the anagrams** together. You can return the answer in **any order**.
|
||||||
|
|
||||||
|
An **Anagram** is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.
|
||||||
|
|
||||||
|
**Example 1:**
|
||||||
|
|
||||||
|
Input: strs = ["eat","tea","tan","ate","nat","bat"]
|
||||||
|
Output: [["bat"],["nat","tan"],["ate","eat","tea"]]
|
||||||
|
|
||||||
|
|
||||||
|
**Example 2:**
|
||||||
|
|
||||||
|
Input: strs = [""]
|
||||||
|
Output: [[""]]
|
||||||
|
|
||||||
|
|
||||||
|
**Example 3:**
|
||||||
|
|
||||||
|
Input: strs = ["a"]
|
||||||
|
Output: [["a"]]
|
||||||
|
|
||||||
|
|
||||||
|
**Constraints:**
|
||||||
|
|
||||||
|
* `1 <= strs.length <= 104`
|
||||||
|
* `0 <= strs[i].length <= 100`
|
||||||
|
* `strs[i]` consists of lowercase English letters.
|
13
0049_group-anagrams/python3/naive.py
Normal file
13
0049_group-anagrams/python3/naive.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Time: O(N * MlogM) where N is len(strs) and M is num of chars in a string
|
||||||
|
# Space: O(N)
|
||||||
|
|
||||||
|
class Solution:
|
||||||
|
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
|
||||||
|
groups = {}
|
||||||
|
|
||||||
|
for s in strs:
|
||||||
|
s_sorted = ''.join(sorted(s))
|
||||||
|
|
||||||
|
groups[s_sorted] = groups.get(s_sorted, []) + [s]
|
||||||
|
|
||||||
|
return list(groups.values())
|
24
0049_group-anagrams/python3/solution.py
Normal file
24
0049_group-anagrams/python3/solution.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Time: O(N · M)
|
||||||
|
# Space: O(N)
|
||||||
|
|
||||||
|
from collections import Counter, defaultdict
|
||||||
|
|
||||||
|
class Solution:
|
||||||
|
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
|
||||||
|
# If key doesn't exist, creates empty list using `list`
|
||||||
|
# factory/ctor function
|
||||||
|
groups = defaultdict(list)
|
||||||
|
|
||||||
|
for s in strs:
|
||||||
|
# Keep counter for num of times each letter appeared
|
||||||
|
counts = [0] * 26
|
||||||
|
|
||||||
|
for c in s:
|
||||||
|
i = ord(c) - ord('a')
|
||||||
|
counts[i] += 1
|
||||||
|
|
||||||
|
# Lists aren't hashable, so we need to convert the counts
|
||||||
|
# to tuple so that we can key them
|
||||||
|
groups[tuple(counts)].append(s)
|
||||||
|
|
||||||
|
return list(groups.values())
|
24
0217_contains-duplicate/README.md
Normal file
24
0217_contains-duplicate/README.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
Given an integer array `nums`, return `true` if any value appears **at least twice** in the array, and return `false` if every element is distinct.
|
||||||
|
|
||||||
|
**Example 1:**
|
||||||
|
|
||||||
|
Input: nums = [1,2,3,1]
|
||||||
|
Output: true
|
||||||
|
|
||||||
|
|
||||||
|
**Example 2:**
|
||||||
|
|
||||||
|
Input: nums = [1,2,3,4]
|
||||||
|
Output: false
|
||||||
|
|
||||||
|
|
||||||
|
**Example 3:**
|
||||||
|
|
||||||
|
Input: nums = [1,1,1,3,3,4,3,2,4,2]
|
||||||
|
Output: true
|
||||||
|
|
||||||
|
|
||||||
|
**Constraints:**
|
||||||
|
|
||||||
|
* `1 <= nums.length <= 105`
|
||||||
|
* `-109 <= nums[i] <= 109`
|
11
0217_contains-duplicate/python3/solution.py
Normal file
11
0217_contains-duplicate/python3/solution.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
class Solution:
|
||||||
|
def containsDuplicate(self, nums: List[int]) -> bool:
|
||||||
|
counts = {}
|
||||||
|
|
||||||
|
for num in nums:
|
||||||
|
counts[num] = counts.get(num, 0) + 1
|
||||||
|
|
||||||
|
if counts[num] > 1:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
8
0238_product-of-array-except-self/NOTES.md
Normal file
8
0238_product-of-array-except-self/NOTES.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
## What if we were allowed to use division?
|
||||||
|
|
||||||
|
Well, one might think that you can then find product(nums) and divide by nums[i] in the loop. But the problem with this approach is when there are 0s in the array. That causes the entire product to become zero.
|
||||||
|
|
||||||
|
So, we probably need to keep track of zero count and the first zero index.
|
||||||
|
|
||||||
|
1. If there are >1 zeroes, then the result would be all zeroes so.
|
||||||
|
2. If there's only 1 zero, then we need to keep product excluding the zero to be kept. Then fill the result with all zeroes except for the 0 element's index which would equal the product.
|
25
0238_product-of-array-except-self/README.md
Normal file
25
0238_product-of-array-except-self/README.md
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
Given an integer array `nums`, return _an array_ `answer` _such that_ `answer[i]` _is equal to the product of all the elements of_ `nums` _except_ `nums[i]`.
|
||||||
|
|
||||||
|
The product of any prefix or suffix of `nums` is **guaranteed** to fit in a **32-bit** integer.
|
||||||
|
|
||||||
|
You must write an algorithm that runs in `O(n)` time and without using the division operation.
|
||||||
|
|
||||||
|
**Example 1:**
|
||||||
|
|
||||||
|
Input: nums = [1,2,3,4]
|
||||||
|
Output: [24,12,8,6]
|
||||||
|
|
||||||
|
|
||||||
|
**Example 2:**
|
||||||
|
|
||||||
|
Input: nums = [-1,1,0,-3,3]
|
||||||
|
Output: [0,0,9,0,0]
|
||||||
|
|
||||||
|
|
||||||
|
**Constraints:**
|
||||||
|
|
||||||
|
* `2 <= nums.length <= 105`
|
||||||
|
* `-30 <= nums[i] <= 30`
|
||||||
|
* The product of any prefix or suffix of `nums` is **guaranteed** to fit in a **32-bit** integer.
|
||||||
|
|
||||||
|
**Follow up:** Can you solve the problem in `O(1)` extra space complexity? (The output array **does not** count as extra space for space complexity analysis.)
|
25
0238_product-of-array-except-self/python3/solution.py
Normal file
25
0238_product-of-array-except-self/python3/solution.py
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
from functools import reduce
|
||||||
|
|
||||||
|
class Solution:
|
||||||
|
def productExceptSelf(self, nums: List[int]) -> List[int]:
|
||||||
|
# We can divide this problem by finding the prefix and
|
||||||
|
# postfix products of a given element and then multiplying
|
||||||
|
# them together
|
||||||
|
result = [0] * len(nums)
|
||||||
|
|
||||||
|
# Find prefix products, i.e, for ith element, store
|
||||||
|
# product of 0 to a[i - 1]
|
||||||
|
prefix = 1
|
||||||
|
for i, num in enumerate(nums):
|
||||||
|
result[i] = prefix
|
||||||
|
prefix *= num
|
||||||
|
|
||||||
|
# Find suffix products by iterating from the last, and
|
||||||
|
# combine them with prefix in the same step to reduce cost
|
||||||
|
suffix = 1
|
||||||
|
for i in range(len(nums) - 1, -1, -1):
|
||||||
|
result[i] *= suffix
|
||||||
|
suffix *= nums[i]
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
22
0242_valid-anagram/README.md
Normal file
22
0242_valid-anagram/README.md
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
Given two strings `s` and `t`, return `true` _if_ `t` _is an anagram of_ `s`_, and_ `false` _otherwise_.
|
||||||
|
|
||||||
|
An **Anagram** is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.
|
||||||
|
|
||||||
|
**Example 1:**
|
||||||
|
|
||||||
|
Input: s = "anagram", t = "nagaram"
|
||||||
|
Output: true
|
||||||
|
|
||||||
|
|
||||||
|
**Example 2:**
|
||||||
|
|
||||||
|
Input: s = "rat", t = "car"
|
||||||
|
Output: false
|
||||||
|
|
||||||
|
|
||||||
|
**Constraints:**
|
||||||
|
|
||||||
|
* `1 <= s.length, t.length <= 5 * 104`
|
||||||
|
* `s` and `t` consist of lowercase English letters.
|
||||||
|
|
||||||
|
**Follow up:** What if the inputs contain Unicode characters? How would you adapt your solution to such a case?
|
13
0242_valid-anagram/python3/nlogn.py
Normal file
13
0242_valid-anagram/python3/nlogn.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Time: O(NlogN)
|
||||||
|
# Space: O(1)
|
||||||
|
|
||||||
|
from collections import Counter
|
||||||
|
|
||||||
|
class Solution:
|
||||||
|
def isAnagram(self, s: str, t: str) -> bool:
|
||||||
|
slen, tlen = len(s), len(t)
|
||||||
|
|
||||||
|
if slen != tlen:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return sorted(s) == sorted(t)
|
8
0242_valid-anagram/python3/oneliner.py
Normal file
8
0242_valid-anagram/python3/oneliner.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Time: O(N)
|
||||||
|
# Space: O(N)
|
||||||
|
|
||||||
|
from collections import Counter
|
||||||
|
|
||||||
|
class Solution:
|
||||||
|
def isAnagram(self, s: str, t: str) -> bool:
|
||||||
|
return Counter(s) == Counter(t)
|
21
0242_valid-anagram/python3/solution.py
Normal file
21
0242_valid-anagram/python3/solution.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# Time: O(N) where N is num of chars in string
|
||||||
|
# Space: O(N) where N is num of chars in string
|
||||||
|
|
||||||
|
from collections import Counter
|
||||||
|
|
||||||
|
class Solution:
|
||||||
|
def isAnagram(self, s: str, t: str) -> bool:
|
||||||
|
slen, tlen = len(s), len(t)
|
||||||
|
|
||||||
|
if slen != tlen:
|
||||||
|
return False
|
||||||
|
|
||||||
|
scounts, tcounts = {}, {}
|
||||||
|
|
||||||
|
for i in range(slen):
|
||||||
|
sc, tc = s[i], t[i]
|
||||||
|
|
||||||
|
scounts[sc] = scounts.get(sc, 0) + 1
|
||||||
|
tcounts[tc] = tcounts.get(tc, 0) + 1
|
||||||
|
|
||||||
|
return scounts == tcounts
|
41
0347_top-k-frequent-elements/python3/bucketsort.py
Normal file
41
0347_top-k-frequent-elements/python3/bucketsort.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
class Solution:
|
||||||
|
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
|
||||||
|
'''
|
||||||
|
Approach using bucket sort
|
||||||
|
'''
|
||||||
|
|
||||||
|
c = Counter(nums)
|
||||||
|
|
||||||
|
# Idea here is that the list indices will represent
|
||||||
|
# the actual counts and we store elements matching thise
|
||||||
|
# counts under the index. If size n list is provided, max
|
||||||
|
# count possible is n but lists are 0-indexed so we set
|
||||||
|
# num_bucket to have n+1 size.
|
||||||
|
num_bucket = [[] for _ in range(len(nums) + 1)]
|
||||||
|
|
||||||
|
# Later down, we will iterate in reverse through `num_bucket` and
|
||||||
|
# instead of iterating through the entire list, we can take note
|
||||||
|
# of the max count we observe and start from there instead.
|
||||||
|
max_count_seen = -1
|
||||||
|
|
||||||
|
for num, count in c.items():
|
||||||
|
num_bucket[count].append(num)
|
||||||
|
|
||||||
|
max_count_seen = max(max_count_seen, count)
|
||||||
|
|
||||||
|
result = []
|
||||||
|
j = max_count_seen
|
||||||
|
|
||||||
|
# Iterate reverse through num_bucket (note the max_count_seen
|
||||||
|
# optimization) and fill the result array until k elements are
|
||||||
|
# added
|
||||||
|
while j >= 0:
|
||||||
|
for num in num_bucket[j]:
|
||||||
|
result.append(num)
|
||||||
|
|
||||||
|
# Possible that we filled k elements already in this inner
|
||||||
|
# loop, so get out
|
||||||
|
if len(result) == k:
|
||||||
|
return result
|
||||||
|
|
||||||
|
j -= 1
|
@ -1,3 +1,4 @@
|
|||||||
|
from collections import Counter
|
||||||
from heapq import heapify, heappop
|
from heapq import heapify, heappop
|
||||||
|
|
||||||
class Solution:
|
class Solution:
|
||||||
|
Loading…
Reference in New Issue
Block a user