Skip to content

Commit

Permalink
feat(python): solutions
Browse files Browse the repository at this point in the history
  • Loading branch information
hongbo-miao committed May 17, 2022
1 parent 7c94483 commit eb18eba
Show file tree
Hide file tree
Showing 15 changed files with 585 additions and 10 deletions.
2 changes: 1 addition & 1 deletion JavaScript/0315. Count of Smaller Numbers After Self.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*/

// Binary Search
// Traverse from the back to the beginning of the array, maintain an sorted array of numbers have been visited.
// Traverse from the back to the beginning of the array, maintain a sorted array of numbers that have been visited.
// Use binary search to find the first element in the sorted array which is larger or equal to target number.
// For example, [5,2,3,6,1], when we reach 2, we have a sorted array [1,3,6], binary search returns 1,
// which is the index where 2 should be inserted and is also the number smaller than 2.
Expand Down
3 changes: 2 additions & 1 deletion JavaScript/0322. Coin Change.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* @param {number} amount
* @return {number}
*/

// 1) Dynamic Programming
// Similar
// 279. Perfect Squares
Expand Down Expand Up @@ -49,7 +50,7 @@
//
// e.g. coins = [1, 2, 5], amount = 11
// dp =
// [0, 1, I, I, I, I, I, I, I, I, I, I] // I stands for Infinity
// [0, 1, I, I, I, I, I, I, I, I, I, I] // "I" stands for Infinity
// [0, 1, 1, I, I, I, I, I, I, I, I, I]
// [0, 1, 1, 2, I, I, I, I, I, I, I, I]
// [0, 1, 1, 2, 2, I, I, I, I, I, I, I]
Expand Down
1 change: 0 additions & 1 deletion JavaScript/0328. Odd Even Linked List.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@
// odd
// Final head -> 1 -> 3 -> 5 -> 2 -> 4 -> null
// evenHead even
//
const oddEvenList = (head) => {
if (head == null) return null;

Expand Down
77 changes: 77 additions & 0 deletions Python/0315. Count of Smaller Numbers After Self.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# You are given an integer array nums and you have to return a new counts array. The counts array has the property where counts[i] is the number of smaller elements to the right of nums[i].
#
# Example 1:
#
# Input: nums = [5,2,6,1]
# Output: [2,1,1,0]
# Explanation:
# To the right of 5 there are 2 smaller elements (2 and 1).
# To the right of 2 there is only 1 smaller element (1).
# To the right of 6 there is 1 smaller element (1).
# To the right of 1 there is 0 smaller element.
#
# Example 2:
#
# Input: nums = [-1]
# Output: [0]
#
# Example 3:
#
# Input: nums = [-1,-1]
# Output: [0,0]
#
# Constraints:
#
# 1 <= nums.length <= 10^5
# -10^4 <= nums[i] <= 10^4


# 1) Binary Search
# Traverse from the back to the beginning of the array, maintain a sorted array of numbers that have been visited.
# Use binary search to find the first element in the sorted array which is larger or equal to target number.
# For example, [5,2,3,6,1], when we reach 2, we have a sorted array [1,3,6], binary search returns 1,
# which is the index where 2 should be inserted and is also the number smaller than 2.
# Then we insert 2 into the sorted array to form [1,2,3,6].
class Solution:
def countSmaller(self, nums: List[int]) -> List[int]:
if not nums:
return []
if len(nums) == 1:
return [0]
res = [0] * len(nums)
sorted = []
for i in range(len(nums) - 1, -1, -1):
idx = self.lower_bound(sorted, nums[i])
res[i] = idx
sorted.insert(idx, nums[i])
return res

def lower_bound(self, nums: List[int], target: int) -> int:
l = 0
r = len(nums)
while l < r:
m = (l + r) // 2
if nums[m] < target: # Note <
l = m + 1
else:
r = m
return l


# 2) Binary Search, similar to 1)
import bisect


class Solution:
def countSmaller(self, nums: List[int]) -> List[int]:
if not nums:
return []
if len(nums) == 1:
return [0]
res = [0] * len(nums)
sorted = []
for i in range(len(nums) - 1, -1, -1):
idx = bisect.bisect_left(sorted, nums[i])
res[i] = idx
sorted.insert(idx, nums[i])
return res
82 changes: 82 additions & 0 deletions Python/0322. Coin Change.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# You are given an integer array coins representing coins of different denominations and an integer amount representing a total amount of money.
# Return the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.
# You may assume that you have an infinite number of each kind of coin.
#
# Example 1:
#
# Input: coins = [1,2,5], amount = 11
# Output: 3
# Explanation: 11 = 5 + 5 + 1
#
# Example 2:
#
# Input: coins = [2], amount = 3
# Output: -1
#
# Example 3:
#
# Input: coins = [1], amount = 0
# Output: 0
#
# Constraints:
#
# 1 <= coins.length <= 12
# 1 <= coins[i] <= 2^31 - 1
# 0 <= amount <= 10^4


# 1) Dynamic Programming
# Similar
# 279. Perfect Squares
# 300. Longest Increasing Subsequence
# 322. Coin Change
#
# https://leetcode.com/problems/coin-change/discuss/77377/Javascript-Solution-(faster-than-90%2B-submissions)-*added-explanation
# changes is an array to store the least amount of coins we need to make up a certain amount of money, the index of
# changes means the amount of money to make up, so changes[x] means to make up money amount x how many coins we need at least
#
# Now, imagine if changes[0] ... to changes[10] is already known, and we need to calculate changes[11], coins = [1, 2, 5],
# we know we have to take at least one coin from coins list otherwise we won't be able to make up 11
#
# If we take coins[0] which has value 1, and now the total amount of money we need to make up becomes 10, and how many
# coins we need at least to make up 10 is known already as changes[10], so if we take coins[0] to make up amount 11,
# the least amount of coins we need will be 1 + changes[10]
#
# If we take coins[1] which has value 2, the least amount of coins we need will be 1 + changes[9]
# If we take coins[2] which has value 5, the least amount of coins we need will be 1 + changes[6]
#
# changes[11] = min(1 + changes[10], 1 + changes[9], 1 + changes[6])
#
# From the explanation above, we can see that to calculate changes[x], we will need to know the values from changes[0]
# to changes[x-1], so in order to know changes[x] we start to calculate from changes[0]
#
# Corner cases are when the amount remaining to make up is less than the coin value, in this case, we simply continue
# to the next coin, and if all coins values are greater than the amount to make up (changes[amount] will equal to
# Infinity), that means we don't have any coin to make up that amount, so return -1
#
# e.g. coins = [1, 2, 5], amount = 11
# dp =
# [0, 1, I, I, I, I, I, I, I, I, I, I] # "I" stands for Infinity
# [0, 1, 1, I, I, I, I, I, I, I, I, I]
# [0, 1, 1, 2, I, I, I, I, I, I, I, I]
# [0, 1, 1, 2, 2, I, I, I, I, I, I, I]
# [0, 1, 1, 2, 2, 1, I, I, I, I, I, I]
# [0, 1, 1, 2, 2, 1, 2, I, I, I, I, I]
# [0, 1, 1, 2, 2, 1, 2, 2, I, I, I, I]
# [0, 1, 1, 2, 2, 1, 2, 2, 3, I, I, I]
# [0, 1, 1, 2, 2, 1, 2, 2, 3, 3, I, I]
# [0, 1, 1, 2, 2, 1, 2, 2, 3, 3, 2, I]
# [0, 1, 1, 2, 2, 1, 2, 2, 3, 3, 2, 3]
class Solution:
def coinChange(self, coins: List[int], amount: int) -> int:
dp = [float("inf")] * (amount + 1)
dp[0] = 0
for i in range(1, amount + 1):
for coin in coins:
if i >= coin:
dp[i] = min(dp[i], dp[i - coin] + 1)
return dp[amount] if dp[amount] != float("inf") else -1


# 2) DFS + Greedy + Pruning
# https://youtu.be/uUETHdijzkA
46 changes: 46 additions & 0 deletions Python/0324. Wiggle Sort II.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Given an integer array nums, reorder it such that nums[0] < nums[1] > nums[2] < nums[3]....
# You may assume the input array always has a valid answer.
#
# Example 1:
#
# Input: nums = [1,5,1,1,6,4]
# Output: [1,6,1,5,1,4]
# Explanation: [1,4,1,5,1,6] is also accepted.
#
# Example 2:
#
# Input: nums = [1,3,2,2,3,1]
# Output: [2,3,1,3,1,2]
#
# Constraints:
#
# 1 <= nums.length <= 5 * 10^4
# 0 <= nums[i] <= 5000
# It is guaranteed that there will be an answer for the given input nums.
#
# Follow Up: Can you do it in O(n) time and/or in-place with O(1) extra space?


# 1)
class Solution:
def wiggleSort(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
nums.sort()
l = len(nums)
m = l // 2
k = m - 1 if l % 2 == 0 else m # middle index

copy = nums[:]
j = l - 1
for i in range(0, l, 2):
nums[i] = copy[k]
if i < l - 1:
nums[i + 1] = copy[j]
k -= 1
j -= 1


# 2)
# https://leetcode.com/problems/wiggle-sort-ii/discuss/77682/Step-by-step-explanation-of-index-mapping-in-Java
46 changes: 46 additions & 0 deletions Python/0326. Power of Three.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Given an integer n, return true if it is a power of three. Otherwise, return false.
# An integer n is a power of three, if there exists an integer x such that n == 3x.
#
# Example 1:
#
# Input: n = 27
# Output: true
#
# Example 2:
#
# Input: n = 0
# Output: false
#
# Example 3:
#
# Input: n = 9
# Output: true
#
# Constraints:
#
# -2^31 <= n <= 2^31 - 1


# 1)
# Time O(log n). In our case that is O(log3 n). The number of divisions is given by that logarithm.
# Space O(1)
class Solution:
def isPowerOfThree(self, n: int) -> bool:
if n <= 0:
return False
while n % 3 == 0:
n /= 3
return n == 1


# 2) Mathematics
# n = 3^i
# i = log3(n)
# i = log10(n) / log10(3)
import math


class Solution:
def isPowerOfThree(self, n: int) -> bool:
# using % 1 to get the decimal part
return n > 0 and (math.log10(n) / math.log10(3)) % 1 == 0
48 changes: 48 additions & 0 deletions Python/0328. Odd Even Linked List.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Given the head of a singly linked list, group all the nodes with odd indices together followed by the nodes with even indices, and return the reordered list.
# The first node is considered odd, and the second node is even, and so on.
# Note that the relative order inside both the even and odd groups should remain as it was in the input.
# You must solve the problem in O(1) extra space complexity and O(n) time complexity.
#
# Example 1:
#
# Input: head = [1,2,3,4,5]
# Output: [1,3,5,2,4]
#
# Example 2:
#
# Input: head = [2,1,3,5,6,4,7]
# Output: [2,3,6,7,1,5,4]
#
# Constraints:
#
# The number of nodes in the linked list is in the range [0, 10^4].
# -10^6 <= Node.val <= 10^6


# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next


# Notion

# Time O(n)
# Space O(1)
class Solution:
def oddEvenList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if not head:
return None

odd = head
even = head.next

even_head = even
while even and even.next:
odd.next = even.next
odd = odd.next
even.next = odd.next
even = even.next
odd.next = even_head
return head
54 changes: 54 additions & 0 deletions Python/0329. Longest Increasing Path in a Matrix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Given an m x n integers matrix, return the length of the longest increasing path in matrix.
# From each cell, you can either move in four directions: left, right, up, or down. You may not move diagonally or move outside the boundary (i.e., wrap-around is not allowed).
#
# Example 1:
#
# Input: matrix = [[9,9,4],[6,6,8],[2,1,1]]
# Output: 4
# Explanation: The longest increasing path is [1, 2, 6, 9].
#
# Example 2:
#
# Input: matrix = [[3,4,5],[3,2,6],[2,2,1]]
# Output: 4
# Explanation: The longest increasing path is [3, 4, 5, 6]. Moving diagonally is not allowed.
#
# Example 3:
#
# Input: matrix = [[1]]
# Output: 1
#
# Constraints:
#
# m == matrix.length
# n == matrix[i].length
# 1 <= m, n <= 200
# 0 <= matrix[i][j] <= 2^31 - 1


# Backtracking + Memoization
class Solution:
def longestIncreasingPath(self, matrix: List[List[int]]) -> int:
if not matrix:
return 0
m, n = len(matrix), len(matrix[0])
dirs = [(1, 0), (-1, 0), (0, 1), (0, -1)]
cache = [[None] * n for _ in range(m)]

def go(x, y):
if cache[x][y] is not None:
return cache[x][y]
mx = 1
for dx, dy in dirs:
i = x + dx
j = y + dy
if 0 <= i < m and 0 <= j < n and matrix[i][j] > matrix[x][y]:
mx = max(mx, go(i, j) + 1)
cache[x][y] = mx
return mx

mx = 0
for i in range(m):
for j in range(n):
mx = max(mx, go(i, j))
return mx
Loading

0 comments on commit eb18eba

Please sign in to comment.