Array Hashing Flashcards

1
Q

Merge Sorted Array
Solved
Easy
You are given two integer arrays nums1 and nums2, sorted in non-decreasing order, and two integers m and n, representing the number of elements in nums1 and nums2 respectively.

Merge nums1 and nums2 into a single array sorted in non-decreasing order.

The final sorted array should not be returned by the function, but instead be stored inside the array nums1. To accommodate this, nums1 has a length of m + n, where the first m elements denote the elements that should be merged, and the last n elements are set to 0 and should be ignored. nums2 has a length of n.

Example 1:

Input: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
Output: [1,2,2,3,5,6]
Explanation: The arrays we are merging are [1,2,3] and [2,5,6].
The result of the merge is [1,2,2,3,5,6] with the underlined elements coming from nums1.
Example 2:

Input: nums1 = [1], m = 1, nums2 = [], n = 0
Output: [1]
Explanation: The arrays we are merging are [1] and [].
The result of the merge is [1].
Example 3:

Input: nums1 = [0], m = 0, nums2 = [1], n = 1
Output: [1]
Explanation: The arrays we are merging are [] and [1].
The result of the merge is [1].
Note that because m = 0, there are no elements in nums1. The 0 is only there to ensure the merge result can fit in nums1.

Facebook 87
Amazon 41
Google 14
Microsoft 14

A
class Solution(object):
    def merge(self, nums1, m, nums2, n):
        """
        :type nums1: List[int]
        :type m: int
        :type nums2: List[int]
        :type n: int
        :rtype: None Do not return anything, modify nums1 in-place instead.
        """
        p1 = m-1
        p2 = n-1
        p = len(nums1) - 1
        while(p>=0):
            if(p2<0):
                break
            if(p1>=0 and nums1[p1] > nums2[p2]):
                nums1[p] = nums1[p1]
                p1-=1
            else:
                nums1[p] = nums2[p2]
                p2-=1
            p-=1
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q
  1. Group Anagrams
    Medium
    Companies

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.

https://leetcode.com/problems/group-anagrams/description/

A
from collections import defaultdict
class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        res = defaultdict(list)
        for s in strs:
            count = [0] * 26
            for c in s:
                count[ord(c) - ord('a')] += 1
            res[tuple(count)].append(s)
        return res.values()

O(n), space: O(n*26)

If you want to save space in case words are smaller than 26 all the time and space is at a premium,

sort each string and use that as the key.
That changes the time to n(mLog(m)) where m is avg word length and n is number of entries. Space becomes m*n

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q
  1. Top K Frequent Elements

Top K Frequent Elements
Solved
Medium
Topics
Companies
Given an integer array nums and an integer k, return the k most frequent elements. You may return the answer in any order.

Example 1:

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

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

Constraints:

1 <= nums.length <= 105
-104 <= nums[i] <= 104
k is in the range [1, the number of unique elements in the array].
It is guaranteed that the answer is unique.

Follow up: Your algorithm’s time complexity must be better than O(n log n), where n is the array’s size.

Facebook
58
Amazon
20

https://leetcode.com/problems/top-k-frequent-elements/description/347

A
from collections import Counter

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        if k == len(nums):
            return nums
        counts = Counter(nums)
        return heapq.nlargest(k, counts.keys(), counts.get)

