My Notes - LeetCode

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 31

8/25/2020 My Notes - LeetCode

23. Merge k Sorted Lists 


Given an array of linked-lists lists, each linked list is sorted in ascending order.

Merge all the linked-lists into one sort linked-list and return it.

Example 1:

Input: lists = [[1,4,5],[1,3,4],[2,6]]


Output: [1,1,2,3,4,4,5,6]
Explanation: The linked-lists are:
[
1->4->5,
1->3->4,
2->6
]
merging them into one sorted list:
1->1->2->3->4->4->5->6

Example 2:

Input: lists = []
Output: []

Example 3:

Input: lists = [[]]


Output: []

Constraints:

k == lists.length
0 <= k <= 10^4
0 <= lists[i].length <= 500
-10^4 <= lists[i][j] <= 10^4
lists[i] is sorted in ascending order.
The sum of lists[i].length won't exceed 10^4 .

Given an array of linked-lists lists, each linked list is sorted in ascending order.

Merge all the linked-lists into one sort linked-list and return it.

https://leetcode.com/notes/ 1/31
8/25/2020 My Notes - LeetCode

Example 1:

Input: lists = [[1,4,5],[1,3,4],[2,6]]


Output: [1,1,2,3,4,4,5,6]
Explanation: The linked-lists are:
[
1->4->5,
1->3->4,
2->6
]
merging them into one sorted list:
1->1->2->3->4->4->5->6

struct compare {
bool operator()(const ListNode* l, const ListNode* r) {
return l->val > r->val;
}
};

ListNode *mergeKLists(vector<ListNode *> &lists) {


std::priority_queue<ListNode*, std::vector<ListNode*>, compare > heap;
ListNode head(0);
ListNode *curNode = &head;
int i, k, n = lists.size();
for (i = 0; i < n; i++)
if (lists[i]) heap.push(lists[i]);
while (!heap.empty()){
curNode->next = heap.top();
heap.pop();
curNode = curNode->next;
if (curNode->next) heap.push(curNode->next);
}
return head.next;
}

Here are some example how to use the compare-component-function

-Method 1 -

std::priority_queue<int, std::vector<int>, decltype(&compare)> pq(&compare); The compare can


be any your defined function

-Method 2-

You can use the default less function

std::priority_queue<int, std::vector<int>, std::less<int> > pq; -Method 3-

You can use the lamda-expression

auto comp = [] (int &a, int &b) -> bool { return a < b; };
std::priority_queue<int,std::vector<int>, decltype(comp) > pq (comp);

31. Next Permutation 


https://leetcode.com/notes/ 2/31
8/25/2020 My Notes - LeetCode

Implement next permutation, which rearranges numbers into the lexicographically next greater
permutation of numbers.

If such arrangement is not possible, it must rearrange it as the lowest possible order (ie, sorted in
ascending order).

