January LeetCoding Challenge 2021 Flashcards

1
Q
  1. Palindrome Permutation
    Given a string, determine if a permutation of the string could form a palindrome.

Input: “code”
Output: false

Input: “aab”
Output: true

A

In case of a palindrome, the number of characters with odd number of occurrences can’t exceed 1.

map(c, #occurences of c)

Time O(n), Space O(1) cuz the number of distinct characters are bounded

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q
  1. Check Array Formation Through Concatenation

You are given an array of distinct integers “arr” and an array of integer arrays “pieces”, where the integers in “pieces” are distinct. Your goal is to form “arr” by concatenating the arrays in “pieces” in any order. However, you are not allowed to reorder the integers in each array pieces[i].

Return true if it is possible to form the array “arr” from “pieces”. Otherwise, return false.

Input: arr = [15,88], pieces = [[88],[15]]
Output: true

Input: arr = [91,4,64,78], pieces = [[78],[4,64],[91]]
Output: true

Input: arr = [49,18,16], pieces = [[16,18,49]]
Output: false
Explanation: Even though the numbers match, we cannot reorder pieces[0].

A

Store the “pieces” according to their first element in a hashmap. Find the piece starting with arr[i] in mapping. Return false if no match. Check whether each integer in the piece matches arr’s sublist starting from i with the same length.

Time O(N), Space O(N), N length of arr

class Solution:
    def canFormArray(self, arr, pieces):
        n = len(arr)
        mapping = {p[0]: p for p in pieces}
        i = 0
        while i < n:
            if arr[i] not in mapping:
                return False
            target_piece = mapping[arr[i]]
            for x in target_piece:
                if x != arr[i]:
                    return False
                i += 1
    return True
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q
  1. Find a Corresponding Node of a Binary Tree in a Clone of That Tree

Given two binary trees original and cloned and given a reference to a node target in the original tree.

The cloned tree is a copy of the original tree.

Return a reference to the same node in the cloned tree.

Note that you are not allowed to change any of the two trees or the target node and the answer must be a reference to a node in the cloned tree.

Follow up: Solve the problem if repeated values on the tree are allowed.

A

Let’s traverse both trees in parallel, and once the target node is identified in the first tree, return the corresponding node from the second tree.

1) DFS: Time O(N), Space O(H) to keep the recursion stack, where H is a tree height.
inorder / preorder / postorder

    def inorder(o: TreeNode, c: TreeNode):
        if o:
            inorder(o.left, c.left)
            if o is target:
                self.ans = c
            inorder(o.right, c.right)

    inorder(original, cloned)
    return self.ans 

2) BFS: Time O(N), Space O(N) to keep the queue. Let’s use the last level to estimate the queue size. This level could contain up to N/2 tree nodes in the case of complete binary tree.

    qor, qcl = deque(), deque()
    nor, ncl = original, cloned
        while nor!=target:
            if nor:
                qor.append(nor.left)
                qor.append(nor.right)
                qcl.append(ncl.left)
                qcl.append(ncl.right)
            nor = qor.popleft()
            ncl = qcl.popleft()
        return ncl
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q
  1. Beautiful Arrangement

Suppose you have n integers from 1 to n. We define a beautiful arrangement as an array that is constructed by these n numbers successfully if one of the following is true for the ith position (1 <= i <= n) in this array:

The number at the ith position is divisible by i.
i is divisible by the number at the ith position.
Given an integer n, return the number of the beautiful arrangements that you can construct. (1 <= n <= 15)

Input: n = 2
Output: 2
Explanation:
The first beautiful arrangement is [1, 2]:
Number at the 1st position (i=1) is 1, and 1 is divisible by i (i=1).
Number at the 2nd position (i=2) is 2, and 2 is divisible by i (i=2).
The second beautiful arrangement is [2, 1]:
Number at the 1st position (i=1) is 2, and 2 is divisible by i (i=1).
Number at the 2nd position (i=2) is 1, and i (i=2) is divisible by 1.

A

1) Brute force O(n!)

2) Backtracking
我们使用一个使用一个大小为 n 的 “已使用数组” ,这里 visited[i]表示目前为止第 i 个数字是否已经使用过.
我们使用函数 helper,它将从 1 到 n 所有还没有visited数字放到当前位置 idx,并检查是否满足divisible。如果 i 放到当前位置 idx 是满足要求的,我们就把 i 放在当前位置 idx 并继续考虑下一个位置 idx + 1,否则我们需要换一个数字放在当前位置。

class Solution:
ans = 0
def countArrangement(self, n: int) -> int:
def helper(visited, idx):
if idx>n: #判断否已进入最底层
self.ans += 1
return
for i in range(n): #每一层遍历
#剪枝
if visited[i]==0 and (((i+1)%idx==0) | (idx%(i+1)==0)):
visited[i] = 1
helper(visited, idx+1) #递归
visited[i] = 0 #递归结束后将visited[i]重置

    visited = [0] * n
    helper(visited, 1)
    return self.ans
Time O(k). k the number of valid permutations.  递归深度为n层,但每一层需要执行的递归次数却是由该层的固定位置下可能存在的优美排列的数量决定的。 因此,时间复杂度就是O(k),k为优美排列的数量
Space O(n), visited array of size n is used. The depth of recursion tree will also go upto n.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q
  1. Merge Two Sorted Lists
    Merge two sorted linked lists and return it as a sorted list. The list should be made by splicing together the nodes of the first two lists.
    Input: l1 = [1,2,4], l2 = [1,3,4]
    Output: [1,1,2,3,4,4]
A

Approach 1: Iteration, time O(n+m), space O(1)