using quick select with count frequencies as key.
from collections import Counter
class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """

        counts = Counter(nums)
        unique = counts.keys()

        def partition(l, r):
            if l == r:
                return l
            pivot = unique[r]
            store_idx = l

            for i in range(l, r):
                if counts[unique[i]] < counts[pivot]:
                    unique[i], unique[store_idx] = unique[store_idx], unique[i]
                    store_idx += 1
            unique[r], unique[store_idx] = unique[store_idx], unique[r]

            return store_idx
        
        def quick_select(k):
            k = len(unique) - k
            l = 0
            r = len(unique) - 1
            piv_idx = partition(l, r)
            while l < r:
                if piv_idx == k:
                    return
                elif piv_idx < k:
                    l = piv_idx + 1
                    piv_idx = partition(l, r)
                else:
                    r = piv_idx - 1
                    piv_idx = partition(l, r)
    
        quick_select(k)
        n = len(unique)
        return unique[n-k:]
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q
  1. Encode and Decode Strings
    Solved
    Medium
    Topics
    Companies
    Design an algorithm to encode a list of strings to a string. The encoded string is then sent over the network and is decoded back to the original list of strings.

Machine 1 (sender) has the function:

string encode(vector<string> strs) {
// ... your code
return encoded_string;
}
Machine 2 (receiver) has the function:
vector<string> decode(string s) {
//... your code
return strs;
}
So Machine 1 does:</string></string>

string encoded_string = encode(strs);
and Machine 2 does:

vector<string> strs2 = decode(encoded_string);
strs2 in Machine 2 should be the same as strs in Machine 1.</string>

Implement the encode and decode methods.

You are not allowed to solve the problem using any serialize methods (such as eval).

https://leetcode.com/problems/encode-and-decode-strings/

A
class Codec:

    def encode(self, strs):
        """Encodes a list of strings to a single string.
        
        :type strs: List[str]
        :rtype: str
        """
        sent = []
        for str in strs:
            str = str.replace("/", "//")
            str = str.replace("$", "/$")
            sent.append(str)
        return "$".join(sent)
        

    def decode(self, s):
        """Decodes a single string to a list of strings.
        
        :type s: str
        :rtype: List[str]
        """
        out = []
        i = 0
        word = ""
        while i < len(s):
            if s[i] == "/":
                i += 1
            elif s[i] == "$":
                out.append(word)
                word = ""
                i += 1
            word += s[i] 
            i += 1
        out.append(word)
        return out
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q
  1. Product of Array Except Self
    Solved
    Medium
    Topics
    Companies
    Hint
    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.)

https://leetcode.com/problems/product-of-array-except-self/

A
class Solution:
    def productExceptSelf(self, nums: List[int]) -> List[int]:
        out = [1] * len(nums)
        prev = 1
        for i in range(1, len(nums)):
            out[i] = out[i-1] * nums[i-1]
       
			 suffix = 1
        for i in range(len(nums)-1, -1, -1):
            out[i] = suffix * out[i]
            suffix = suffix * nums[i]    
        return out
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q
  1. Longest Consecutive Sequence
    Medium
    Given an unsorted array of integers nums, return the length of the longest consecutive elements sequence.

You must write an algorithm that runs in O(n) time.

Example 1:

Input: nums = [100,4,200,1,3,2]
Output: 4
Explanation: The longest consecutive elements sequence is [1, 2, 3, 4]. Therefore its length is 4.
Example 2:

Input: nums = [0,3,7,2,5,8,4,6,0,1]
Output: 9

Constraints:

0 <= nums.length <= 105
-109 <= nums[i] <= 109

Amazon
17
Adobe
8

10 min hard cap, O(nLogn) solution.

https://leetcode.com/problems/longest-consecutive-sequence/description/

A
class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        starts = set()
        maxlen = 0
        nums_set = set(nums)
        for n in nums:
            if n-1 not in nums_set:
                starts.add(n)
        for start in starts:
            nxt = start
            slen = 0
            while nxt in nums_set:
                slen +=1
                nxt += 1
            maxlen = max(maxlen, slen)
        return maxlen

nLogn, O(n) space

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q
  1. Remove Element
    Easy
    Companies

Given an integer array nums and an integer val, remove all occurrences of val in nums in-place. The order of the elements may be changed. Then return the number of elements in nums which are not equal to val.

Consider the number of elements in nums which are not equal to val be k, to get accepted, you need to do the following things:

Change the array nums such that the first k elements of nums contain the elements which are not equal to val. The remaining elements of nums are not important as well as the size of nums.
Return k.

Example 1:

Input: nums = [3,2,2,3], val = 3
Output: 2, nums = [2,2,,]
Explanation: Your function should return k = 2, with the first two elements of nums being 2.
It does not matter what you leave beyond the returned k (hence they are underscores).
Example 2:

Input: nums = [0,1,2,2,3,0,4,2], val = 2
Output: 5, nums = [0,1,4,0,3,,,_]
Explanation: Your function should return k = 5, with the first five elements of nums containing 0, 0, 1, 3, and 4.
Note that the five elements can be returned in any order.
It does not matter what you leave beyond the returned k (hence they are underscores).

Constraints:

0 <= nums.length <= 100
0 <= nums[i] <= 50
0 <= val <= 100

https://leetcode.com/problems/remove-element/description

A
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        insert = 0
        idx = 0
        while idx < len(nums):
            if nums[idx] != val:
                nums[idx], nums[insert] = nums[insert], nums[idx]
                insert += 1
            idx += 1
        return insert
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q
  1. Remove Duplicates from Sorted Array
    Easy
    Companies
    Given an integer array nums sorted in non-decreasing order, remove the duplicates in-place such that each unique element appears only once. The relative order of the elements should be kept the same. Then return the number of unique elements in nums.

Consider the number of unique elements of nums to be k, to get accepted, you need to do the following things:

Change the array nums such that the first k elements of nums contain the unique elements in the order they were present in nums initially. The remaining elements of nums are not important as well as the size of nums.
Return k.
Custom Judge:

The judge will test your solution with the following code:

int[] nums = […]; // Input array
int[] expectedNums = […]; // The expected answer with correct length

int k = removeDuplicates(nums); // Calls your implementation

assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
assert nums[i] == expectedNums[i];
}
If all assertions pass, then your solution will be accepted.

Example 1:

Input: nums = [1,1,2]
Output: 2, nums = [1,2,_]
Explanation: Your function should return k = 2, with the first two elements of nums being 1 and 2 respectively.
It does not matter what you leave beyond the returned k (hence they are underscores).
Example 2:

Input: nums = [0,0,1,1,1,2,2,3,3,4]
Output: 5, nums = [0,1,2,3,4,,,,,_]
Explanation: Your function should return k = 5, with the first five elements of nums being 0, 1, 2, 3, and 4 respectively.
It does not matter what you leave beyond the returned k (hence they are underscores).

Constraints:

1 <= nums.length <= 3 * 104
-100 <= nums[i] <= 100
nums is sorted in non-decreasing order.

https://leetcode.com/problems/remove-duplicates-from-sorted-array/

A
class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        l = 1
        for r in range(1, len(nums)):
            if nums[r] != nums[r-1]:
                nums[l] = nums[r]
                l+= 1
        return l
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q
  1. Remove Duplicates from Sorted Array II
    Solved
    Medium

Topics

Companies
Given an integer array nums sorted in non-decreasing order, remove some duplicates in-place such that each unique element appears at most twice. The relative order of the elements should be kept the same.

Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the first part of the array nums. More formally, if there are k elements after removing the duplicates, then the first k elements of nums should hold the final result. It does not matter what you leave beyond the first k elements.

Return k after placing the final result in the first k slots of nums.

Do not allocate extra space for another array. You must do this by modifying the input array in-place with O(1) extra memory.

Custom Judge:

The judge will test your solution with the following code:

int[] nums = […]; // Input array
int[] expectedNums = […]; // The expected answer with correct length

int k = removeDuplicates(nums); // Calls your implementation

assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
assert nums[i] == expectedNums[i];
}
If all assertions pass, then your solution will be accepted.

Example 1:

Input: nums = [1,1,1,2,2,3]
Output: 5, nums = [1,1,2,2,3,_]
Explanation: Your function should return k = 5, with the first five elements of nums being 1, 1, 2, 2 and 3 respectively.
It does not matter what you leave beyond the returned k (hence they are underscores).
Example 2:

Input: nums = [0,0,1,1,1,1,2,3,3]
Output: 7, nums = [0,0,1,1,2,3,3,,]
Explanation: Your function should return k = 7, with the first seven elements of nums being 0, 0, 1, 1, 2, 3 and 3 respectively.
It does not matter what you leave beyond the returned k (hence they are underscores).

https://leetcode.com/problems/remove-duplicates-from-sorted-array-ii/description

A

Keep swapping elements with insert till their count is less than or equal to 2. Once a new element is encountered, count goes back to 1, thus swapping continues.

class Solution(object):
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        insert = 1
        count = 1
        for i in range(1, len(nums)):
            if nums[i] == nums[i-1]:
                count += 1
            else:
                count = 1
            if count <= 2:
                nums[insert] = nums[i]
                insert += 1
        return insert

this works because if an element is moved to position 3 after checking if position 1 has the same element or not, it is guaranteed it won’t repeat more than 2 times..

<>,1, 1, 2
No matter what is at <> as long as it’s not 2, 2 can safely move one step left and it won’t repeat more than 2 times.

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        # Initialize an integer k that updates the kth index of the array...
        # only when the current element does not match either of the two previous indexes. ...
        insert = 0
        # Traverse all elements through loop...
        for cur_element in nums:
            # If the index does not match elements, count that element and update it...
            two_before_insert = insert - 2
            if insert < 2 or cur_element != nums[two_before_insert]:
                nums[insert] = cur_element
                insert += 1
        return insert
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q
  1. Best Time to Buy and Sell Stock

Solved
Easy

You are given an array prices where prices[i] is the price of a given stock on the ith day.

You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock.

Return the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0.

Example 1:

Input: prices = [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
Note that buying on day 2 and selling on day 1 is not allowed because you must buy before you sell.
Example 2:

Input: prices = [7,6,4,3,1]
Output: 0
Explanation: In this case, no transactions are done and the max profit = 0.

Constraints:

1 <= prices.length <= 105
0 <= prices[i] <= 104

https://leetcode.com/problems/best-time-to-buy-and-sell-stock/

https://leetcode.com/problems/best-time-to-buy-and-sell-stock/

A
class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        pur = prices[0]
        maxp = 0
        for price in prices:
            pur = min(pur, price)
            profit = price - pur
            maxp = max(maxp, profit)
        return maxp
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q
  1. Best Time to Buy and Sell Stock II

https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/description/?envType=study-plan-v2&envId=top-interview-150

Solved
Medium
Topics
Companies
You are given an integer array prices where prices[i] is the price of a given stock on the ith day.

On each day, you may decide to buy and/or sell the stock. You can only hold at most one share of the stock at any time. However, you can buy it then immediately sell it on the same day.

Find and return the maximum profit you can achieve.

Example 1:

Input: prices = [7,1,5,3,6,4]
Output: 7
Explanation: Buy on day 2 (price = 1) and sell on day 3 (price = 5), profit = 5-1 = 4.
Then buy on day 4 (price = 3) and sell on day 5 (price = 6), profit = 6-3 = 3.
Total profit is 4 + 3 = 7.
Example 2:

Input: prices = [1,2,3,4,5]
Output: 4
Explanation: Buy on day 1 (price = 1) and sell on day 5 (price = 5), profit = 5-1 = 4.
Total profit is 4.
Example 3:

Input: prices = [7,6,4,3,1]
Output: 0
Explanation: There is no way to make a positive profit, so we never buy the stock to achieve the maximum profit of 0.

Constraints:

1 <= prices.length <= 3 * 104
0 <= prices[i] <= 104

https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/

A

Each time price falls, reset buy and sell, add the current trade to profit.

class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        pur = 0
        sell = 0
        r = 0
        maxp = 0
        while r < len(prices) - 1:
            # find valley first where price is lowest
            while r < len(prices) - 1 and prices[r] >= prices[r+1]:
                r += 1
            pur = r
            # find peak where price is highest after the valley of lowest price
            while r < len(prices) - 1 and  prices[r] < prices[r + 1]:
                r += 1
            sell = r
            profit = prices[sell] - prices[pur]
            maxp += profit
        return maxp

doing multiple transactions for each high low combo, might not work if question mentions do it in lowest transactions eg transaction has a fee

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        maxprofit = 0
        for i in range(1, len(prices)):
            if prices[i] > prices[i - 1]:
                maxprofit += prices[i] - prices[i - 1]
        return maxprofit

Another approach, monotonic increasing stack like.
# if we never hit a lower price before we finish, we do the final trade outside the loop.

class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        maxP = 0
        dates = []
        buy = prices[0]
        sell = prices[0]
        for i in range(1, len(prices)):
            if prices[i] < sell:
                maxP += (sell - buy)
                buy = prices[i]
                sell = prices[i]
            else:
                sell = prices[i]
        if sell == prices[-1]:
            maxP += (sell-buy)
        return maxP
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q
  1. Jump Game
    Medium

You are given an integer array nums. You are initially positioned at the array’s first index, and each element in the array represents your maximum jump length at that position.

Return true if you can reach the last index, or false otherwise.

Example 1:

Input: nums = [2,3,1,1,4]
Output: true
Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.
Example 2:

Input: nums = [3,2,1,0,4]
Output: false
Explanation: You will always arrive at index 3 no matter what. Its maximum jump length is 0, which makes it impossible to reach the last index.

Constraints:

1 <= nums.length <= 104
0 <= nums[i] <= 105(

Amazon 18

https://leetcode.com/problems/jump-game/

A

going from front to end we keep updating maximum destination we can reach.

class Solution(object):
    def canJump(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        i = 0
        if len(nums) == 1:
            return True
        maxdest = 0
        for i in range(len(nums)):
            if i + nums[i] >= maxdest:
                maxdest = i + nums[i]
            # we hit a zero thus cant move forward    
            if maxdest == i:
                break
        return maxdest >= len(nums) - 1

going from end to start we will keep updating last valid position (posToReach)

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        finalPos = len(nums) - 1
        if finalPos == 0:
            return True
        posToReach = finalPos
        for i in range(finalPos, -1, -1):
            stepsNeeded = posToReach - i
            if nums[i] >= stepsNeeded:
                posToReach = i
        if posToReach == 0:
            return True
        return False
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q
  1. Jump Game II
    https://leetcode.com/problems/jump-game-ii/description/?envType=study-plan-v2&envId=top-interview-150
    Solved
    Medium
    Topics
    Companies
    You are given a 0-indexed array of integers nums of length n. You are initially positioned at nums[0].

Each element nums[i] represents the maximum length of a forward jump from index i. In other words, if you are at nums[i], you can jump to any nums[i + j] where:

0 <= j <= nums[i] and
i + j < n
Return the minimum number of jumps to reach nums[n - 1]. The test cases are generated such that you can reach nums[n - 1].

Example 1:

Input: nums = [2,3,1,1,4]
Output: 2
Explanation: The minimum number of jumps to reach the last index is 2. Jump 1 step from index 0 to 1, then 3 steps to the last index.
Example 2:

Input: nums = [2,3,0,1,4]
Output: 2

Constraints:

1 <= nums.length <= 104
0 <= nums[i] <= 1000
It’s guaranteed that you can reach nums[n - 1].

https://leetcode.com/problems/jump-game-ii

A

builds on the jump 1 front to end solution, we keep track of current jump and when we hit it, we increment the counter to record we jumped.

class Solution(object):
    def jump(self, nums):
        answer = 0
        maxjump = 0
        prev_jump = 0    
        for i in range(len(nums) - 1):
            jump = i + nums[i]
            maxjump = max(jump, maxjump)
            if i == prev_jump:
                prev_jump = maxjump
                answer += 1
        return answer
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q
  1. H-Index
    Medium
    Topics
    Companies

Given an array of integers citations where citations[i] is the number of citations a researcher received for their ith paper, return the researcher’s h-index.

According to the definition of h-index on Wikipedia: The h-index is defined as the maximum value of h such that the given researcher has published at least h papers that have each been cited at least h times.

Example 1:

Input: citations = [3,0,6,1,5]
Output: 3
Explanation: [3,0,6,1,5] means the researcher has 5 papers in total and each of them had received 3, 0, 6, 1, 5 citations respectively.
Since the researcher has 3 papers with at least 3 citations each and the remaining two with no more than 3 citations each, their h-index is 3.
Example 2:

Input: citations = [1,3,1]
Output: 1

Constraints:

n == citations.length
1 <= n <= 5000
0 <= citations[i] <= 1000

https://leetcode.com/problems/h-index/description

A

reverse sort and if citation is < paper count return paper count

from collections import defaultdict

class Solution(object):
    def hIndex(self, citations):
        """
        :type citations: List[int]
        :rtype: int
        """
        sorted_citation = sorted(citations, reverse=True)
        for i in range(len(citations)):
            citation_count = sorted_citation[i]
            paper_number = i+1
            if (citation_count < paper_number):
                return i
        return paper_number

same as above but uses count sort with ceiling as len of array as the hidx can never be more than the count of all papers..

class Solution(object):
    def hIndex(self, citations: List[int]) -> int:
        count = [0] * (len(citations) + 1)
        for c in citations:
            idx = min(len(count)-1, c)
            count[idx] += 1
        total = 0
        papers = 0
        for idx in reversed(range(len(count))):
            papers += count[idx]
            if papers >= idx:
                return idx
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q
  1. Insert Delete GetRandom O(1)

https://leetcode.com/problems/insert-delete-getrandom-o1/description/?envType=study-plan-v2&envId=top-interview-150

Solved
Medium
Topics
Companies
Implement the RandomizedSet class:

RandomizedSet() Initializes the RandomizedSet object.
bool insert(int val) Inserts an item val into the set if not present. Returns true if the item was not present, false otherwise.
bool remove(int val) Removes an item val from the set if present. Returns true if the item was present, false otherwise.
int getRandom() Returns a random element from the current set of elements (it’s guaranteed that at least one element exists when this method is called). Each element must have the same probability of being returned.
You must implement the functions of the class such that each function works in average O(1) time complexity.

Example 1:

Input
[“RandomizedSet”, “insert”, “remove”, “insert”, “getRandom”, “remove”, “insert”, “getRandom”]
[[], [1], [2], [2], [], [1], [2], []]
Output
[null, true, false, true, 2, true, false, 2]

Explanation
RandomizedSet randomizedSet = new RandomizedSet();
randomizedSet.insert(1); // Inserts 1 to the set. Returns true as 1 was inserted successfully.
randomizedSet.remove(2); // Returns false as 2 does not exist in the set.
randomizedSet.insert(2); // Inserts 2 to the set, returns true. Set now contains [1,2].
randomizedSet.getRandom(); // getRandom() should return either 1 or 2 randomly.
randomizedSet.remove(1); // Removes 1 from the set, returns true. Set now contains [2].
randomizedSet.insert(2); // 2 was already in the set, so return false.
randomizedSet.getRandom(); // Since 2 is the only number in the set, getRandom() will always return 2.

Constraints:

-231 <= val <= 231 - 1
At most 2 * 105 calls will be made to insert, remove, and getRandom.
There will be at least one element in the data structure when getRandom is called.

A

main logic here is that you can delete from array at last position in o(1)
so swap element to be deleted to last and pop it

from collections import defaultdict
from random import randrange

class RandomizedSet(object):

def \_\_init\_\_(self):
    self.elements = set()
    self.filled = []
    self.filled_idx = defaultdict(int)

def insert(self, val):
    """
    :type val: int
    :rtype: bool
    """
    present = val in self.elements
    if not present:
        self.filled.append(val)
        self.elements.add(val)
        self.filled_idx[val] = len(self.elements)-1
    return not present

def remove(self, val):
    """
    :type val: int
    :rtype: bool
    """
    present = val in self.elements
    if present:
        self.elements.remove(val)
        remove_idx = self.filled_idx[val]
        self.filled[remove_idx], self.filled[-1] = self.filled[-1], self.filled[remove_idx]
        self.filled_idx[self.filled[remove_idx]] = remove_idx
        self.filled.pop()
    return present
    

def getRandom(self):
    """
    :rtype: int
    """
    randomIdx = randrange(0, len(self.filled))
    return self.filled[randomIdx]
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q
  1. Gas Station

There are n gas stations along a circular route, where the amount of gas at the ith station is gas[i].

You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from the ith station to its next (i + 1)th station. You begin the journey with an empty tank at one of the gas stations.

Given two integer arrays gas and cost, return the starting gas station’s index if you can travel around the circuit once in the clockwise direction, otherwise return -1. If there exists a solution, it is guaranteed to be unique

Example 1:

Input: gas = [1,2,3,4,5], cost = [3,4,5,1,2]
Output: 3
Explanation:
Start at station 3 (index 3) and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 4. Your tank = 4 - 1 + 5 = 8
Travel to station 0. Your tank = 8 - 2 + 1 = 7
Travel to station 1. Your tank = 7 - 3 + 2 = 6
Travel to station 2. Your tank = 6 - 4 + 3 = 5
Travel to station 3. The cost is 5. Your gas is just enough to travel back to station 3.
Therefore, return 3 as the starting index.
Example 2:

Input: gas = [2,3,4], cost = [3,4,3]
Output: -1
Explanation:
You can’t start at station 0 or 1, as there is not enough gas to travel to the next station.
Let’s start at station 2 and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 0. Your tank = 4 - 3 + 2 = 3
Travel to station 1. Your tank = 3 - 3 + 3 = 3
You cannot travel back to station 2, as it requires 4 unit of gas but you only have 3.
Therefore, you can’t travel around the circuit once no matter where you start.

Constraints:

n == gas.length == cost.length
1 <= n <= 105
0 <= gas[i], cost[i] <= 104

https://leetcode.com/problems/gas-station/editorial/?envType=study-plan-v2&envId=top-interview-150

A

View a bunch of stops as segments, you set cur segment to zero if the segment’s gas gain drops to 0 because it means it is not as good starting point, so you start at the next gas station and check it

class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
total_gain = 0
current_gain = 0
start_idx = 0
for idx, (g, c) in enumerate(zip(gas,cost)):
total_gain += (g - c)
current_gain += (g - c)

        if current_gain < 0:
            current_gain = 0
            start_idx = idx + 1
    return start_idx if total_gain >= 0 else -1
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q
  1. Candy
    Solved
    Hard
    Topics
    Companies
    There are n children standing in a line. Each child is assigned a rating value given in the integer array ratings.

You are giving candies to these children subjected to the following requirements:

Each child must have at least one candy.
Children with a higher rating get more candies than their neighbors.
Return the minimum number of candies you need to have to distribute the candies to the children.

Example 1:

Input: ratings = [1,0,2]
Output: 5
Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively.
Example 2:

Input: ratings = [1,2,2]
Output: 4
Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively.
The third child gets 1 candy because it satisfies the above two conditions.

Constraints:

n == ratings.length
1 <= n <= 2 * 104
0 <= ratings[i] <= 2 * 104

https://leetcode.com/problems/candy/description/?envType=study-plan-v2&envId=top-interview-150

A

do a forward pass where you compare the left neighbor and then do a right pass where you compare the right neighbor and then for each individual select the maximum of the forward pass and the left pass.

class Solution(object):
def candy(self, ratings):
sum = 0
n = len(ratings)
left2right = [1] * n
right2left = [1] * n
for i in range(1, n):
if ratings[i] > ratings[i - 1]:
left2right[i] = left2right[i - 1] + 1
for i in range(n - 2, -1, -1):
if ratings[i] > ratings[i + 1]:
right2left[i] = right2left[i + 1] + 1
for i in range(n):
sum += max(left2right[i], right2left[i])
return sum

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q
  1. Minimum Adjacent Swaps to Make a Valid Array
    Solved
    Medium

Topics

Companies: Amazon

Hint
You are given a 0-indexed integer array nums.

Swaps of adjacent elements are able to be performed on nums.

A valid array meets the following conditions:

The largest element (any of the largest elements if there are multiple) is at the rightmost position in the array.
The smallest element (any of the smallest elements if there are multiple) is at the leftmost position in the array.
Return the minimum swaps required to make nums a valid array.

Example 1:

Input: nums = [3,4,5,5,3,1]
Output: 6
Explanation: Perform the following swaps:
- Swap 1: Swap the 3rd and 4th elements, nums is then [3,4,5,3,5,1].
- Swap 2: Swap the 4th and 5th elements, nums is then [3,4,5,3,1,5].
- Swap 3: Swap the 3rd and 4th elements, nums is then [3,4,5,1,3,5].
- Swap 4: Swap the 2nd and 3rd elements, nums is then [3,4,1,5,3,5].
- Swap 5: Swap the 1st and 2nd elements, nums is then [3,1,4,5,3,5].
- Swap 6: Swap the 0th and 1st elements, nums is then [1,3,4,5,3,5].
It can be shown that 6 swaps is the minimum swaps required to make a valid array.
Example 2:
Input: nums = [9]
Output: 0
Explanation: The array is already valid, so we return 0.

Constraints:

1 <= nums.length <= 105
1 <= nums[i] <= 105

https://leetcode.com/problems/minimum-adjacent-swaps-to-make-a-valid-array/description/

A

class Solution(object):
def minimumSwaps(self, nums):
“””
:type nums: List[int]
:rtype: int
“””
minPos = len(nums) + 1
m_num = float(‘inf’)
maxPos = -1
mx_num = float(‘-inf’)
swaps = 0
for i in range(len(nums)):
if nums[i] < m_num:
minPos = i
m_num = nums[i]
if nums[i] >= mx_num:
maxPos = max(maxPos, i)
mx_num = nums[i]
adjustment = 0
if minPos > maxPos:
# they are on the other sides
adjustment = -1
swaps = minPos + ((len(nums) -1) - maxPos) + adjustment
return swaps

19
Q
  1. Minimum Number of Keypresses
    Solved
    Medium

Topics

Companies

Hint
You have a keypad with 9 buttons, numbered from 1 to 9, each mapped to lowercase English letters. You can choose which characters each button is matched to as long as:

All 26 lowercase English letters are mapped to.
Each character is mapped to by exactly 1 button.
Each button maps to at most 3 characters.
To type the first character matched to a button, you press the button once. To type the second character, you press the button twice, and so on.

Given a string s, return the minimum number of keypresses needed to type s using your keypad.

Note that the characters mapped to by each button, and the order they are mapped in cannot be changed.

Example 1:

Input: s = “apple”
Output: 5
Explanation: One optimal way to setup your keypad is shown above.
Type ‘a’ by pressing button 1 once.
Type ‘p’ by pressing button 6 once.
Type ‘p’ by pressing button 6 once.
Type ‘l’ by pressing button 5 once.
Type ‘e’ by pressing button 3 once.
A total of 5 button presses are needed, so return 5.
Example 2:

Input: s = “abcdefghijkl”
Output: 15
Explanation: One optimal way to setup your keypad is shown above.
The letters ‘a’ to ‘i’ can each be typed by pressing a button once.
Type ‘j’ by pressing button 1 twice.
Type ‘k’ by pressing button 2 twice.
Type ‘l’ by pressing button 3 twice.
A total of 15 button presses are needed, so return 15.

Constraints:

1 <= s.length <= 105
s consists of lowercase English letters.

https://leetcode.com/problems/minimum-number-of-keypresses/description/

A

from collections import Counter,defaultdict

class Solution(object):
def minimumKeypresses(self, s):
“””
:type s: str
:rtype: int
“””
scount = Counter(s)
heap = []
for key, value in scount.items():
heapq.heappush(heap, (-value, key))
keys = defaultdict(list)
charToKey = {}
idx = 0
keypress = 0
while heap:
_, char = heapq.heappop(heap)
number = (idx % 9 + 1)
idx += 1
keys[number].append(char)
charToKey[char] = number
for char in s:
keypress += (keys[charToKey[char]].index(char) + 1)
return keypress

This solution prevents the last index of by using an array to set the index of the ordinal as key pressed needed (basically every time we go above 9 keys, the order increases by 1

class Solution:
def minimumKeypresses(self, s: str) -> int:
cache = Counter(s)
vals = sorted(cache.items(), key=lambda x: -x[1])
ans = 0
r = key = 1
order = [0] * 26

    for k, v in vals:
        x = ord(k) - 97

        if not order[x]:
            order[x] = r
            key += 1

            if key == 10:
                key = 1
                r += 1

        ans += order[x] * v

    return ans
20
Q
  1. Valid Word Abbreviation
    Solved
    Easy (Looks like a medium)
    Companies: Facebook 2024

A string can be abbreviated by replacing any number of non-adjacent, non-empty substrings with their lengths. The lengths should not have leading zeros.

For example, a string such as “substitution” could be abbreviated as (but not limited to):

"s10n" ("s ubstitutio n")
"sub4u4" ("sub stit u tion")
"12" ("substitution")
"su3i1u2on" ("su bst i t u ti on")
"substitution" (no substrings replaced)

The following are not valid abbreviations:

"s55n" ("s ubsti tutio n", the replaced substrings are adjacent)
"s010n" (has leading zeros)
"s0ubstitution" (replaces an empty substring)

Given a string word and an abbreviation abbr, return whether the string matches the given abbreviation.

A substring is a contiguous non-empty sequence of characters within a string.

Example 1:

Input: word = “internationalization”, abbr = “i12iz4n”
Output: true
Explanation: The word “internationalization” can be abbreviated as “i12iz4n” (“i nternational iz atio n”).

Example 2:

Input: word = “apple”, abbr = “a2e”
Output: false
Explanation: The word “apple” cannot be abbreviated as “a2e”.

Constraints:

1 <= word.length <= 20
word consists of only lowercase English letters.
1 <= abbr.length <= 10
abbr consists of lowercase English letters and digits.
All the integers in abbr will fit in a 32-bit integer.

https://leetcode.com/problems/valid-word-abbreviation/description/

A

Keep two pointers, one i for the main word and j for the abbr
once you encounter a jump in abbr,
make the i pointer jump and then continue comparing chars at i and j.

class Solution:
    def validWordAbbreviation(self, word: str, abbr: str) -> bool:
        i=0
        j=0
        while i < len(word) and j < len(abbr):
            if abbr[j].isdigit():
                if abbr[j] == '0':
                    return False
                jump = ""
                while j < len(abbr) and abbr[j].isdigit():
                    jump += abbr[j]
                    j+=1
                jump = int(jump)
                i = i + (jump)
                continue
            if word[i] != abbr[j]:
                return False
            i+=1
            j+=1
        if i == len(word) and j == len(abbr):
                return True
        else:
            return False 
21
Q
  1. Dot Product of Two Sparse Vectors
    Medium
    Facebook

Given two sparse vectors, compute their dot product.

Implement class SparseVector:

SparseVector(nums) Initializes the object with the vector nums
dotProduct(vec) Compute the dot product between the instance of SparseVector and vec

A sparse vector is a vector that has mostly zero values, you should store the sparse vector efficiently and compute the dot product between two SparseVector.

Follow up: What if only one of the vectors is sparse?

Example 1:

Input: nums1 = [1,0,0,2,3], nums2 = [0,3,0,4,0]
Output: 8
Explanation: v1 = SparseVector(nums1) , v2 = SparseVector(nums2)
v1.dotProduct(v2) = 10 + 03 + 00 + 24 + 3*0 = 8

Example 2:

Input: nums1 = [0,1,0,0,0], nums2 = [0,0,0,0,2]
Output: 0
Explanation: v1 = SparseVector(nums1) , v2 = SparseVector(nums2)
v1.dotProduct(v2) = 00 + 10 + 00 + 00 + 0*2 = 0

Example 3:

Input: nums1 = [0,1,0,0,2,0,0], nums2 = [1,0,0,0,3,0,4]
Output: 6

Constraints:

n == nums1.length == nums2.length
1 <= n <= 10^5
0 <= nums1[i], nums2[i] <= 100

O(n), O(n)

https://leetcode.com/problems/dot-product-of-two-sparse-vectors/description/

A

Store vectors as dictionary of keys format.

class SparseVector:
    def \_\_init\_\_(self, nums: List[int]):
        self.vec = self._to_sparse(nums)

    def _to_sparse(self, vec: List[int]):
        output = {}
        for i, e in enumerate(vec):
            if e != 0:
                output[i] = e
        return output

    # Return the dotProduct of two sparse vectors
    def dotProduct(self, vec: 'SparseVector') -> int:
        ret = 0
        for idx, val in vec.vec.items():
            if idx in self.vec:
                ret += self.vec[idx] * val
        return ret 

Slight Optimization, iterate through smaller one

class SparseVector:
    def \_\_init\_\_(self, nums: List[int]):
        self.vec = self._to_sparse(nums)

    def _to_sparse(self, vec: List[int]):
        output = {}
        for i, e in enumerate(vec):
            if e != 0:
                output[i] = e
        return output

    # Return the dotProduct of two sparse vectors
    def dotProduct(self, vec: 'SparseVector') -> int:
        small = self.vec
        large = vec.vec
        if len(large) < len(small):
            small = vec.vec
            large = self.vec

        ret = 0
        for idx, val in small.items():
            if idx in large:
                ret += large[idx] * val
        return ret 

Less than 10 minutes. 7-8 minutes

O(n), O(n)

22
Q
  1. Basic Calculator II
    Medium/Hard
    Companies: Facebook

Given a string s which represents an expression, evaluate this expression and return its value.

The integer division should truncate toward zero.

You may assume that the given expression is always valid. All intermediate results will be in the range of [-231, 231 - 1].

Note: You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such as eval().

Example 1:

Input: s = “3+2*2”
Output: 7

Example 2:

Input: s = “ 3/2 “
Output: 1

Example 3:

Input: s = “ 3+5 / 2 “
Output: 5

Constraints:

1 <= s.length <= 3 * 105
s consists of integers and operators ('+', '-', '*', '/') separated by some number of spaces.
s represents a valid expression.
All the integers in the expression are non-negative integers in the range [0, 231 - 1].
The answer is guaranteed to fit in a 32-bit integer.

Do it in O(1) space and O(n) time

https://leetcode.com/problems/basic-calculator-ii/description/

A

Evaluate previous operations each time you read a number. The s+='+0' is just a easy way to keep the solution clean. Because we are always looking one operation behind.

class Solution(object):
    def calculate(self, s):
        """
        :type s: str
        :rtype: int
        """
        s = s.replace(' ', '')
        def calc(s):
            i = 0
            cur_num = ''
            op = '+'
            res = 0
            last_num = 0
            s += '+0'
            while i < len(s):
                if s[i] in {'+', '-', '*', '/'}:
                    op = s[i]
                    i+=1
                    continue
                elif s[i].isdigit():
                    while i < len(s) and s[i].isdigit():
                        cur_num += s[i]
                        i+=1
                    cur_num = int(cur_num)
                    if op == '-':
                        cur_num = -cur_num
                        res += last_num
                        last_num = cur_num
                    if op == '+':
                        res += last_num
                        last_num = cur_num
                    if op == '*':
                        last_num = last_num * cur_num
                    if op == '/':
                        last_num = int(last_num / (1.0 * cur_num))
                    cur_num = ''
            return res 
        return calc(s)

Hard question, 20 mins assigned

O(n), space O(1)

23
Q
  1. Basic Calculator
    Hard
    Companies DoorDash, Atlassian

Given a string s representing a valid expression, implement a basic calculator to evaluate it, and return the result of the evaluation.

Note: You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such as eval().

Example 1:

Input: s = “1 + 1”
Output: 2

Example 2:

Input: s = “ 2-1 + 2 “
Output: 3

Example 3:

Input: s = “(1+(4+5+2)-3)+(6+8)”
Output: 23

Constraints:

1 <= s.length <= 3 * 105
s consists of digits, '+', '-', '(', ')', and ' '.
s represents a valid expression.
'+' is not used as a unary operation (i.e., "+1" and "+(2 + 3)" is invalid).
'-' could be used as a unary operation (i.e., "-1" and "-(2 + 3)" is valid).
There will be no two consecutive operators in the input.
Every number and running calculation will fit in a signed 32-bit integer.

Do it in O(n) space and time

https://leetcode.com/problems/basic-calculator/description/

A

When doing current_num we have 2 states:
1. If we have a number
2. If we have open parentheses.

If we have parentheses send idx+1 in to evaluate and once evaluated, return the index+1 and current result. That index will be used to continue evaluations in parent method.

class Solution(object):
    def calculate(self, s):
        """
        :type s: str
        :rtype: int
        """
        def calc(s, i):
            cur_num = ''
            op = '+'
            res = 0
            while i < len(s):
                if s[i] == ')':
                    return res, i+1
                if s[i] in {'+', '-'}:
                    op = s[i]
                    i+=1
                else:
                    if s[i].isdigit():
                        while i < len(s) and s[i].isdigit():
                            cur_num += s[i]
                            i+=1
                        cur_num = int(cur_num)
                    elif s[i] == '(':
                        cur_num, i = calc(s, i+1)
                    if op == '-':
                            cur_num = -cur_num
                    res += cur_num
                    cur_num = ''
            return res
        s = s.replace(' ', '')
        return calc(s, 0)
24
Q
  1. Basic Calculator III
    Hard
    Companies N/A

Implement a basic calculator to evaluate a simple expression string.

The expression string contains only non-negative integers, ‘+’, ‘-‘, ‘*’, ‘/’ operators, and open ‘(‘ and closing parentheses ‘)’. The integer division should truncate toward zero.

You may assume that the given expression is always valid. All intermediate results will be in the range of [-231, 231 - 1].

Note: You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such as eval().

Example 1:

Input: s = “1+1”
Output: 2

Example 2:

Input: s = “6-4/2”
Output: 4

Example 3:

Input: s = “2(5+52)/3+(6/2+8)”
Output: 21

Constraints:

1 <= s <= 104
s consists of digits, '+', '-', '*', '/', '(', and ')'.
s is a valid expression.

Needs basic 1+2

https://leetcode.com/problems/basic-calculator-iii/description/

A

Building on Basic 1 and Basic 2 this is not too difficult but by itself, it might never be asked in interview as it will require a lot of time for someone who has never seen this before.

class Solution(object):
    def calculate(self, s):
        """
        :type s: str
        :rtype: int
        """
        def calc(s, i):
            cur_num = ''
            last_num = 0
            op = '+'
            res = 0
            while i < len(s):
                if s[i] == ')':
                    return res+last_num, i+1
                if s[i] in {'+', '-', '/', '*'}:
                    op = s[i]
                    i+=1
                else:
                    if s[i].isdigit():
                        while i < len(s) and s[i].isdigit():
                            cur_num += s[i]
                            i+=1
                        cur_num = int(cur_num)
                    elif s[i] == '(':
                        cur_num, i = calc(s,i+1)
                    if op == '-':
                        cur_num = -cur_num
                        res += last_num
                        last_num = cur_num
                    if op == '+':
                        res += last_num
                        last_num = cur_num
                    if op == '/':
                        last_num = int(last_num / (1.0 * cur_num))
                    if op == '*':
                        last_num = last_num * cur_num
                    cur_num = ''
            return last_num + res
        s = s.replace(' ', '')
        return calc(s, 0)

20 Minutes - Hard

O(n), O(n) space (recursion stack, each call is O(1) by itself)

25
Q
  1. Custom Sort String
    Medium
    Companies: facebook 2024

You are given two strings order and s. All the characters of order are unique and were sorted in some custom order previously.

Permute the characters of s so that they match the order that order was sorted. More specifically, if a character x occurs before a character y in order, then x should occur before y in the permuted string.

Return any permutation of s that satisfies this property.

Example 1:

Input: order = “cba”, s = “abcd”

Output: “cbad”

Explanation: “a”, “b”, “c” appear in order, so the order of “a”, “b”, “c” should be “c”, “b”, and “a”.

Since “d” does not appear in order, it can be at any position in the returned string. “dcba”, “cdba”, “cbda” are also valid outputs.

Example 2:

Input: order = “bcafg”, s = “abcd”

Output: “bcad”

Explanation: The characters “b”, “c”, and “a” from order dictate the order for the characters in s. The character “d” in s does not appear in order, so its position is flexible.

Following the order of appearance in order, “b”, “c”, and “a” from s should be arranged as “b”, “c”, “a”. “d” can be placed at any position since it’s not in order. The output “bcad” correctly follows this rule. Other arrangements like “bacd” or “bcda” would also be valid, as long as “b”, “c”, “a” maintain their order.

Constraints:

1 <= order.length <= 26
1 <= s.length <= 200
order and s consist of lowercase English letters.
All the characters of order are unique.

10 mins alloted, 15 max

https://leetcode.com/problems/custom-sort-string/

A

nLog(n) answer (not optimal, interviewer will ask for optimal)
~~~
from collections import defaultdict
class Solution(object):
def customSortString(self, order, s):
“””
:type order: str
:type s: str
:rtype: str
“””
ranks = defaultdict(int)
ranks = {c: i+1 for i, c in enumerate(order)}
idx_s = map(lambda x: (ranks.get(x, 0), x), s)
sorted_s = sorted(idx_s)
return ““.join(map(lambda i: i[1], sorted_s))
~~~

Optimal O(n) Using count/bucket sorting / freq table.
Create a list of buckets with length one greater than the order (the extra is for elements without any order).
each time you encounter a character from s, find its rank and add it to it’s bucket.

After that go through the list of buckets and just create output string.

from collections import defaultdict
class Solution:
    def customSortString(self, order: str, s: str) -> str:
        rank_d = {c: i+1 for i, c in enumerate(order)}
        freq_table = [[""] for _ in range(len(order)+1)]
        for c in s:
            freq_table[rank_d.get(c, 0)].append(c)
        ret = []
        for v in freq_table:
            ret.extend(v)
        return "".join(ret)

O(n) (optimal), O(n) space

26
Q
  1. Interval List Intersections
    Solved
    Medium
    Topics
    Companies

You are given two lists of closed intervals, firstList and secondList, where firstList[i] = [starti, endi] and secondList[j] = [startj, endj]. Each list of intervals is pairwise disjoint and in sorted order.

Return the intersection of these two interval lists.

A closed interval [a, b] (with a <= b) denotes the set of real numbers x with a <= x <= b.

The intersection of two closed intervals is a set of real numbers that are either empty or represented as a closed interval. For example, the intersection of [1, 3] and [2, 4] is [2, 3].

Example 1:

Input: firstList = [[0,2],[5,10],[13,23],[24,25]], secondList = [[1,5],[8,12],[15,24],[25,26]]
Output: [[1,2],[5,5],[8,10],[15,23],[24,24],[25,25]]

Example 2:

Input: firstList = [[1,3],[5,9]], secondList = []
Output: []

Constraints:

0 <= firstList.length, secondList.length <= 1000
firstList.length + secondList.length >= 1
0 <= starti < endi <= 109
endi < starti+1
0 <= startj < endj <= 109 
endj < startj+1

10 mins acceptable, 15 max

https://leetcode.com/problems/interval-list-intersections/description/

A
class Solution(object):
    def intervalIntersection(self, firstList, secondList):
        """
        :type firstList: List[List[int]]
        :type secondList: List[List[int]]
        :rtype: List[List[int]]
        """
        ret = []
        i = 0
        j = 0
        while i < len(firstList) and j < len(secondList):
            # Find the latest start point 
            start = max(firstList[i][0], secondList[j][0])
            # Find the earliest end point
            end = min(firstList[i][1], secondList[j][1])

            # If they were overlapping then start <= end otherwise not.
            if start <= end:
                ret.append([start, end])
            # keep the one with the latest end to compare against the next interval.
            if firstList[i][1] < secondList[j][1]:
                i+=1
            else:
                j += 1
        return ret

O(n), O(1) space (not counting return list)

27
Q
  1. Merge Intervals
    Medium
    Companies: Facebook 2024

Given an array of intervals where intervals[i] = [starti, endi], merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input.

Example 1:

Input: intervals = [[1,3],[2,6],[8,10],[15,18]]
Output: [[1,6],[8,10],[15,18]]
Explanation: Since intervals [1,3] and [2,6] overlap, merge them into [1,6].

Example 2:

Input: intervals = [[1,4],[4,5]]
Output: [[1,5]]
Explanation: Intervals [1,4] and [4,5] are considered overlapping.

Constraints:

1 <= intervals.length <= 104
intervals[i].length == 2
0 <= starti <= endi <= 104

10 - 15 mins hard cap

https://leetcode.com/problems/longest-consecutive-sequence/description/

A

Sort them by start.

class Solution(object):
    def merge(self, intervals):
        """
        :type intervals: List[List[int]]
        :rtype: List[List[int]]
        """
        s_intervals = sorted(intervals)
        ret = []
        for interval in s_intervals:
            if not ret:
                ret.append(interval)
            else:
                # next interval starts after previous ends
                if interval[0] > ret[-1][1]:
                    ret.append(interval)
                ret[-1][1] = max(interval[1], ret[-1][1])
        return ret

O(nLog(n)), O(n)

28
Q
  1. Minimum Add to Make Parentheses Valid
    Medium
    Companies: Facebook 2024

A parentheses string is valid if and only if:

It is the empty string,
It can be written as AB (A concatenated with B), where A and B are valid strings, or
It can be written as (A), where A is a valid string.

You are given a parentheses string s. In one move, you can insert a parenthesis at any position of the string.

For example, if s = "()))", you can insert an opening parenthesis to be "(()))" or a closing parenthesis to be "())))".

Return the minimum number of moves required to make s valid.

Example 1:

Input: s = “())”
Output: 1

Example 2:

Input: s = “(((“
Output: 3

Constraints:

1 <= s.length <= 1000
s[i] is either '(' or ')'.

10 min hard cap. O(n) time O(1) space expected.

https://leetcode.com/problems/minimum-add-to-make-parentheses-valid/description/

A
class Solution:
    def minAddToMakeValid(self, s: str) -> int:
        count_open = 0
        count_close = 0
        for i, c in enumerate(s):
            if c == '(':
                count_open += 1
            if c == ')':
                if count_open > 0:
                    count_open -= 1
                else:
                    count_close+=1
        return count_open + count_close

O(n), O(1) space

29
Q
  1. Group Shifted Strings
    Solved
    Medium
    Topics
    Companies

Perform the following shift operations on a string:

Right shift: Replace every letter with the successive letter of the English alphabet, where 'z' is replaced by 'a'. For example, "abc" can be right-shifted to "bcd" or "xyz" can be right-shifted to "yza".
Left shift: Replace every letter with the preceding letter of the English alphabet, where 'a' is replaced by 'z'. For example, "bcd" can be left-shifted to "abc" or "yza" can be left-shifted to "xyz".

We can keep shifting the string in both directions to form an endless shifting sequence.

For example, shift "abc" to form the sequence: ... <-> "abc" <-> "bcd" <-> ... <-> "xyz" <-> "yza" <-> .... <-> "zab" <-> "abc" <-> ...

You are given an array of strings strings, group together all strings[i] that belong to the same shifting sequence. You may return the answer in any order.

Example 1:

Input: strings = [“abc”,”bcd”,”acef”,”xyz”,”az”,”ba”,”a”,”z”]

Output: [[“acef”],[“a”,”z”],[“abc”,”bcd”,”xyz”],[“az”,”ba”]]

Example 2:

Input: strings = [“a”]

Output: [[“a”]]

Constraints:

1 <= strings.length <= 200
1 <= strings[i].length <= 50
strings[i] consists of lowercase English letters.

10-15 mins Linear Time

https://leetcode.com/problems/group-shifted-strings/description/

A

If the diff in 2 chars is negative,
eg za and ab are same, the diff is -25,1
there are 26 letters in the alphabet, thus 26 + (-25) = 1
basically it’s to say a and z are 1 apart.
Make a list then convert to tuple.

class Solution:
    def groupStrings(self, strings: List[str]) -> List[List[str]]:
        d = defaultdict(list)
        for s in strings:
            if len(s) == 1:
                d[(0)].append(s)
            else:
                pattern = []
                for i in range(1, len(s)):
                    diff = ord(s[i])-ord(s[i-1])
                    if diff < 0:
                        diff = (ord('z')-ord('a')) + diff + 1
                    pattern.append(diff)
                d[tuple(pattern)].append(s)
        output = []
        for v in d.values():
            output.append(v)
        return output
30
Q
  1. Subarray Sum Equals K
    Medium
    Companies: Facebook 2024

Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k.

A subarray is a contiguous non-empty sequence of elements within an array.

Example 1:

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

Example 2:

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

Constraints:

1 <= nums.length <= 2 * 104
-1000 <= nums[i] <= 1000
-107 <= k <= 107

2 Solutions O(n), O(n) space and O(n^2), O(1) space 20 mins for both.

https://leetcode.com/problems/subarray-sum-equals-k/description/

A

O(n) Solution, O(n) space (recommended to give O(n^2) solution first (the second one) and then this one.

from collections import defaultdict
class Solution(object):
    def subarraySum(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        ret = 0
        prefixSumStore = defaultdict(int)
        prefixSumStore[0] += 1
        prefixSum = 0
        for n in nums:
            prefixSum += n
            ret += prefixSumStore[prefixSum-k]
            prefixSumStore[prefixSum] += 1
        return ret

Constant Space Solution (most likely will ask) if you give the first one as the first solution.

from collections import defaultdict

class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        ret = 0
        total = 0
        for start in range(len(nums)):
            total = 0
            for end in range(start, len(nums)):
                total += nums[end]
                if total == k:
                    ret += 1
        return ret
31
Q
  1. Product of Two Run-Length Encoded Arrays
    Solved
    Medium
    Topics
    Companies
    Hint
    Run-length encoding is a compression algorithm that allows for an integer array nums with many segments of consecutive repeated numbers to be represented by a (generally smaller) 2D array encoded. Each encoded[i] = [vali, freqi] describes the ith segment of repeated numbers in nums where vali is the value that is repeated freqi times.

For example, nums = [1,1,1,2,2,2,2,2] is represented by the run-length encoded array encoded = [[1,3],[2,5]]. Another way to read this is “three 1’s followed by five 2’s”.
The product of two run-length encoded arrays encoded1 and encoded2 can be calculated using the following steps:

Expand both encoded1 and encoded2 into the full arrays nums1 and nums2 respectively.
Create a new array prodNums of length nums1.length and set prodNums[i] = nums1[i] * nums2[i].
Compress prodNums into a run-length encoded array and return it.
You are given two run-length encoded arrays encoded1 and encoded2 representing full arrays nums1 and nums2 respectively. Both nums1 and nums2 have the same length. Each encoded1[i] = [vali, freqi] describes the ith segment of nums1, and each encoded2[j] = [valj, freqj] describes the jth segment of nums2.

Return the product of encoded1 and encoded2.

Note: Compression should be done such that the run-length encoded array has the minimum possible length.

Example 1:

Input: encoded1 = [[1,3],[2,3]], encoded2 = [[6,3],[3,3]]
Output: [[6,6]]
Explanation: encoded1 expands to [1,1,1,2,2,2] and encoded2 expands to [6,6,6,3,3,3].
prodNums = [6,6,6,6,6,6], which is compressed into the run-length encoded array [[6,6]].
Example 2:

Input: encoded1 = [[1,3],[2,1],[3,2]], encoded2 = [[2,3],[3,3]]
Output: [[2,3],[6,1],[9,2]]
Explanation: encoded1 expands to [1,1,1,2,3,3] and encoded2 expands to [2,2,2,3,3,3].
prodNums = [2,2,2,6,9,9], which is compressed into the run-length encoded array [[2,3],[6,1],[9,2]].

Constraints:

1 <= encoded1.length, encoded2.length <= 105
encoded1[i].length == 2
encoded2[j].length == 2
1 <= vali, freqi <= 104 for each encoded1[i].
1 <= valj, freqj <= 104 for each encoded2[j].
The full arrays that encoded1 and encoded2 represent are the same length.

Element Wise Multiplication.

https://leetcode.com/problems/product-of-two-run-length-encoded-arrays/description/

A
from collections import deque
class Solution(object):
    def findRLEArray(self, encoded1, encoded2):
        """
        :type encoded1: List[List[int]]
        :type encoded2: List[List[int]]
        :rtype: List[List[int]]
        """
        res = deque()
        carry = 0
        one, two = encoded1.pop(), encoded2.pop()
            
        while True:
            freq = min(one[1], two[1])
            prod = one[0] * two[0]
            one[1] -= freq
            two[1] -= freq
            if res and res[0][0] == prod:
                res[0][1] += freq
            else:
                res.appendleft([prod, freq])
            if not one[1] and encoded1:
                one = encoded1.pop()
            if not two[1] and encoded2:
                two = encoded2.pop()
            elif not two[1] and not one[1]:
                break
        return res
32
Q
  1. Valid Number
    Solved
    Hard
    Topics
    Companies
    Given a string s, return whether s is a valid number.

For example, all the following are valid numbers: “2”, “0089”, “-0.1”, “+3.14”, “4.”, “-.9”, “2e10”, “-90E3”, “3e+7”, “+6e-1”, “53.5e93”, “-123.456e789”, while the following are not valid numbers: “abc”, “1a”, “1e”, “e3”, “99e2.5”, “–6”, “-+3”, “95a54e53”.

Formally, a valid number is defined using one of the following definitions:

An integer number followed by an optional exponent.
A decimal number followed by an optional exponent.
An integer number is defined with an optional sign ‘-‘ or ‘+’ followed by digits.

A decimal number is defined with an optional sign ‘-‘ or ‘+’ followed by one of the following definitions:

Digits followed by a dot ‘.’.
Digits followed by a dot ‘.’ followed by digits.
A dot ‘.’ followed by digits.
An exponent is defined with an exponent notation ‘e’ or ‘E’ followed by an integer number.

The digits are defined as one or more digits.

Example 1:

Input: s = “0”

Output: true

Example 2:

Input: s = “e”

Output: false

Example 3:

Input: s = “.”

Output: false

Constraints:

1 <= s.length <= 20
s consists of only English letters (both uppercase and lowercase), digits (0-9), plus ‘+’, minus ‘-‘, or dot ‘.’.

Hint: Follow the rules and simplify the logic.

https://leetcode.com/problems/valid-number/description/

A
class Solution:
    def isNumber(self, s: str) -> bool:

        dp = [0]*len(s)
        exponent = {'e', 'E'}
        sign = {'+', '-'}
        if s and s[0] in sign:
            s = s[1:]
        sign_possible = False
        seen_exp = False
        seen_dec = False
        seen_digit = False

        for i, c in enumerate(s):
            if c.isdigit():
                seen_digit = True
            elif c in exponent:
                if not seen_digit or seen_exp or i < 1:
                    return False
                else:
                    seen_exp = True
                    seen_digit = False
                    sign_possible = True
            elif c == '.':
                if seen_exp or seen_dec:
                    return False
                else:
                    seen_dec = True
            elif c in sign:
                if not sign_possible or (i > 0 and s[i-1] not in exponent):
                    return False
            else:
                return False
        return seen_digit

A Bit more intuitive, break the number to 2 parts expnent and decimal, and verify them
left should be valid decimal and right should be valid exponent (if it exists). Split the decimal in two, and then join them to make one number (without decimal), it should have at least one digit and the right split should NOT start with a sign because if left is empty then .+1 will look like +1

class Solution(object):
    @staticmethod 
    def isSignedInteger(s):
        if not s:
            return False
        if s[0] in {'+', '-'}:
            s = s[1:]
        return Solution.isInteger(s)
            
            
    @staticmethod 
    def isInteger(s):
        if not s:
            return False
        for c in s:
            if not c.isdigit():
                return False
        return True

    @staticmethod 
    def isDecimal(s):
        if not s:
            return False
        split = s.split(".")
        if len(split) > 2:
            return False
        left = split[0]
        full = left
        if len(split) == 2:
            right = split[1]
            if right and right[0] in {'+', '-'}:
                return False
            full += right
      
        return Solution.isSignedInteger(full)
    
    @staticmethod 
    def isExponent(s):
        split = s.split("e")
        if len(split) > 2:
            return False
        if len(split) == 2:
            return Solution.isDecimal(split[0]) and Solution.isSignedInteger(split[1])
        if len(split) == 1:
            return Solution.isDecimal(split[0])

        
    def isNumber(self, s):
        """
        :type s: str
        :rtype: bool
        """
        s = s.lower()
        return Solution.isExponent(s)
33
Q
  1. Missing Ranges
    Easy
    Companies: Facebook
    You are given an inclusive range [lower, upper] and a sorted unique integer array nums, where all elements are within the inclusive range.

A number x is considered missing if x is in the range [lower, upper] and x is not in nums.

Return the shortest sorted list of ranges that exactly covers all the missing numbers. That is, no element of nums is included in any of the ranges, and each missing number is covered by one of the ranges.

Example 1:

Input: nums = [0,1,3,50,75], lower = 0, upper = 99
Output: [[2,2],[4,49],[51,74],[76,99]]
Explanation: The ranges are:
[2,2]
[4,49]
[51,74]
[76,99]
Example 2:

Input: nums = [-1], lower = -1, upper = -1
Output: []
Explanation: There are no missing ranges since there are no missing numbers.

Constraints:

-109 <= lower <= upper <= 109
0 <= nums.length <= 100
lower <= nums[i] <= upper
All the values of nums are unique.

Careful of edge cases

https://leetcode.com/problems/missing-ranges/description/

A
class Solution(object):
    def findMissingRanges(self, nums, lower, upper):
        """
        :type nums: List[int]
        :type lower: int
        :type upper: int
        :rtype: List[List[int]]
        """
        ranges = []
        i = 0

        if not nums:
            ranges.append([lower, upper])
            return ranges

        if nums[0] != lower:
            ranges.append([lower, nums[0]-1])

        for i in range(len(nums)):
            if i > 0 and nums[i-1]+1 == nums[i]:
                continue
            elif i > 0:
                r = [ nums[i-1]+1,  nums[i]-1]
                ranges.append(r)
                i+=1

        if nums[-1] != upper:
            ranges.append([nums[-1] + 1, upper])
        return ranges
34
Q
  1. Verifying an Alien Dictionary
    Solved
    Easy
    Topics
    Companies
    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 lexicographically in this alien language.

Example 1:

Input: words = [“hello”,”leetcode”], order = “hlabcdefgijkmnopqrstuvwxyz”
Output: true
Explanation: As ‘h’ comes before ‘l’ in this language, then the sequence is sorted.
Example 2:

Input: words = [“word”,”world”,”row”], order = “worldabcefghijkmnpqstuvxyz”
Output: false
Explanation: As ‘d’ comes after ‘l’ in this language, then words[0] > words[1], hence the sequence is unsorted.
Example 3:

Input: words = [“apple”,”app”], order = “abcdefghijklmnopqrstuvwxyz”
Output: false
Explanation: The first three characters “app” match, and the second string is shorter (in size.) According to lexicographical rules “apple” > “app”, because ‘l’ > ‘∅’, where ‘∅’ is defined as the blank character which is less than any other character (More info).

Constraints:

1 <= words.length <= 100
1 <= words[i].length <= 20
order.length == 26
All characters in words[i] and order are English lowercase letters.

(do the simplest way)

https://leetcode.com/problems/verifying-an-alien-dictionary/

A

One Liner
avg letter in word: m
len of words: n
len or order: l

n*mLog(m) + l (Its a guess as I do not know how does python sort lists with individual values)

from collections import defaultdict
class Solution(object):
    def isAlienSorted(self, words, order):
        """
        :type words: List[str]
        :type order: str
        :rtype: bool
        """
        order_dict = {c: i for i,c in enumerate(order)}
        modified = list(map(lambda word: map(lambda c: order_dict[c], word), words))
        return modified == sorted(modified)

Proper
O(m*n + l)
~~~
from itertools import zip_longest
class Solution:
def isAlienSorted(self, words: List[str], order: str) -> bool:
order_dict = {c:i for i,c in enumerate(order)}
order_dict[’$’] = -1

    # pair of words
    for word_a, word_b in zip(words, words[1:]):
        for letter_a, letter_b in zip_longest(word_a, word_b, fillvalue='$'):
            if order_dict[letter_a] < order_dict[letter_b]:
                break
            if order_dict[letter_a] > order_dict[letter_b]:
                return False
    return True ~~~
35
Q
  1. Next Permutation
    Hard - Impossible without prior algo knowledge.
    Companies: Facebook
    A permutation of an array of integers is an arrangement of its members into a sequence or linear order.

For example, for arr = [1,2,3], the following are all the permutations of arr: [1,2,3], [1,3,2], [2, 1, 3], [2, 3, 1], [3,1,2], [3,2,1].
The next permutation of an array of integers is the next lexicographically greater permutation of its integer. More formally, if all the permutations of the array are sorted in one container according to their lexicographical order, then the next permutation of that array is the permutation that follows it in the sorted container. If such arrangement is not possible, the array must be rearranged as the lowest possible order (i.e., sorted in ascending order).

For example, the next permutation of arr = [1,2,3] is [1,3,2].
Similarly, the next permutation of arr = [2,3,1] is [3,1,2].
While the next permutation of arr = [3,2,1] is [1,2,3] because [3,2,1] does not have a lexicographical larger rearrangement.
Given an array of integers nums, find the next permutation of nums.

The replacement must be in place and use only constant extra memory.

Example 1:

Input: nums = [1,2,3]
Output: [1,3,2]
Example 2:

Input: nums = [3,2,1]
Output: [1,2,3]
Example 3:

Input: nums = [1,1,5]
Output: [1,5,1]

Constraints:

1 <= nums.length <= 100
0 <= nums[i] <= 100

If you know you know, otherwise, see answer.

https://leetcode.com/problems/next-permutation/description/

A
class Solution:
    def nextPermutation(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """

        def reverse(n, start, stop):
            while start < stop:
                n[start], n[stop] = n[stop], n[start]
                start += 1
                stop -= 1

        pivot_idx = -1
        n = len(nums)
        prev = float('-inf')

        for i in range(n-1, -1,-1):
            if nums[i] < prev:
                pivot_idx = i
                break
            prev = nums[i]
        
        if pivot_idx == -1:
            reverse(nums, 0, len(nums)-1)
            return

        pivot = nums[pivot_idx]
        swap_idx = n-1
        
        for i in range(n-1, pivot_idx, -1):
            if nums[i] > pivot:
                swap_idx = i
                break

        nums[swap_idx], nums[pivot_idx] = nums[pivot_idx], nums[swap_idx]

        reverse(nums, pivot_idx+1, n-1)
        return