The replacement must be in-place (http://en.wikipedia.org/wiki/In-place_algorithm) and use only


constant extra memory.

Here are some examples. Inputs are in the left-hand column and its corresponding outputs are in the
right-hand column.

1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

According to Wikipedia, a man named Narayana Pandita presented the following simple algorithm to
solve this problem in the 14th century.

ALGORITHM :

* Find the largest index k such that nums[k] < nums[k + 1]. If no such index exists, jus
t reverse nums and done.
* Find the largest index l > k such that nums[k] < nums[l].
* Swap nums[k] and nums[l].
* Reverse the sub-array nums[k + 1:].

class Solution {
public:
void nextPermutation(vector<int>& nums) {
int n = nums.size(), k, l;
for (k = n - 2; k >= 0; k--) {
if (nums[k] < nums[k + 1]) {
break;
}
}
if (k < 0) {
reverse(nums.begin(), nums.end());
} else {
for (l = n - 1; l > k; l--) {
if (nums[l] > nums[k]) {
break;
}
}
swap(nums[k], nums[l]);
reverse(nums.begin() + k + 1, nums.end());
}
}
};

The above algorithm can also handle duplicates and thus can be further used to solve Permutations and
Permutations II.

https://leetcode.com/notes/ 3/31
8/25/2020 My Notes - LeetCode

76. Minimum Window Substring 


Given a string S and a string T, find the minimum window in S which will contain all the characters in T in
complexity O(n).

Example:

Input: S = "ADOBECODEBANC", T = "ABC"


Output: "BANC"

Note:

If there is no such window in S that covers all characters in T, return the empty string "" .
If there is such window, you are guaranteed that there will always be only one unique minimum
window in S.

Given a string S and a string T, find the minimum window in S which will contain all the characters in T in
complexity O(n).

Example:

Input: S = "ADOBECODEBANC", T = "ABC"


Output: "BANC"

https://leetcode.com/notes/ 4/31
8/25/2020 My Notes - LeetCode

class Solution:
def minWindow(self, s: str, t: str) -> str:
#stores t char frequency
dict_t = Counter(t)
#current state
state = Counter()
#number of characters required
req = len(dict_t)
#two pointers
i=j=0
#currently formed
formed=0
#ans that contains length and starting index
ans = float('inf'),None

while j<len(s):

char = s[j]
#if current character we can include
if(char in dict_t):
#update current state
state[char]+=1
#if frequency of current character is equal to frequency in t .. increme
nt Formed
if(state[char]==dict_t[char]):
formed+=1
#while current window is valid
while i<=j and req == formed:
char = s[i]
if(j-i+1<ans[0]):
ans = j-i+1,i
# Try to shrink window
if(char in dict_t):
state[char]-=1
# if removal of current character doesn't satisy constraint then decreme
nt formed
if(state[char]==dict_t[char]-1):
formed-=1
i+=1
j+=1
return "" if ans[0]==float('inf') else s[ans[1]:ans[1]+ans[0]]

87. Scramble String 


Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings
recursively.

Below is one possible representation of s1 = "great" :

https://leetcode.com/notes/ 5/31
8/25/2020 My Notes - LeetCode

great
/ \
gr eat
/ \ / \
g r e at
/ \
a t

To scramble the string, we may choose any non-leaf node and swap its two children.

For example, if we choose the node "gr" and swap its two children, it produces a scrambled string
"rgeat" .

rgeat
/ \
rg eat
/ \ / \
r g e at
/ \
a t

We say that "rgeat" is a scrambled string of "great" .

Similarly, if we continue to swap the children of nodes "eat" and "at" , it produces a scrambled string
"rgtae" .

rgtae
/ \
rg tae
/ \ / \
r g ta e
/ \
t a

We say that "rgtae" is a scrambled string of "great" .

Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.

Example 1:

Input: s1 = "great", s2 = "rgeat"


Output: true

Example 2:

Input: s1 = "abcde", s2 = "caebd"


Output: false

It is exponential solution acc. to big O notation but its quite fast due to pruning.

https://leetcode.com/notes/ 6/31
8/25/2020 My Notes - LeetCode

class Solution:
def isScramble(self, s1: str, s2: str) -> bool:
n,m = len(s1),len(s2)
if n!=m or sorted(s1)!=sorted(s2):
return False
if n<4 or s1==s2:
return True
f = self.isScramble
for i in range(1,n):
if((f(s1[:i],s2[:i]) and f(s1[i:],s2[i:])) or (f(s1[:i],s2[-i:]) and f(s1
[i:],s2[:-i]))):
return True
return False

94. Binary Tree Inorder Traversal 


Given a binary tree, return the inorder traversal of its nodes' values.

Example:

Input: [1,null,2,3]
1
\
2
/
3

Output: [1,3,2]

Follow up: Recursive solution is trivial, could you do it iteratively?

Here there are 3 states in a stack where 0 means preorder 1 means inorder and 2 means postorder
traversal.

if state is 0 : then update its state to 1 and push left child to stack if state is 1 : then make its state to 2 and
push right child to stack if state is 2 : just pop the element

We can modify this code to get pre and post order as well by simply changing order of appending result to
ans.

https://leetcode.com/notes/ 7/31
8/25/2020 My Notes - LeetCode

def inorderTraversal(self, root: TreeNode) -> List[int]:


if root ==None:
return []
st = [[root,0]]
ans =[]
while(len(st)>0):
curr = st[-1]
if curr[1]==0:
curr[1] =1
if curr[0].left!=None:
st.append([curr[0].left,0])
elif curr[1]==1:
ans.append(curr[0].val)
if(curr[0].right):
st.append([curr[0].right,0])
curr[1]=2
else:
st.pop()
return ans

97. Interleaving String 


Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.

Example 1:

Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"


Output: true

Example 2:

Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"


Output: false

BFS Approach: If we expand the two strings s1 and s2 into a chessboard, then this problem can be
transferred into a path seeking problem from the top-left corner to the bottom-right corner. The key is,
each cell (y, x) in the board corresponds to an interval between y-th character in s1 and x-th character in
s2. And adjacent cells are connected with like a grid. A BFS can then be efficiently performed to find the
path.

Better to illustrate with an example here:

Say s1 = "aab" and s2 = "abc". s3 = "aaabcb". Then the board looks like

https://leetcode.com/notes/ 8/31
8/25/2020 My Notes - LeetCode

o--a--o--b--o--c--o
| | | |
a a a a
| | | |
o--a--o--b--o--c--o
| | | |
a a a a
| | | |
o--a--o--b--o--c--o
| | | |
b b b b
| | | |
o--a--o--b--o--c--o

class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
// BFS version
int l1 = s1.size(), l2 = s2.size(), l3 = s3.size();
if (l1 + l2 != l3) return false;

vector<vector<bool>> visited(l1 + 1, vector<bool>(l2 + 1, false));


queue<pair<int, int>> myqueue;
myqueue.push(pair<int, int>(0, 0));

while(!myqueue.empty()) {
auto p = myqueue.front();
myqueue.pop();
if (p.first == l1 && p.second == l2) {
return true;
}
if (visited[p.first][p.second]) continue;
if (p.first < l1 && s1[p.first] == s3[p.first + p.second]) {
myqueue.push(pair<int, int>(p.first + 1, p.second));
}
if (p.second < l2 && s2[p.second] == s3[p.first + p.second]) {
myqueue.push(pair<int, int>(p.first, p.second + 1));
}
visited[p.first][p.second] = true;
}
return false;
}
};