class Solution:
    def mergeTwoLists(self, l1, l2):
        # maintain an unchanging reference to node ahead of the return node.
        prehead = ListNode(-1)
        prev = prehead
        while l1 and l2:
            if l1.val <= l2.val:
                prev.next = l1
                l1 = l1.next
            else:
                prev.next = l2
                l2 = l2.next            
            prev = prev.next
        # exactly one of l1 and l2 can be non-null at this point, so connect
        # the non-null list to the end of the merged list.
        prev.next = l1 if l1 is not None else l2
    return prehead.next

Approach 2: Recursion, time O(n+m), space O(n+m) The first call to mergeTwoLists does not return until the ends of both l1 and l2 have been reached, so n + m stack frames.

class Solution:
    def mergeTwoLists(self, l1, l2):
        if l1 is None:
            return l2
        elif l2 is None:
            return l1
        elif l1.val < l2.val:
            l1.next = self.mergeTwoLists(l1.next, l2)
            return l1
        else:
            l2.next = self.mergeTwoLists(l1, l2.next)
            return l2
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q
  1. Remove Duplicates from Sorted List II
    Given the head of a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list. Return the linked list sorted as well.
    Input: head = [1,2,3,3,4,4,5]
    Output: [1,2,5]
    Input: head = [1,1,1,2,3]
    Output: [2,3]
A
Approach 1: Sentinel Head + Predecessor
Time O(N) Space O(1)
# class ListNode:
#     def \_\_init\_\_(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        # sentinel
        sentinel = ListNode(0, head)
        # predecessor = the last node 
        # before the sublist of duplicates
        pred = sentinel
    while head:
        # if it's a beginning of duplicates sublist 
        # skip all duplicates
        if head.next and head.val == head.next.val:
            # move till the end of duplicates sublist
            while head.next and head.val == head.next.val:
                head = head.next
            # skip all duplicates
            pred.next = head.next 
        # otherwise, move predecessor
        else:
            pred = pred.next  #!!直接向后移一位
            # move forward
            head = head.next
    return sentinel.next
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q
  1. Kth Missing Positive Number
    Given an array arr of positive integers sorted in a strictly increasing order, and an integer k.
    Find the kth positive integer that is missing from this array.

Input: arr = [2,3,4,7,11], k = 5
Output: 9
Explanation: The missing positive integers are [1,5,6,8,9,10,12,13,…]. The 5th missing positive integer is 9.

Constraints:
1 <= arr.length <= 1000
1 <= arr[i] <= 1000
1 <= k <= 1000
arr[i] < arr[j] for 1 <= i < j <= arr.length
A
Approach 1 : Linear search, time O(n)
    def findKthPositive(self, arr: List[int], k: int) -> int:
        num = 1
        i = 0
        while k:
            if (i
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q
  1. Longest Substring Without Repeating Characters
    Given a string s, find the length of the longest substring without repeating characters.

Input: s = “abcabcbb”
Output: 3
Explanation: The answer is “abc”, with the length of 3.

A
(做了很多遍依然记不住最优解...)
Sliding Window 使用i,j记录start,end;set记录已有的字字母
time O(2n) = O(n), space O(min(m,n)) window size is upper bounded by n (the size of s) and m (the size of the charset/alphabet)
def lengthOfLongestSubstring(self, s: str) -> int:
        window = set()
        ans = 0
        i, j, n = 0, 0, len(s)
        while (i
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q
  1. Check If Two String Arrays are Equivalent
    Given two string arrays word1 and word2, return true if the two arrays represent the same string, and false otherwise.
    A string is represented by an array if the array elements concatenated in order forms the string.
    Input: word1 = [“ab”, “c”], word2 = [“a”, “bc”]
    Output: true
    Explanation:
    word1 represents string “ab” + “c” -> “abc”
    word2 represents string “a” + “bc” -> “abc”
    The strings are the same, so return true.
A

1) simple solution, time O(m+n) space O(m+n)
‘‘.join(word1) == ‘‘.join(word2)
2) use a generator to “yield” individual characters, space O(1)
def arrayStringsAreEqual(self, word1: List[str], word2: List[str]) -> bool:
for c1, c2 in zip(self.gen(word1), self.gen(word2)):
if c1 != c2:
return False
return True

    def gen(self, word: List[str]):
        for s in word:
            for c in s:
                yield c
        # Ensure False when len(word1) != len(word2) 
        yield None
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q
  1. Merge Sorted Array
    Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.
    The number of elements initialized in nums1 and nums2 are m and n respectively. You may assume that nums1 has enough space (size that is equal to m + n) to hold additional elements from nums2.

Input: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
Output: [1,2,2,3,5,6]

A
Two pointers / Start from the end
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        l = len(nums1)-1
        m, n = m-1, n-1
        while m>=0 and n>=0:
            if nums1[m]>=nums2[n]:
                nums1[l] = nums1[m]
                m -= 1
                l -= 1
            else:
                nums1[l] = nums2[n]
                n -= 1
                l -= 1
        if m>=0:
            nums1[:l+1] = nums1[:m+1]
        if n>=0:
            nums1[:l+1] = nums2[:n+1]
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q
  1. Add Two Numbers
    You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order, and each of their nodes contains a single digit. Add the two numbers and return the sum as a linked list.
    You may assume the two numbers do not contain any leading zero, except the number 0 itself.
    Input: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
    Output: [8,9,9,9,0,0,0,1]
A
Time complexity : O(max(m,n)). 
Space complexity : O(max(m,n)) returned new list
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        dummy = cur = ListNode(0)
        carry = 0
        while l1 or l2 or carry:
            if l1:
                carry+=l1.val
                l1=l1.next
            if l2:
                carry+=l2.val
                l2=l2.next 
            cur.next = ListNode(carry%10)
            cur = cur.next
            carry = carry//10
        return dummy.next
How well did you know this?
1
Not at all
2
3
4
5
Perfectly