https://www.nayuki.io/page/next-lexicographical-permutation-algorithm

36
Q
  1. Multiply Strings
    Solved
    Medium
    Topics
    Companies
    Given two non-negative integers num1 and num2 represented as strings, return the product of num1 and num2, also represented as a string.

Note: You must not use any built-in BigInteger library or convert the inputs to integer directly.

Example 1:

Input: num1 = “2”, num2 = “3”
Output: “6”
Example 2:

Input: num1 = “123”, num2 = “456”
Output: “56088”

Constraints:

1 <= num1.length, num2.length <= 200
num1 and num2 consist of digits only.
Both num1 and num2 do not contain any leading zero, except the number 0 itself.

https://leetcode.com/problems/multiply-strings/

A
class Solution:
    def multiply(self, num1: str, num2: str) -> str:
        
        def digit(c):
            return ord(c) - ord('0')

        def multiply_small(number, d):
            carry = 0
            num = 0
            for i, c in enumerate(number[::-1]):
                product = digit(c) * digit(d) + carry
                cur_digit = product%10
                carry = product//10
                num = cur_digit * (10**i) + num
            if carry:
                num = carry * (10**(i+1)) + num
            return num

        big, small = num1, num2
        if len(num1) < len(num2):
            big, small = small, big

        p = 0
        num = 0
        for i, c in enumerate(small[::-1]):
            num = (10**i) * multiply_small(big, c) + num
            p+=1
        return str(num)