DP Solution :

https://leetcode.com/notes/ 9/31
8/25/2020 My Notes - LeetCode

bool isInterleave(string s1, string s2, string s3) {

if(s3.length() != s1.length() + s2.length())


return false;

bool table[s1.length()+1][s2.length()+1];

for(int i=0; i<s1.length()+1; i++)


for(int j=0; j< s2.length()+1; j++){
if(i==0 && j==0)
table[i][j] = true;
else if(i == 0)
table[i][j] = ( table[i][j-1] && s2[j-1] == s3[i+j-1]);
else if(j == 0)
table[i][j] = ( table[i-1][j] && s1[i-1] == s3[i+j-1]);
else
table[i][j] = (table[i-1][j] && s1[i-1] == s3[i+j-1] ) || (table[i][j-1]
&& s2[j-1] == s3[i+j-1] );
}

return table[s1.length()][s2.length()];
}

115. Distinct Subsequences 


Given a string S and a string T, count the number of distinct subsequences of S which equals T.

A subsequence of a string is a new string which is formed from the original string by deleting some (can
be none) of the characters without disturbing the relative positions of the remaining characters. (ie, "ACE"
is a subsequence of "ABCDE" while "AEC" is not).

It's guaranteed the answer fits on a 32-bit signed integer.

Example 1:

Input: S = "rabbbit", T = "rabbit"


Output: 3
Explanation:
As shown below, there are 3 ways you can generate "rabbit" from S.
(The caret symbol ^ means the chosen letters)

rabbbit
^^^^ ^^
rabbbit
^^ ^^^^
rabbbit
^^^ ^^^

Example 2:

https://leetcode.com/notes/ 10/31
8/25/2020 My Notes - LeetCode

Input: S = "babgbag", T = "bag"


Output: 5
Explanation:
As shown below, there are 5 ways you can generate "bag" from S.
(The caret symbol ^ means the chosen letters)

babgbag
^^ ^
babgbag
^^ ^
babgbag
^ ^^
babgbag
^ ^^
babgbag
^^^

Well, a dynamic programming problem. Let's first define its state dp[i][j] to be the number of distinct
subsequences of t[0..i - 1] in s[0..j - 1]. Then we have the following state equations:

General case 1: dp[i][j] = dp[i][j - 1] if t[i - 1] != s[j - 1];

General case 2: dp[i][j] = dp[i][j - 1] + dp[i - 1][j - 1] if t[i - 1] == s[j - 1];

Boundary case 1: dp[0][j] = 1 for all j;

Boundary case 2: dp[i][0] = 0 for all positive i.

Now let's give brief explanations to the four equations above.

If t[i - 1] != s[j - 1], the distinct subsequences will not include s[j - 1] and thus all the number of distinct
subsequences will simply be those in s[0..j - 2], which corresponds to dp[i][j - 1];

If t[i - 1] == s[j - 1], the number of distinct subsequences include two parts: those with s[j - 1] and those
without; An empty string will have exactly one subsequence in any string :-) Non-empty string will have no
subsequences in an empty string. Putting these together, we will have the following simple codes (just like
translation :-)):

class Solution {
public:
int numDistinct(string s, string t) {
int m = t.length(), n = s.length();
vector<vector<int>> dp(m + 1, vector<int> (n + 1, 0));
for (int j = 0; j <= n; j++) dp[0][j] = 1;
for (int j = 1; j <= n; j++)
for (int i = 1; i <= m; i++)
dp[i][j] = dp[i][j - 1] + (t[i - 1] == s[j - 1] ? dp[i - 1][j - 1] : 0);
return dp[m][n];
}
};

Notice that we keep the whole m*n matrix simply for dp[i - 1][j - 1]. So we can simply store that
value in a single variable and further optimize the space complexity. The final code is as follows.

https://leetcode.com/notes/ 11/31
8/25/2020 My Notes - LeetCode

int numDistinct(string s, string t) {


int n = s.length(), m = t.length();
vector<int> dp(m+1, 0);
dp[0] = 1;
for (int j = 1; j <= n; j++){
for (int i = m; i >= 1; i--){
dp[i] += s[j-1] == t[i-1] ? dp[i-1] : 0;
}
}
return dp[m];
}

};

131. Palindrome Partitioning 


Given a string s, partition s such that every substring of the partition is a palindrome.

Return all possible palindrome partitioning of s.

Example:

Input: "aab"
Output:
[
["aa","b"],
["a","a","b"]
]

39. Combination Sum


https://leetcode.com/problems/combination-sum/ (https://leetcode.com/problems/combination-sum/) Given
a set of candidate numbers (candidates) (without duplicates) and a target number (target), find all unique
combinations in candidates where the candidate numbers sums to target

Input: candidates = [2,3,6,7], target = 7,


A solution set is:
[
[7],
[2,2,3]
]

https://leetcode.com/notes/ 12/31
8/25/2020 My Notes - LeetCode

def combinationSum(self, candidates, target):


def backtrack(tmp, start, end, target):
if target == 0:
ans.append(tmp[:])
elif target > 0:
for i in range(start, end):
tmp.append(candidates[i])
backtrack(tmp, i, end, target - candidates[i])
tmp.pop()
ans = []
candidates.sort(reverse= True)
backtrack([], 0, len(candidates), target)
return ans

40. Combination Sum II


https://leetcode.com/problems/combination-sum-ii/ (https://leetcode.com/problems/combination-sum-ii/)

Given a collection of candidate numbers (candidates) and a target number (target), find all unique
combinations in candidates where the candidate numbers sums to target.

Each number in candidates may only be used once in the combination.

Input: candidates = [10,1,2,7,6,1,5], target = 8,


A solution set is:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]

def combinationSum2(self, candidates, target):


def backtrack(start, end, tmp, target):
if target == 0:
ans.append(tmp[:])
elif target > 0:
for i in range(start, end):
if i > start and candidates[i] == candidates[i-1]:
continue
tmp.append(candidates[i])
backtrack(i+1, end, tmp, target - candidates[i])
tmp.pop()
ans = []
candidates.sort(reverse= True)
backtrack(0, len(candidates), [], target)
return ans

78. Subsets
https://leetcode.com/problems/subsets/ (https://leetcode.com/problems/subsets/)

Given a set of distinct integers, nums, return all possible subsets (the power set).

Note: The solution set must not contain duplicate subsets.

https://leetcode.com/notes/ 13/31
8/25/2020 My Notes - LeetCode

Input: nums = [1,2,3]


Output:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]

def subsets(self, nums):


def backtrack(start, end, tmp):
ans.append(tmp[:])
for i in range(start, end):
tmp.append(nums[i])
backtrack(i+1, end, tmp)
tmp.pop()
ans = []
backtrack(0, len(nums), [])
return ans

90. Subsets II
https://leetcode.com/problems/subsets-ii/ (https://leetcode.com/problems/subsets-ii/)

Given a collection of integers that might contain duplicates, nums, return all possible subsets (the power
set).

Note: The solution set must not contain duplicate subsets.

Example:

Input: [1,2,2]
Output:
[
[2],
[1],
[1,2,2],
[2,2],
[1,2],
[]
]

https://leetcode.com/notes/ 14/31
8/25/2020 My Notes - LeetCode

def subsetsWithDup(self, nums):


def backtrack(start, end, tmp):
ans.append(tmp[:])
for i in range(start, end):
if i > start and nums[i] == nums[i-1]:
continue
tmp.append(nums[i])
backtrack(i+1, end, tmp)
tmp.pop()
ans = []
nums.sort()
backtrack(0, len(nums), [])
return ans

46. Permutations
https://leetcode.com/problems/permutations/ (https://leetcode.com/problems/permutations/)

Given a collection of distinct integers, return all possible permutations.

Example:

Input: [1,2,3]
Output:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]

def permute(self, nums):


def backtrack(start, end):
if start == end:
ans.append(nums[:])
for i in range(start, end):
nums[start], nums[i] = nums[i], nums[start]
backtrack(start+1, end)
nums[start], nums[i] = nums[i], nums[start]

ans = []
backtrack(0, len(nums))
return ans

47. Permutations II
https://leetcode.com/problems/permutations-ii/ (https://leetcode.com/problems/permutations-ii/)

Given a collection of numbers that might contain duplicates, return all possible unique permutations.

https://leetcode.com/notes/ 15/31
8/25/2020 My Notes - LeetCode

Example:

Input: [1,1,2]
Output:
[
[1,1,2],
[1,2,1],
[2,1,1]
]

def permuteUnique(self, nums):


def backtrack(tmp, size):
if len(tmp) == size:
ans.append(tmp[:])
else:
for i in range(size):
if visited[i] or (i > 0 and nums[i-1] == nums[i] and not
visited[i-1]):
continue
visited[i] = True
tmp.append(nums[i])
backtrack(tmp, size)
tmp.pop()
visited[i] = False
ans = []
visited = [False] * len(nums)
nums.sort()
backtrack([], len(nums))
return ans

60. Permutation Sequence


https://leetcode.com/problems/permutation-sequence/ (https://leetcode.com/problems/permutation-
sequence/)

The set [1,2,3,...,n] contains a total of n! unique permutations.

By listing and labeling all of the permutations in order, we get the following sequence for n = 3:

"123"
"132"
"213"
"231"
"312"
"321" Given n and k, return the kth permutation sequence.