37
Q
  1. Contiguous Array
    Medium
    Companies: Facebook
    Given a binary array nums, return the maximum length of a contiguous subarray with an equal number of 0 and 1.

Example 1:

Input: nums = [0,1]
Output: 2
Explanation: [0, 1] is the longest contiguous subarray with an equal number of 0 and 1.
Example 2:

Input: nums = [0,1,0]
Output: 2
Explanation: [0, 1] (or [1, 0]) is a longest contiguous subarray with equal number of 0 and 1.

Constraints:

1 <= nums.length <= 105
nums[i] is either 0 or 1.

https://leetcode.com/problems/contiguous-array/description/?envType=company&envId=facebook&favoriteSlug=facebook-thirty-days

A
from itertools import accumulate

class Solution:
    def findMaxLength(self, nums: List[int]) -> int:
        # Use the sum to track, like how many extra parenthesis to remove
        # Negative count means we just need to remove a subarray with that many extra 0's
        # We store the first occurance of such a subarray where either 1's or 0's are in excess, this will
        # allow us to get longest, i.e to subtract the minimum amount of index. 
        # 0  0  0  1  0  0  0  1  1  1 
        #      -3 -2 -3 -4 -5 -4 -3 -2
        # In the above example at the second last 1, we are 3 zeros extra, we just need to remove the earlist subarray
        # with the same excess zeros. The number of 1's will  be the same as number of zeros no matter which -3 you choose
        # either at idx 2 or 4 that's why we just store it once.
        sum_store = {}
        count = 0
        longest = 0
        for i,c in enumerate(nums):
            count += c if c else -1
            if not count:
                longest = i+1
            else:
                if count in sum_store:
                    longest = max(longest, i - sum_store[count])
                else:
                    sum_store[count] = i
        return longest