Input: n = 4, k = 9
Output: "2314"

https://leetcode.com/notes/ 16/31
8/25/2020 My Notes - LeetCode

def getPermutation(self, n, k):


nums = [str(i) for i in range(1, n+1)]
fact = [1] * n
for i in range(1,n):
fact[i] = i*fact[i-1]
k -= 1
ans = []
for i in range(n, 0, -1):
id = k / fact[i-1]
k %= fact[i-1]
ans.append(nums[id])
nums.pop(id)
return ''.join(ans)

131. Palindrome Partitioning


https://leetcode.com/problems/palindrome-partitioning/ (https://leetcode.com/problems/palindrome-
partitioning/)

Given a string s, partition s such that every substring of the partition is a palindrome.

Return all possible palindrome partitioning of s.

Example:

Input: "aab"
Output:
[
["aa","b"],
["a","a","b"]
]

def partition(self, s):


def backtrack(start, end, tmp):
if start == end:
ans.append(tmp[:])
for i in range(start, end):
cur = s[start:i+1]
if cur == cur[::-1]:
tmp.append(cur)
backtrack(i+1, end, tmp)
tmp.pop()
ans = []
backtrack(0, len(s), [])
return ans

267. Palindrome Permutation II https://leetcode.com/problems/palindrome-permutation-ii/