O(n), O(n)

38
Q
  1. Continuous Subarray Sum
    Solved
    Medium
    Topics
    Companies
    Given an integer array nums and an integer k, return true if nums has a good subarray or false otherwise.

A good subarray is a subarray where:

its length is at least two, and
the sum of the elements of the subarray is a multiple of k.
Note that:

A subarray is a contiguous part of the array.
An integer x is a multiple of k if there exists an integer n such that x = n * k. 0 is always a multiple of k.

Example 1:

Input: nums = [23,2,4,6,7], k = 6
Output: true
Explanation: [2, 4] is a continuous subarray of size 2 whose elements sum up to 6.
Example 2:

Input: nums = [23,2,6,4,7], k = 6
Output: true
Explanation: [23, 2, 6, 4, 7] is an continuous subarray of size 5 whose elements sum up to 42.
42 is a multiple of 6 because 42 = 7 * 6 and 7 is an integer.
Example 3:

Input: nums = [23,2,6,4,7], k = 13
Output: false

Constraints:

1 <= nums.length <= 105
0 <= nums[i] <= 109
0 <= sum(nums[i]) <= 231 - 1
1 <= k <= 231 - 1

https://leetcode.com/problems/continuous-subarray-sum/description/

A

Remember here: every number with the same mod with k, will be multiples of k away from each other.

eg 17,23,29,35 , k = 6
they all have mod 5 and all are multiples of 6 away from each other.

Thus update the subarray with the earliest index for a mod, if you find it later, removing that subarray will gurantee multiple of 6 sum as they HAVE to be in multiples of 6 away from each other

thus do accumulate on them, mod them by k and that is your prefix-sum
then it becomes the same as subarray sum = k
~~~
from collections import defaultdict
from itertools import accumulate

class Solution:
def checkSubarraySum(self, nums: List[int], k: int) -> bool:
modmap = defaultdict(int)
modmap[0] = -1 # Replaces # if mod is 0, and i > 0 : return True
mod_prefix_sum = list(map(lambda x: x%k, accumulate(nums)))
for i, mod in enumerate(mod_prefix_sum):
if mod in modmap:
if i-modmap[mod] > 1:
return True
else:
modmap[mod] = i
return False
~~~

39
Q
  1. High-Access Employees
    Medium
    Topics
    Companies: Atlassian
    You are given a 2D 0-indexed array of strings, access_times, with size n. For each i where 0 <= i <= n - 1, access_times[i][0] represents the name of an employee, and access_times[i][1] represents the access time of that employee. All entries in access_times are within the same day.

The access time is represented as four digits using a 24-hour time format, for example, “0800” or “2250”.