(https://leetcode.com/problems/palindrome-permutation-ii/) Related to this two:

268. Next Permutation: https://leetcode.com/problems/next-permutation/


(https://leetcode.com/problems/next-permutation/)

269. Palindrome Permutation: https://leetcode.com/problems/palindrome-permutation/


(https://leetcode.com/problems/palindrome-permutation/)

https://leetcode.com/notes/ 17/31
8/25/2020 My Notes - LeetCode

def generatePalindromes(self, s):


kv = collections.Counter(s)
mid = [k for k, v in kv.iteritems() if v%2]
if len(mid) > 1:
return []
mid = '' if mid == [] else mid[0]
half = ''.join([k * (v/2) for k, v in kv.iteritems()])
half = [c for c in half]

def backtrack(end, tmp):


if len(tmp) == end:
cur = ''.join(tmp)
ans.append(cur + mid + cur[::-1])
else:
for i in range(end):
if visited[i] or (i>0 and half[i] == half[i-1] and not visited[i-
1]):
continue
visited[i] = True
tmp.append(half[i])
backtrack(end, tmp)
visited[i] = False
tmp.pop()

ans = []
visited = [False] * len(half)
backtrack(len(half), [])
return ans

139. Word Break 


Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if
s can be segmented into a space-separated sequence of one or more dictionary words.

Note:

The same word in the dictionary may be reused multiple times in the segmentation.
You may assume the dictionary does not contain duplicate words.

Example 1:

Input: s = "leetcode", wordDict = ["leet", "code"]


Output: true
Explanation: Return true because "leetcode" can be segmented as "leet code".

Example 2:

Input: s = "applepenapple", wordDict = ["apple", "pen"]


Output: true
Explanation: Return true because "applepenapple" can be segmented as "apple pen apple".
Note that you are allowed to reuse a dictionary word.

Example 3:

https://leetcode.com/notes/ 18/31
8/25/2020 My Notes - LeetCode

Input: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]


Output: false

Given a non-empty string s and a dictionary wordDict containing a list of non-empty words, determine if s
can be segmented into a space-separated sequence of one or more dictionary words.

Input: s = "leetcode", wordDict = ["leet", "code"]


Output: true
Explanation: Return true because "leetcode" can be segmented as "leet code".

class Solution:
def wordBreak(self, A: str, B: List[str]) -> bool:
B = set(B)
n = len(A)
dp = [False]*(n+1)
dp[0] = True
for i in range(1,n+1):
for j in range(i-1,-1,-1):
if dp[j]:
if A[j:i] in B:
dp[i] = True
break
return dp[n]

We use a boolean vector dp[]. dp[i] is set to true if a valid word (word sequence) ends there. The
optimization is to look from current position i back and only substring and do dictionary look up in case the
preceding position j with dp[j] == true is found.

300. Longest Increasing Subsequence 


Given an unsorted array of integers, find the length of longest increasing subsequence.

Example:

Input: [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is
4.

Note:

There may be more than one LIS combination, it is only necessary for you to return the length.
Your algorithm should run in O(n2) complexity.

Follow up: Could you improve it to O(n log n) time complexity?

Here ans contains longest increasing subsequence.When the curr element is greater than all element
just append it to ans otherwise replace its lower bound to ans.

https://leetcode.com/notes/ 19/31
8/25/2020 My Notes - LeetCode

from bisect import bisect_left


class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
n = len(nums)
if n==0:
return 0
ans = []

for i in range(n):
if len(ans)==0:
ans.append(nums[i])
else:
ind = bisect_left(ans,nums[i])
if ind ==len(ans):
ans.append(nums[i])
else:
ans[ind] = nums[i]
return len(ans)

399. Evaluate Division 


Equations are given in the format A / B = k , where A and B are variables represented as strings, and
k is a real number (floating point number). Given some queries, return the answers. If the answer does
not exist, return -1.0 .

Example:
Given a / b = 2.0, b / c = 3.0.
queries are: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ? .
return [6.0, 0.5, -1.0, 1.0, -1.0 ].

The input is: vector<pair<string, string>> equations, vector<double>& values,


vector<pair<string, string>> queries , where equations.size() == values.size() , and the values
are positive. This represents the equations. Return vector<double> .

According to the example above:

equations = [ ["a", "b"], ["b", "c"] ],


values = [2.0, 3.0],
queries = [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ].

The input is always valid. You may assume that evaluating the queries will result in no division by zero
and there is no contradiction.

Although this looks like a math problem, we can easily model it with graph.

For example: Given: a/b = 2.0, b/c = 3.0 We can build a directed graph: a -- 2.0 --> b -- 3.0 --> c If we
were asked to find a/c, we have: a/c = a/b * b/c = 2.0 * 3.0 In the graph, it is the product of costs of edges.

https://leetcode.com/notes/ 20/31
8/25/2020 My Notes - LeetCode

Do notice that, 2 edges need to added into the graph with one given equation, because with a/b we also
get result of b/a, which is the reciprocal of a/b.

class Solution(object):
def calcEquation(self, equations, values, queries):

graph = {}

def build_graph(equations, values):


def add_edge(f, t, value):
if f in graph:
graph[f].append((t, value))
else:
graph[f] = [(t, value)]

for vertices, value in zip(equations, values):


f, t = vertices
add_edge(f, t, value)
add_edge(t, f, 1/value)

def find_path(query):
b, e = query

if b not in graph or e not in graph:


return -1.0

q = collections.deque([(b, 1.0)])
visited = set()

while q:
front, cur_product = q.popleft()
if front == e:
return cur_product
visited.add(front)
for neighbor, value in graph[front]:
if neighbor not in visited:
q.append((neighbor, cur_product*value))

return -1.0

build_graph(equations, values)
return [find_path(q) for q in queries]

653. Two Sum IV - Input is a BST 


Given a Binary Search Tree and a target number, return true if there exist two elements in the BST such
that their sum is equal to the given target.

Example 1:

https://leetcode.com/notes/ 21/31
8/25/2020 My Notes - LeetCode

Input:
5
/ \
3 6
/ \ \
2 4 7

Target = 9

Output: True

Example 2:

Input:
5
/ \
3 6
/ \ \
2 4 7

Target = 28

Output: False

Using Binary Search Tree Iterator:


We have used two stacks one for inorder in forward direction(For traversing in increasing order) and
other for inorder in backward direction(in decreasing order). Idea is same as finding two sum in a sorted
array.

https://leetcode.com/notes/ 22/31
8/25/2020 My Notes - LeetCode

int get_next_left(stack<int>&st)
{
if(st.size()>0)
{
TreeNode* curr = st.top();
st.pop();
pushAll_left(curr->right,st);
return curr->val;

}else
{
return -1;
}
}

int get_next_right(stack<int>&st)
{

if(st.size()>0)
{
TreeNode* curr = st.top();
st.pop();
pushAll_right(curr->left,st);
return curr->val;

}else
{
return -1;
}
}
void pushAll_left(TreeNode* root,stack<int>&st)
{
while(root !=NULL)
{
st.push(root);
root = root->left;
}
}
void pushAll_right(TreeNode* root,stack<int>&st)
{
while(root !=NULL)
{
st.push(root);
root = root->right;
}
}
bool solve(TreeNode* root,int tar)
{
stack<TreeNode*>ls;
stack<TreeNode*>rs;
pushAll_left(root,ls);
pushAll_right(root,rs);
int left = get_next_left(ls);
int right = get_next_right(rs);
while(left<right)
{
if(left+right==tar)

https://leetcode.com/notes/ 23/31
8/25/2020 My Notes - LeetCode

{
return true;
}else if(left+right<tar)
{
left = get_next_left(ls);
}else
{
right = get_next_right(rs);
}
}
return false;

}
int Solution::t2Sum(TreeNode* A, int B) {
return solve(A,B);
}

714. Best Time to Buy and Sell Stock with


Transaction Fee 

Your are given an array of integers prices , for which the i -th element is the price of a given stock on
day i ; and a non-negative integer fee representing a transaction fee.

You may complete as many transactions as you like, but you need to pay the transaction fee for each
transaction. You may not buy more than 1 share of a stock at a time (ie. you must sell the stock share
before you buy again.)

Return the maximum profit you can make.

Example 1:

Input: prices = [1, 3, 2, 8, 4, 9], fee = 2


Output: 8
Explanation: The maximum profit can be achieved by:
Buying at prices[0] = 1
Selling at prices[3] = 8
Buying at prices[4] = 4
Selling at prices[5] = 9
The total profit is ((8 - 1) - 2) + ((9 - 4) - 2) = 8.

Note:

0 < prices.length <= 50000 .


0 < prices[i] < 50000 .
0 <= fee < 50000 .

Buy and sell stock Variations


definition of T[i][k] should really be split into two: T[i][k][0] and T[i][k][1], where the former
denotes the maximum profit at the end of the i-th day with at most k transactions and with 0 stock in our
hand AFTER taking the action, while the latter denotes the maximum profit at the end of the i-th day with
https://leetcode.com/notes/ 24/31
8/25/2020 My Notes - LeetCode

at most k transactions and with 1 stock in our hand AFTER taking the action. Now the base cases and the
recurrence relations can be written as: Base cases:

T[-1][k][0] = 0, T[-1][k][1] = -Infinity


T[i][0][0] = 0, T[i][0][1] = -Infinity

Recurrence relations:

T[i][k][0] = max(T[i-1][k][0], T[i-1][k][1] + prices[i])


T[i][k][1] = max(T[i-1][k][1], T[i-1][k-1][0] - prices[i])

For One transaction


public int maxProfit(int[] prices) {
int T_i10 = 0, T_i11 = Integer.MIN_VALUE;

for (int price : prices) {


T_i10 = Math.max(T_i10, T_i11 + price);
T_i11 = Math.max(T_i11, -price);
}

return T_i10;
}

For 2 Transactions :
public int maxProfit(int[] prices) {
int T_i10 = 0, T_i11 = Integer.MIN_VALUE;
int T_i20 = 0, T_i21 = Integer.MIN_VALUE;

for (int price : prices) {


T_i20 = Math.max(T_i20, T_i21 + price);
T_i21 = Math.max(T_i21, T_i10 - price);
T_i10 = Math.max(T_i10, T_i11 + price);
T_i11 = Math.max(T_i11, -price);
}

return T_i20;
}

For Infinite Transactions


public int maxProfit(int[] prices) {
int T_ik0 = 0, T_ik1 = Integer.MIN_VALUE;

for (int price : prices) {


int T_ik0_old = T_ik0;
T_ik0 = Math.max(T_ik0, T_ik1 + price);
T_ik1 = Math.max(T_ik1, T_ik0_old - price);
}

return T_ik0;
}

https://leetcode.com/notes/ 25/31
8/25/2020 My Notes - LeetCode

If number of transactions are arbitrary


public int maxProfit(int k, int[] prices) {
if (k >= prices.length >>> 1) {
int T_ik0 = 0, T_ik1 = Integer.MIN_VALUE;

for (int price : prices) {


int T_ik0_old = T_ik0;
T_ik0 = Math.max(T_ik0, T_ik1 + price);
T_ik1 = Math.max(T_ik1, T_ik0_old - price);
}

return T_ik0;
}

int[] T_ik0 = new int[k + 1];


int[] T_ik1 = new int[k + 1];
Arrays.fill(T_ik1, Integer.MIN_VALUE);

for (int price : prices) {


for (int j = k; j > 0; j--) {
T_ik0[j] = Math.max(T_ik0[j], T_ik1[j] + price);
T_ik1[j] = Math.max(T_ik1[j], T_ik0[j - 1] - price);
}
}

return T_ik0[k];
}

With cooldown
public int maxProfit(int[] prices) {
int T_ik0_pre = 0, T_ik0 = 0, T_ik1 = Integer.MIN_VALUE;

for (int price : prices) {


int T_ik0_old = T_ik0;
T_ik0 = Math.max(T_ik0, T_ik1 + price);
T_ik1 = Math.max(T_ik1, T_ik0_pre - price);
T_ik0_pre = T_ik0_old;
}

return T_ik0;
}

With Transactions Fee


*Solution I *-- pay the fee when buying the stock:

https://leetcode.com/notes/ 26/31
8/25/2020 My Notes - LeetCode

public int maxProfit(int[] prices, int fee) {


int T_ik0 = 0, T_ik1 = Integer.MIN_VALUE;

for (int price : prices) {


int T_ik0_old = T_ik0;
T_ik0 = Math.max(T_ik0, T_ik1 + price);
T_ik1 = Math.max(T_ik1, T_ik0_old - price - fee);
}

return T_ik0;
}

*Solution II *-- pay the fee when selling the stock:

public int maxProfit(int[] prices, int fee) {


long T_ik0 = 0, T_ik1 = Integer.MIN_VALUE;

for (int price : prices) {


long T_ik0_old = T_ik0;
T_ik0 = Math.max(T_ik0, T_ik1 + price - fee);
T_ik1 = Math.max(T_ik1, T_ik0_old - price);
}

return (int)T_ik0;
}

```ff

904. Fruit Into Baskets 


In a row of trees, the i -th tree produces fruit with type tree[i] .

You start at any tree of your choice, then repeatedly perform the following steps:

1. Add one piece of fruit from this tree to your baskets. If you cannot, stop.
2. Move to the next tree to the right of the current tree. If there is no tree to the right, stop.

Note that you do not have any choice after the initial choice of starting tree: you must perform step 1, then
step 2, then back to step 1, then step 2, and so on until you stop.

You have two baskets, and each basket can carry any quantity of fruit, but you want each basket to only
carry one type of fruit each.

What is the total amount of fruit you can collect with this procedure?

Example 1:

Input: [1,2,1]
Output: 3
Explanation: We can collect [1,2,1].

Example 2:

https://leetcode.com/notes/ 27/31
8/25/2020 My Notes - LeetCode

Input: [0,1,2,2]
Output: 3
Explanation: We can collect [1,2,2].
If we started at the first tree, we would only collect [0, 1].

Example 3:

Input: [1,2,3,2,2]
Output: 4
Explanation: We can collect [2,3,2,2].
If we started at the first tree, we would only collect [1, 2].

Example 4:

Input: [3,3,3,1,2,1,1,2,3,3,4]
Output: 5
Explanation: We can collect [1,2,1,1,2].
If we started at the first tree or the eighth tree, we would only collect 4 fruits.

Note:

1. 1 <= tree.length <= 40000


2. 0 <= tree[i] < tree.length

By using flexible sliding window :

class Solution:
def totalFruit(self, tree: List[int]) -> int:

d = {}
i,j =0,0
ans =0
while j<len(tree):
if tree[j] in d:
d[tree[j]]+=1
else:
d[tree[j]] =1

while(len(d)>2):
d[tree[i]]-=1
if d[tree[i]]==0:
del d[tree[i]]
i+=1
ans = max(ans,j-i+1)
j+=1
return ans

930. Binary Subarrays With Sum 


https://leetcode.com/notes/ 28/31
8/25/2020 My Notes - LeetCode

In an array A of 0 s and 1 s, how many non-empty subarrays have sum S ?

Example 1:

Input: A = [1,0,1,0,1], S = 2
Output: 4
Explanation:
The 4 subarrays are bolded below:
[1,0,1,0,1]
[1,0,1,0,1]
[1,0,1,0,1]
[1,0,1,0,1]

Note:

1. A.length <= 30000


2. 0 <= S <= A.length
3. A[i] is either 0 or 1 .

class Solution {
public int numSubarraysWithSum(int[] A, int S) {
// calculate all subarrays less and equal to sum S minus all subarrays less and
equal to sum S - 1
return numSubarraysLessAndEqualToSum(A, S) - numSubarraysLessAndEqualToSum(A, S
- 1);
}

private int numSubarraysLessAndEqualToSum(int[] A, int S) {


int lo = 0;
int hi = 0;
int sum = 0;
int num = 0; // to calculate all legit subarrays end with hi
while (hi < A.length) {
sum += A[hi];
while (lo <= hi && sum > S) {
/* currently subarray end with hi is not valid, we need to forward lo*/
sum -= A[lo++];
}
num += hi - lo + 1;
hi++;
}
return num;
}
}

1248. Count Number of Nice Subarrays 


https://leetcode.com/notes/ 29/31
8/25/2020 My Notes - LeetCode

Given an array of integers nums and an integer k . A subarray is called nice if there are k odd numbers
on it.

Return the number of nice sub-arrays.

Example 1:

Input: nums = [1,1,2,1,1], k = 3


Output: 2
Explanation: The only sub-arrays with 3 odd numbers are [1,1,2,1] and [1,2,1,1].

Example 2:

Input: nums = [2,4,6], k = 1


Output: 0
Explanation: There is no odd numbers in the array.

Example 3:

Input: nums = [2,2,2,1,2,2,1,2,2,2], k = 2


Output: 16

Constraints:

1 <= nums.length <= 50000


1 <= nums[i] <= 10^5
1 <= k <= nums.length

Given an array of integers nums and an integer k. A subarray is called nice if there are k odd numbers on
it.

Return the number of nice sub-arrays.

Example 1:

Input: nums = [1,1,2,1,1], k = 3


Output: 2
Explanation: The only sub-arrays with 3 odd numbers are [1,1,2,1] and [1,2,1,1].

exactly K times = at most K times - at most K - 1 times

https://leetcode.com/notes/ 30/31
8/25/2020 My Notes - LeetCode

def numberOfSubarrays(self, A, k):


def atMost(k):
res = i = 0
for j in xrange(len(A)):
k -= A[j] % 2
while k < 0:
k += A[i] % 2
i += 1
res += j - i + 1
return res

return atMost(k) - atMost(k - 1)

Solution II: One pass


Actually it's same as three pointers. Though we use count to count the number of even numebers.

def numberOfSubarrays(self, A, k):


i = count = res = 0
for j in xrange(len(A)):
if A[j] & 1:
k -= 1
count = 0
while k == 0:
k += A[i] & 1
i += 1
count += 1
res += count
return res

https://leetcode.com/notes/ 31/31

You might also like