An employee is said to be high-access if he has accessed the system three or more times within a one-hour period.

Times with exactly one hour of difference are not considered part of the same one-hour period. For example, “0815” and “0915” are not part of the same one-hour period.

Access times at the start and end of the day are not counted within the same one-hour period. For example, “0005” and “2350” are not part of the same one-hour period.

Return a list that contains the names of high-access employees with any order you want.

Example 1:

Input: access_times = [[“a”,”0549”],[“b”,”0457”],[“a”,”0532”],[“a”,”0621”],[“b”,”0540”]]
Output: [“a”]
Explanation: “a” has three access times in the one-hour period of [05:32, 06:31] which are 05:32, 05:49, and 06:21.
But “b” does not have more than two access times at all.
So the answer is [“a”].
Example 2:

Input: access_times = [[“d”,”0002”],[“c”,”0808”],[“c”,”0829”],[“e”,”0215”],[“d”,”1508”],[“d”,”1444”],[“d”,”1410”],[“c”,”0809”]]
Output: [“c”,”d”]
Explanation: “c” has three access times in the one-hour period of [08:08, 09:07] which are 08:08, 08:09, and 08:29.
“d” has also three access times in the one-hour period of [14:10, 15:09] which are 14:10, 14:44, and 15:08.
However, “e” has just one access time, so it can not be in the answer and the final answer is [“c”,”d”].
Example 3:

Input: access_times = [[“cd”,”1025”],[“ab”,”1025”],[“cd”,”1046”],[“cd”,”1055”],[“ab”,”1124”],[“ab”,”1120”]]
Output: [“ab”,”cd”]
Explanation: “ab” has three access times in the one-hour period of [10:25, 11:24] which are 10:25, 11:20, and 11:24.
“cd” has also three access times in the one-hour period of [10:25, 11:24] which are 10:25, 10:46, and 10:55.
So the answer is [“ab”,”cd”].

Constraints:

1 <= access_times.length <= 100
access_times[i].length == 2
1 <= access_times[i][0].length <= 10
access_times[i][0] consists only of English small letters.
access_times[i][1].length == 4
access_times[i][1] is in 24-hour time format.
access_times[i][1] consists only of ‘0’ to ‘9’.

https://leetcode.com/problems/high-access-employees/description

A
from itertools import starmap, groupby
from collections import deque,defaultdict
class Solution:
    def findHighAccessEmployees(self, access_times: List[List[str]]) -> List[str]:
        time_check = defaultdict(deque)
        def std_time(mil_time):
            mins = int(mil_time[2:])
            hrs = int(mil_time[:2])
            return mins + (hrs * 60)

        entries_sorted = sorted(starmap(lambda emp, t: (emp, std_time(t)), access_times), key=lambda x:(x[0], x[1]))
        hae = set()

        for emp, time_mins in entries_sorted:
            # We already marked this employe High Access, no need for further checks.
            if emp in hae:
                continue
            if emp not in time_check:
                time_check[emp].append(time_mins)
                continue
            else:
                while time_check[emp] and time_mins - time_check[emp][0] >= 60:
                    time_check[emp].popleft()
                time_check[emp].append(time_mins)
                if len(time_check[emp]) >= 3:
                    hae.add(emp)
        return list(hae)

O(nLog(n)), space O(n)

40
Q
  1. Rank Teams by Votes
    Medium
    In a special ranking system, each voter gives a rank from highest to lowest to all teams participating in the competition.

The ordering of teams is decided by who received the most position-one votes. If two or more teams tie in the first position, we consider the second position to resolve the conflict, if they tie again, we continue this process until the ties are resolved. If two or more teams are still tied after considering all positions, we rank them alphabetically based on their team letter.

You are given an array of strings votes which is the votes of all voters in the ranking systems. Sort all teams according to the ranking system described above.

Return a string of all teams sorted by the ranking system.

Example 1:

Input: votes = [“ABC”,”ACB”,”ABC”,”ACB”,”ACB”]
Output: “ACB”
Explanation:
Team A was ranked first place by 5 voters. No other team was voted as first place, so team A is the first team.
Team B was ranked second by 2 voters and ranked third by 3 voters.
Team C was ranked second by 3 voters and ranked third by 2 voters.
As most of the voters ranked C second, team C is the second team, and team B is the third.
Example 2:

Input: votes = [“WXYZ”,”XYZW”]
Output: “XWYZ”
Explanation:
X is the winner due to the tie-breaking rule. X has the same votes as W for the first position, but X has one vote in the second position, while W does not have any votes in the second position.
Example 3:

Input: votes = [“ZMNAGUEDSJYLBOPHRQICWFXTVK”]
Output: “ZMNAGUEDSJYLBOPHRQICWFXTVK”
Explanation: Only one voter, so their votes are used for the ranking.

Constraints:

1 <= votes.length <= 1000
1 <= votes[i].length <= 26
votes[i].length == votes[j].length for 0 <= i, j < votes.length.
votes[i][j] is an English uppercase letter.
All characters of votes[i] are unique.
All the characters that occur in votes[0] also occur in votes[j] where 1 <= j < votes.length.

https://leetcode.com/problems/rank-teams-by-votes

A
from collections import defaultdict

class Solution(object):
    def rankTeams(self, votes):
        """
        :type votes: List[str]
        :rtype: str
        """
        votelen = len(votes[0]) - 1
        count = defaultdict(lambda: [0]*len(votes[0]))
    
        for vote in votes:
            for i in range(len(vote)):
                count[vote[i]][i] += 1
        
        entries = []
        for k, v in count.items():
            entries.append((v, k))
        entries = sorted(entries, reverse=True, key=lambda x: (x[0], -ord(x[1])))

        answer = "".join(list(map(lambda e: e[1], entries)))
        return answer
41
Q
  1. Majority Element II
    Medium
    Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times.

Example 1:

Input: nums = [3,2,3]
Output: [3]
Example 2:

Input: nums = [1]
Output: [1]
Example 3:

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

Constraints:

1 <= nums.length <= 5 * 104
-109 <= nums[i] <= 109

Follow up: Could you solve the problem in linear time and in O(1) space?

https://leetcode.com/problems/majority-element-ii

A
from collections import defaultdict
class Solution:
    def majorityElement(self, nums: List[int]) -> List[int]:
        counts = defaultdict(int)
        for num in nums:
            if num not in counts and len(counts) >= 2:
                candidates = list(counts.keys())
                for k in candidates:
                    counts[k] -= 1
                    if counts[k] < 1:
                        del[counts[k]]                    
            else:
                counts[num] += 1
        return filter(lambda k: nums.count(k) > len(nums)//3, counts.keys())
42
Q

Subarray with k-distinct elements
(no leetcode)

Return the number of subarrays in the given nums array that have k distinct elements.

nums = [1,2,6,6,3,6,7,1,8]
k = 3
k_distinct(nums, k)

Output: 9
[1, 2, 6]
[1, 2, 6, 6]
[2, 6, 6, 3]
[2, 6, 6, 3, 6]
[6, 6, 3, 6, 7]
[6, 3, 6, 7]
[3, 6, 7]
[6, 7, 1]
[7, 1, 8]
A
from collections import defaultdict

def k_distinct(nums, k):
    uniq = {}
    l = 0
    r = 0
    subarr = 0
    while r < len(nums):
        if nums[r] in uniq:
            uniq[nums[r]] += 1
        else:
            uniq[nums[r]] = 1
        if len(uniq) == k:
            subarr+=1
            print(nums[l:r+1])
        elif len(uniq) == k+1:
            while len(uniq) == k+1 and l < r:
                uniq[nums[l]] -= 1
                if uniq[nums[l]] == 0:
                    del(uniq[nums[l]])
                l += 1
                if len(uniq) == k+1:
                    subarr+=1
                    print(nums[l:r])
            if len(uniq) == k:
                subarr += 1
                print(nums[l:r+1])
        r+=1
    return subarr
43
Q
  1. First Missing Positive
    Solved
    Hard
    Topics
    Companies
    Hint
    Given an unsorted integer array nums. Return the smallest positive integer that is not present in nums.

You must implement an algorithm that runs in O(n) time and uses O(1) auxiliary space.

Example 1:

Input: nums = [1,2,0]
Output: 3
Explanation: The numbers in the range [1,2] are all in the array.
Example 2:

Input: nums = [3,4,-1,1]
Output: 2
Explanation: 1 is in the array but 2 is missing.
Example 3:

Input: nums = [7,8,9,11,12]
Output: 1
Explanation: The smallest positive integer 1 is missing.

Constraints:

1 <= nums.length <= 105
-231 <= nums[i] <= 231 - 1

https://leetcode.com/problems/first-missing-positive/description/

A

Observe the answer has to be in range 1 to n+1 n is len
if we have array of length 3
[1,2,3]
the missing number is 4
[-1,-2,-3] the missing number is 1
[1,99,3] the missing number is 2
[1,2,4] the missing number is 3

it is because you can only fit n numbers in array of length n, so best case you fit all 1 to n the answer is n+1

Solution: Arranges the array in a way where each positive number in the range 1-to-n in its correct location. i.e num-1 i.e 3 will sit at idx 2 (0 indexed)
if the numbers are negative or larger than n, then just ignore then,

Once the swapping is done, return the first number which is not at it’s location, else return n+1 since if all numbers are at their locations then it means the array is complete.

class Solution(object):
    def firstMissingPositive(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        for i in range(n):
            while 0 < nums[i] <= n and nums[i] != nums[nums[i] - 1]:
                a, b = nums[i] - 1, i
                nums[a], nums[b] = nums[b], nums[a]
        
        for i in range(n):
            if nums[i] != i+1:
                return i+1
        
        return n+1