LeetCode Freedom Flashcards

Getting into Google

1
Q

@49. Group Anagrams

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”]]

1 <= strs.length <= 104
0 <= strs[i].length <= 100
strs[i] consists of lowercase English letters.

A

Sort the string and use it as key. Value are the keys that are anagrams. (‘ant’: [‘tan’, ‘ant’, ‘atn’])

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

@217. Contains Duplicate

Given an integer array nums, return true if any value appears at least twice in the array, and return false if every element is distinct.

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

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

A

Create a set. Check if number already in set.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

@347. Top K Frequent Elements

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]

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

A

Create a bucket that stores number by count.

Bucket will look like this
Count 1 2 3 4 5
Num 2 1 8 0 9

Top 2 frequent are the two right most bucket that has number in it.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

@392. Is Subsequence

Given two strings s and t, return true if s is a subsequence of t, or false otherwise.

A subsequence of a string is a new string that is formed from the original string by deleting some (can be none) of the characters without disturbing the relative positions of the remaining characters. (i.e., “ace” is a subsequence of “abcde” while “aec” is not).

Example 1:
Input: s = “abc”, t = “ahbgdc”
Output: true

Example 2:
Input: s = “axc”, t = “ahbgdc”
Output: false

0 <= s.length <= 100
0 <= t.length <= 10^4
s and t consist only of lowercase English letters.

A

Compare all the way using a pointer for s and a pointer for t. If is subsequence, the pointer for s should exceed the end of s.

func isSubsequence(s string, t string) bool {
    var i int

    for j := 0; j < len(t) && i < len(s); j++ {
        if s[i] == t[j] {
            i++
        }
    }

    return i == len(s)
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

@1. Two Sum

Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.

You may assume that each input would have exactly one solution, and you may not use the same element twice.

You can return the answer in any order.

Example 1:
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].

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

2 <= nums.length <= 10^4
-10^9 <= nums[i] <= 10^9
-10^9 <= target <= 10^9
Only one valid answer exists.

A

Create a hashmap using substraction(target - num) as key and index as value.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

@Two Sum - Input array is sorted

Given a 1-indexed array of integers numbers that is already sorted in non-decreasing order, find two numbers such that they add up to a specific target number. Let these two numbers be numbers[index1] and numbers[index2] where 1 <= index1 < index2 <= numbers.length.

Return the indices of the two numbers, index1 and index2, added by one as an integer array [index1, index2] of length 2.

The tests are generated such that there is exactly one solution. You may not use the same element twice.

Your solution must use only constant extra space.

Example 1:
Input: numbers = [2,7,11,15], target = 9
Output: [1,2]
Explanation: The sum of 2 and 7 is 9. Therefore, index1 = 1, index2 = 2. We return [1, 2].

2 <= numbers.length <= 3 * 104
-1000 <= numbers[i] <= 1000
numbers is sorted in non-decreasing order.
-1000 <= target <= 1000
The tests are generated such that there is exactly one solution.

A

Add head and tail. If result greater than target, tail is too big, move tail; else, move head.

func twoSum(nums []int, target int) []int {
// Array sorted. Compare would be easier.
    i, j := 0, len(nums) - 1

    for nums[i] + nums[j] != target {
        if nums[i] + nums[j] < target {
            i++
        } else if nums[i] + nums[j] > target {
            j--
        }
    }
    return []int{i + 1, j + 1}
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

@128. Longest Consecutive Sequence

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.

0 <= nums.length <= 10^5
-10^9 <= nums[i] <= 10^9

A

Create a set that stores all number. Check the left neighbor to know if a number is the start of a sequence. Check the right neighbor until the neighbor is not in the set. Visualizing the problem would be easier.

__1,2,3,4_____100_____200_>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

@Valid Sudoku

Determine if a 9 x 9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules:

Each row must contain the digits 1-9 without repetition.
Each column must contain the digits 1-9 without repetition.
Each of the nine 3 x 3 sub-boxes of the grid must contain the digits 1-9 without repetition.
Note:

A Sudoku board (partially filled) could be valid but is not necessarily solvable.
Only the filled cells need to be validated according to the mentioned rules.

board.length == 9
board[i].length == 9
board[i][j] is a digit 1-9 or ‘.’.

A

Create 3 hashsets (rows, columns and squares) that stores existing number. Squares index calculation is tricky.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

@238. Product of Array Except Self

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.

2 <= nums.length <= 10^5
-30 <= nums[i] <= 30
The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer.

A

Construct left and right product array using 1D dp. Calculate product array with the two array.

nums = [ a, b, c, d]
left = [ 1, a, ab, abc]
right = [bcd, cd, d, 1]
—————————–
Desire = [bcd, acd, abd, abc]

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

@121. Best Time to Buy and Sell Stock

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.

A

Think of it logically. There’s no need to keep the previous low when you encounter a lower one, so update the currLow whenever there’s a lower number. Since we don’t know where the max profit happens, we keep a maxProfit and update it at every possible turn, which is a Greedy algorithm.

[3, 6, 7, 2, 8, 1, 3, 5]
|3–6|
|3—–7|
|3————-8|(Don’t need to track, we already have a smaller number 2)
|3——————-3|(Don’t need to track, we already have a smaller number 1)
|3————————5|(Don’t need to track, we already have a smaller number 1)
|2–8|
|2——–3|(Don’t need to track, we already have a smaller number 1)
|2———–5|(Don’t need to track, we already have a smaller number 1)
|1–3|
|1—-5|

func maxProfit(prices []int) int {
    var profit int

    currLow := prices[0]

    for i := 0; i < len(prices); i++ {
        if prices[i] >= currLow {
            profit = max(prices[i] - currLow, profit)
        } else {
            currLow = prices[i]
        }
    }

    return profit
}

Greedy. Keep track of every possible minimum buy-in price and maximum profit ==> Too vague.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

@125. Valid Palindrome.

A phrase is a palindrome if, after converting all uppercase letters into lowercase letters and removing all non-alphanumeric characters, it reads the same forward and backward. Alphanumeric characters include letters and numbers.

Given a string s, return true if it is a palindrome, or false otherwise.

Example 1:
Input: s = “A man, a plan, a canal: Panama”
Output: true
Explanation: “amanaplanacanalpanama” is a palindrome.

1 <= s.length <= 2 * 10^5
s consists only of printable ASCII characters.

A

Two Pointers. Clean string. Continue when a char isn’t alphanumeric.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

@242. Valid Anagram

Given two strings s and t, return true if t is an anagram of s, and false otherwise.

An Anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.

Example 1:

Input: s = “anagram”, t = “nagaram”
Output: true

1 <= s.length, t.length <= 5 * 10^4
s and t consist of lowercase English letters.

A
  1. Count with hashmap. Substract counts when traverse second string. All value of hashmap should eventually be 0.
  2. Use byte - ‘a’ to create an indexed array indicating the frequencies. Compare the two arrays.
func isAnagram(s string, t string) bool {
    if len(s) != len(t) {
        return false
    }

    var sArr, tArr [26]int 

    for i := 0; i < len(s); i++ {
        // index in sArr is s[i] - 'a'
        sArr[s[i] - 'a']++
        // index in tArr is t[i] - 'a'
        tArr[t[i] - 'a']++
    } 

    return sArr == tArr
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

@424. Longest Repeating Character Replacement

You are given a string s and an integer k. You can choose any character of the string and change it to any other uppercase English character. You can perform this operation at most k times.

Return the length of the longest substring containing the same letter you can get after performing the above operations.

Example 1:
Input: s = “ABAB”, k = 2
Output: 4
Explanation: Replace the two ‘A’s with two ‘B’s or vice versa.

1 <= s.length <= 10^5
s consists of only uppercase English letters.
0 <= k <= s.length

A

Sliding window. (WindowSize - Most frequent Element count in window) = Characters that need to be replaced. If Characters that need to be replaced is greater than k, move left pointer of window.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

@11. Container with most water

You are given an integer array height of length n. There are n vertical lines drawn such that the two endpoints of the ith line are (i, 0) and (i, height[i]).

Find two lines that together with the x-axis form a container, such that the container contains the most water.

Return the maximum amount of water a container can store.

Notice that you may not slant the container.

Example1:
Input: height = [1,8,6,2,5,4,8,3,7]
Output: 49
Explanation: The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49.

n == height.length
2 <= n <= 105
0 <= height[i] <= 104

A

Two Pointers. Compare left height and right height. Move the lower height one step forward. Compare the previous stored maxArea with the new area.

The logic for moving the pointers:
Scenario A: Moving the one with higher height.
1. We move to a higher height => Doesn’t matter, the height of the area is still determined by the lower one, since we decreased (right - left), the area is smaller.
2. We move to an equal height => Doesn’t matter, the area is smaller due to decreased (right - left).
3. Lower height => Not considerable, we always get a lower height.

Scenario B: Moving the one with the lower height.
	1. We move to an equal height => Doesn't matter, the area is smaller due to decreased (right - left).
 		2. We move to a lower height => Not considerable, we always get a lower height.
	3. We move to a higher height => Wwe have a `chance` of getting a greater area, but we don't know more about it since (right - left) is also an issue

With all the scenarios given, moving the lower height one step forward and compare with the current max area is the solution.
func maxArea(height []int) int {
		area := func(left, right, leftHeight, rightHeight int) int {
		// The area is determined by the bottleneck from the lower between leftHeight and rightHeight
			return (right - left) * min(leftHeight, rightHeight)
		}

	i, j := 0, len(height) - 1

	// How do we update our left and right pointers?
	// Minimum height is the bottleneck, we are trying to find a better bottleneck.
	// For example, left height = 1, right height = 7
	// We now assume that right height is good, and we want to optimize the answer by finding a better left height, move left height and compare again.
	var maxArea int
	for i < j {
    maxArea = max(maxArea, area(i, j, height[i], height[j]))
    if height[i] < height[j] {
        i++
    } else {
        j--
    }
	}

		return maxArea
	}

	func max(a, b int) int {
		if a > b {
			return a
		}
		return b
	}

	func min(a, b int) int {
		if a < b {
			return a
		}
		return b
	}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

@Permutation in String

Given two strings s1 and s2, return true if s2 contains a permutation of s1, or false otherwise.

In other words, return true if one of s1’s permutations is the substring of s2.

Example 1:

Input: s1 = “ab”, s2 = “eidbaooo”
Output: true
Explanation: s2 contains one permutation of s1 (“ba”).

1 <= s1.length, s2.length <= 10^4
s1 and s2 consist of lowercase English letters.

A
  1. Use byte - ‘a’ to create an indexed array indicating the frequencies. Array is comparable in Go. Compare the two arrays.
func checkInclusion(s1 string, s2 string) bool {
    windowSize := len(s1)
    if len(s2) < windowSize {
        return false
    }

    // Create two arrays to compare.
    var s1Arr [26]int
    for i := range s1 {
        // All lowercases. rune 'a' is 97. rune 'b' is 98. 98-97 means adding one to bucket 1 in the array.
        s1Arr[s1[i] - 'a']++
    }

    var s2Arr [26]int
    var prevHeadIndex int 
    for r := range s2 {
        // Remove head from s2Arr.
        prevHeadIndex = r - windowSize
        if prevHeadIndex >= 0 {
            s2Arr[s2[prevHeadIndex] - 'a']--
        }

        // Add current new element to s2Arr. r is the new tail index.
        s2Arr[s2[r] - 'a']++
        if s1Arr == s2Arr {
            return true
        }
    }

    return false
}
  1. Create a hashmap that helps check if the window is permutation of s1.
  2. TLE. Sort string and check if the window is permutation of s1.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

@3. Longest Substring Without Repeating Characters.

Given a string s, find the length of the longest
substring
without repeating characters.

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

A

Sliding window. When confront a duplcate, remove the head until the new element is not in set.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

@76. [Hard] Minimum Window Substring

Given two strings s and t of lengths m and n respectively, return the minimum window
substring
of s such that every character in t (including duplicates) is included in the window. If there is no such substring, return the empty string “”.

The testcases will be generated such that the answer is unique.

Example 1:
Input: s = “ADOBECODEBANC”, t = “ABC”
Output: “BANC”
Explanation: The minimum window substring “BANC” includes ‘A’, ‘B’, and ‘C’ from string t.

m == s.length
n == t.length
1 <= m, n <= 10^5
s and t consist of uppercase and lowercase English letters.

A

Use hashmap for counts. Keep track of ‘needs’ and ‘haves’ instead of comparing the entire hashmap. Loop the following until the end: Expand the window until it’s valid; shrink the window until it’s not valid. Keep track of minimum length and only update the window location when minimum length occurs.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

@20. Valid Parentheses

Given a string s containing just the characters ‘(‘, ‘)’, ‘{‘, ‘}’, ‘[’ and ‘]’, determine if the input string is valid.

An input string is valid if:
- Open brackets must be closed by the same type of brackets.
- Open brackets must be closed in the correct order.
- Every close bracket has a corresponding open bracket of the same type.

Example 1:
Input: s = “()[]{}”
Output: true

Example 2:
Input: s = “(]”
Output: false

1 <= s.length <= 10^4
s consists of parentheses only ‘()[]{}’

A

Use a stack to keep track of occurences. Pop the stack correspondingly to the type of the parenthesis. Length of stack should eventually be zero.

func isValid(s string) bool {
parenMap := map[rune]rune{
	')': '(',
	']': '[',
	'}': '{',
}

stack := make([]rune, 0)
for i := range s {
	switch rune(s[i]) {
	case '(', '[', '{':
		stack = append(stack, rune(s[i]))
	case ')', ']', '}':
		if len(stack) == 0 {
			// Error
			return false
		} else {
			if stack[len(stack)-1] != parenMap[rune(s[i])] {
				// Error
				return false
			} else {
				// Pop
				stack = stack[:len(stack)-1]
			}
		}
	}
}

return len(stack) == 0
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

@136. Single Number

Given a non-empty array of integers nums, every element appears twice except for one. Find that single one.

You must implement a solution with a linear runtime complexity and use only constant extra space.

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

A

Bitwise operation. Use XOR.
Set initial as 0. Compare all the way in one loop using XOR.

0000 ^ 0010 = 0010
0010 ^ 0010 = 0000 ( Cancels out each other if there’s a duplicate)

0000 ^ 0001 = 0001
return 0001

func singleNumber(nums []int) int {
    var single int

    for i := range nums {
        single ^= nums[i]
    }

    return single
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

@155. Min Stack

Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.

Implement the MinStack class:

  • MinStack() initializes the stack object.
  • void push(int val) pushes the element val onto the stack.
  • void pop() removes the element on the top of the stack.
  • int top() gets the top element of the stack.
  • int getMin() retrieves the minimum element in the stack.

You must implement a solution within O(1) time for each function

-2^31 <= val <= 2^31 - 1
Methods pop, top and getMin operations will always be called on non-empty stacks.
At most 3 * 10^4 calls will be made to push, pop, top, and getMin.

A

Create a normal stack and a monotonic decreasing stack that keeps track of the minimum values. The minimum value is always the rightmost value of the monotonic decreasing stack.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

@191. Number of 1 Bits.

Write a function that takes the binary representation of a positive integer and returns the number of set bits it has (also known as the Hamming weight).

Example 1:
Input: n = 11
Output: 3

Explanation:
The input binary string 1011 has a total of three set bits.

A

Loop the following: Compare unit digits with 1 (0001)using &. Return value will be either 1 ( true ) or 0 ( false ). If result is 1, add one to count.

func hammingWeight(n int) int {
    var ones int
    // AND with 1.

    for n != 0 {
        if n & 1 == 1 {
            ones++
        }
        n >>= 1
    }

    return ones
}

& and&raquo_space;

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

@150. Evaluate Reverse Polish Notation

You are given an array of strings tokens that represents an arithmetic expression in a Reverse Polish Notation.

Evaluate the expression. Return an integer that represents the value of the expression.

Example 1:
Input: tokens = [“2”,”1”,”+”,”3”,”*”]

Output: 9
Explanation: ((2 + 1) * 3) = 9

  • The valid operators are ‘+’, ‘-‘, ‘*’, and ‘/’.
  • Each operand may be an integer or another expression.
  • The division between two integers always truncates toward zero.
  • There will not be any division by zero.
  • The input represents a valid arithmetic expression in a reverse polish notation.
  • The answer and all the intermediate calculations can be represented in a 32-bit integer.
  • 1 <= tokens.length <= 10^4
  • tokens[i] is either an operator: “+”, “-“, “*”, or “/”, or an integer in the range [-200, 200].
A

Create a stack that supports Pop().
Do the following recursively until the left and right value of the first operator is generated:

Pop() last token ( Head ) from stack.
If the token is an Operator, find left and right recursively.

Ex: [4, 3, *, 13, 5, /, +]
stack = [4, 3, *, 13, 5, /, +]
first op = +, stack = [4, 3, *, 13, 5, /]

left = eval([4, 3, *, 13, 5, /])
second op = /
left = 5, right = 13, return 2, stack = [4, 3, *]

right = eval([4, 3, 8])
third op = *
left = 4, right = 3, return 12, stack = []

firstOp = +, left = 2, right = 12, return 14.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

@22 Generate Parentheses

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.

Example 1:
Input: n = 3
Output: [”((()))”,”(()())”,”(())()”,”()(())”,”()()()”]

1 <= n <= 8

A

Backtracking. Keep track of the open and closing parentheses counts.
* Only add Open parentheses if openCount < n
* Only add a closing parentheses if closeCount < openCount
* Valid if openCount == closeCount == n, return

func generateParenthesis(n int) []string {
open, close := "(", ")"
openCount, closeCount := 1, 0

result := make([]string, 0)

    // Declare the function
var generate func(openCount, closeCount int, currStr string)

    // Define the function
    generate = func(openCount, closeCount int, currStr string) {
        if openCount > n {
            // End the recursive call when openCount exceeds n: Too many Open Brackets.
            return 
        }
    
        if closeCount > openCount {
            // End the recursive call when closeCount exceeds openCount: Too many Close Brackets.
            return
        }

        // Append to result (this is a shared slice) when we reach a valid string.
        if openCount == n && closeCount == n {
            result = append(result, currStr)
            return
        }

        generate(openCount+1, closeCount, fmt.Sprintf("%s%s",currStr, open)) 
        generate(openCount, closeCount+1, fmt.Sprintf("%s%s",currStr, close)) 
}

    // Start generating strings from '('.
    generate(openCount, closeCount, "(")

    return result
}

Backtracking is used when we need to check all the possible conditions and also want to cut the check early off. It is basically a depth first search with conditions.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

@739 Daily Temperature

Given an array of integers temperatures represents the daily temperatures, return an array answer such that answer[i] is the number of days you have to wait after the ith day to get a warmer temperature. If there is no future day for which this is possible, keep answer[i] == 0 instead.

Example 1:
Input: temperatures = [73,74,75,71,69,72,76,73]
Output: [1,1,4,2,1,1,0,0]

Example 2:
Input: temperatures = [30,40,50,60]
Output: [1,1,1,0]

A

Create a stack that stores the index of days that haven’t met it’s condition. Compare the head ( temperatures[s.head()] ) with todays temperature. If the teperature is greater than the head, pop the head from the stack (meaning that it reaches condition and doesn’t have to be compared again). The days would be today - the day it was stored in the stack (todayIdx - storedIdx).

func dailyTemperatures(temperatures []int) []int {
    result := make([]int, len(temperatures))

    s := make(stack, 0)
    for idx, t := range temperatures {
    
        for s.length() > 0 && t > temperatures[s.head()] {
            poppedIdx := s.pop()
            result[poppedIdx] = idx - poppedIdx
        }

        // Add the current number to stack
        s.push(idx)
    }

    return result
}

type stack []int

func (s *stack) push(num int) {
    *s = append(*s, num)
}

func (s *stack) pop() int {

    if s.length() > 0 {
        poppedIndex := (*s)[len(*s) - 1]
        *s = (*s)[:len(*s) - 1]  
        return poppedIndex
    }

    return -1
}

func (s *stack) length() int {
    return len(*s)
}

func (s *stack) head () int {
    return (*s)[len(*s) - 1]
}

Stack is crazy.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
Q

@853 Car Fleet

There are n cars going to the same destination along a one-lane road. The destination is target miles away.

You are given two integer array position and speed, both of length n, where position[i] is the position of the ith car and speed[i] is the speed of the ith car (in miles per hour).

A car can never pass another car ahead of it, but it can catch up to it and drive bumper to bumper at the same speed. The faster car will slow down to match the slower car’s speed. The distance between these two cars is ignored (i.e., they are assumed to have the same position).

A car fleet is some non-empty set of cars driving at the same position and same speed. Note that a single car is also a car fleet.

If a car catches up to a car fleet right at the destination point, it will still be considered as one car fleet.

Return the number of car fleets that will arrive at the destination.

Example 1:
Input: target = 12, position = [10,8,0,5,3], speed = [2,4,1,1,3]
Output: 3

Explanation:
The cars starting at 10 (speed 2) and 8 (speed 4) become a fleet, meeting each other at 12.
The car starting at 0 does not catch up to any other car, so it is a fleet by itself.
The cars starting at 5 (speed 1) and 3 (speed 3) become a fleet, meeting each other at 6. The fleet moves at speed 1 until it reaches target.
Note that no other cars meet these fleets before the destination, so the answer is 3.

n == position.length == speed.length
1 <= n <= 10^5
0 < target <= 10^6
0 <= position[i] < target
All the values of position are unique.
0 < speed[i] <= 10^6

A

Sort the car by position. The ones that are closer to the target are the dominating ones. If a second car reaches the target faster than the dominating one, it joins the fleet. Thus create a monotonic increasing stack that stores the time to destination for dominating cars. Only update when the time to the destination for a second car is greater than the head of the stack (the current dominating car), meaning that the car is slower and cannot catch up, this itself is a new fleet.
(position, speed, timeToTarget)
cars =
(10, 2, 1) sort (0,1,12)
(8, 4, 1) (3,3, 3)
(0, 1, 12) (5,1,7)
(5, 1, 7) (8,4,1)
(3, 3, 3) (10,2,1)

  1. 10, stack [1]
  2. 8, stack[1]
  3. 5, stack[1,7]
  4. 3, stack[1,7]
  5. 0, stack[1, 7, 12]

(0,1)–(3,3)–(5,1)—(8,4)–(10, 2)—12>
dom dom dom

func carFleet(target int, position []int, speed []int) int {
// fleets is a stack that stores the dominating fleet throughout the process.
    // It is a monotonically increasing stack.
    f := make(fleets, 0)

    c := cars{
        pos: position,
        speed: speed,
    }

    // Sort the cars by position. The ones that are closer to the target are the dominators to the previous one.
    sort.Sort(c)

    c.timeToDest = make([]float64, len(c.pos))
    for idx := range c.pos {
        c.timeToDest[idx] = float64(target - c.pos[idx]) / float64(c.speed[idx])
    }

    for i := len(c.timeToDest) - 1; i >= 0; i-- {
        // Only push the time to the stack when the stack is empty or the time to the destination is greater than the previous one (head)
        // We ignore the time to target that is faster than the dominating one => Meaning that it joins the fleet ahead.
        if len(f) == 0 || c.timeToDest[i] > f.head() {
            f.push(c.timeToDest[i])
        }
    }

    return len(f)
}

type cars struct {
    pos   []int
    speed []int 
    timeToDest []float64
}

func (c cars) Len() int           { return len(c.pos) }
func (c cars) Less(i, j int) bool { return c.pos[i] < c.pos[j] }
func (c cars) Swap(i, j int)      { 
    c.pos[i], c.pos[j] = c.pos[j], c.pos[i] 
    c.speed[i], c.speed[j] = c.speed[j], c.speed[i]
}

type fleets []float64

func (f *fleets) push(timeToDest float64) {
*f = append(*f, timeToDest)
}

func (f *fleets) head() float64 {
if len(*f) > 0 {
    return (*f)[len(*f)-1]
}

return -1.0
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
26
Q

@74 Search a 2D Matrix

You are given an m x n integer matrix matrix with the following two properties:

Each row is sorted in non-decreasing order.
The first integer of each row is greater than the last integer of the previous row.
Given an integer target, return true if target is in matrix or false otherwise.

You must write a solution in O(log(m * n)) time complexity.

Input: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
Output: true

m == matrix.length
n == matrix[i].length
1 <= m, n <= 100
-10^4 <= matrix[i][j], target <= 10^4

A

Binary search the row first. Then Binary search the number within the target row. Check edge cases first (Out of bound and greater than the head of the tail row.). If the target is greater or equal to the head of the midRow, move headRow to mid, else, move the tailRow below mid(cuz it is not encluded).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
27
Q

@704 Binary Search

Given an array of integers nums which is sorted in ascending order, and an integer target, write a function to search target in nums. If target exists, then return its index. Otherwise, return -1.

You must write an algorithm with O(log n) runtime complexity.

1 <= nums.length <= 10^4
-10^4 < nums[i], target < 10^4
All the integers in nums are unique.
nums is sorted in ascending order.

A

Binary search. Take special care for the boundary. Always use inclusive for both ends. ‘<=’ is for arrays that only has one element.

func search(nums []int, target int) int {
    // Head and tail all inclusive.
    // Everything left of head is smaller than target, everything right of tail is greater or equal to the target.
    head, tail := 0, len(nums) - 1
    var mid int

    // '<=' is for arrays that only has one element. 
    for head <= tail {
        mid = (head + tail) / 2

        switch {
        case nums[mid] == target:
            return mid
        case nums[mid] > target:
            tail = mid - 1            
        case nums[mid] < target:   
            head = mid + 1        
        }
    }
    return -1
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
28
Q

@875 Koko Eating Bananas

Koko loves to eat bananas. There are n piles of bananas, the ith pile has piles[i] bananas. The guards have gone and will come back in h hours.

Koko can decide her bananas-per-hour eating speed of k. Each hour, she chooses some pile of bananas and eats k bananas from that pile. If the pile has less than k bananas, she eats all of them instead and will not eat any more bananas during this hour.

Koko likes to eat slowly but still wants to finish eating all the bananas before the guards return.

Return the minimum integer k such that she can eat all the bananas within h hours.

Example 1:
Input: piles = [3,6,7,11], h = 8
Output: 4

Example 2:
Input: piles = [30,11,23,4,20], h = 5
Output: 30

A

Binary search. Search for all possible value util the lowest k is found. k starts from 1 and will never exceed the maximum value in piles.

func minEatingSpeed(piles []int, h int) int {
    // k starts from 1 an will never exceed the maximum value in piles.
    head, tail := 1, maxInPiles(piles) // O(n)
    var mid, n int
    for head < tail { // O(n^2)
        mid = (head + tail) / 2
        n = need(piles, mid) // O(n)

        switch {
        case n > h:
            head = mid + 1
        case n <= h:
            // Always looking for a smaller k, we might have a smaller one on the left.
            tail = mid 
        }
    }

	return tail
}

func maxInPiles(piles []int) int {
    maximum := piles[0]

    for i := range piles {
        maximum = max(maximum, piles[i])
    }

    return maximum
}

func need(piles []int, possibleK int) int {
    var n int

    for i := range piles {
        n += int(math.Ceil(float64(piles[i])/ float64(possibleK)))
    }

    return n
}

Take care of the bounds. It’s tricky.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
29
Q

@153 Find Minimum in Rotated Sorted Array

Suppose an array of length n sorted in ascending order is rotated between 1 and n times. For example, the array nums = [0,1,2,4,5,6,7] might become:

[4,5,6,7,0,1,2] if it was rotated 4 times.
[0,1,2,4,5,6,7] if it was rotated 7 times.
Notice that rotating an array [a[0], a[1], a[2], …, a[n-1]] 1 time results in the array [a[n-1], a[0], a[1], a[2], …, a[n-2]].

Given the sorted rotated array nums of unique elements, return the minimum element of this array.

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

Example 1:
Input: nums = [3,4,5,1,2]

Output: 1
Explanation: The original array was [1,2,3,4,5] rotated 3 times.

n == nums.length
1 <= n <= 5000
-5000 <= nums[i] <= 5000
All the integers of nums are unique.
nums is sorted and rotated between 1 and n times

A

Binary Search.

  • If mid is greater than tail, minimum is at the right side of the array. Move head to mid + 1 (since the mid is already greater we don’t need to consider it anymore).
  • If mid is smaller than tail, from mid to tail is an increasing array, where mid is the smallest one for the right side.

The minimum might be in the left side, mid inclusive. Thus move tail to mid.

Value of the head will be the lowest at the end.

func findMin(nums []int) int {
    h, t := 0, len(nums) - 1
    var mid int
    for h < t {
        mid = (h + t) / 2
        if nums[mid] > nums[t] {
            h = mid + 1 
        } else {
            t = mid
        }
    }
    return nums[h]
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
30
Q

@981 Time Based Key Value Store

Design a time-based key-value data structure that can store multiple values for the same key at different time stamps and retrieve the key’s value at a certain timestamp.

Implement the TimeMap class:

TimeMap() Initializes the object of the data structure.
void set(String key, String value, int timestamp) Stores the key key with the value value at the given time timestamp.
String get(String key, int timestamp) Returns a value such that set was called previously, with timestamp_prev <= timestamp. If there are multiple such values, it returns the value associated with the largest timestamp_prev. If there are no values, it returns “”.

Example 1:
Input:
[“TimeMap”, “set”, “get”, “get”, “set”,”get”, “get”, “get”]
[[], [“foo”, “bar”, 2], [“foo”, 2], [“foo”, 3], [“foo”, “bar2”, 4], [“foo”, 1],[“foo”, 4], [“foo”, 5]]

Output:
[null, null, “bar”, “bar”, null, null, “bar2”, “bar2”]

A

Create a map that stores an array as value. Binary search the array base on the timestamp. If timestamp is smaller than the mid value, tail = mid - 1 (since the mid is now not included). If timestamp is greater than the mid value, head = mid (since head might be the result.) Return the tail (last value that is available, which is the max).

Note that if a value exist but the desired timestamp is smaller than the earliest timestamp, return null.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
31
Q

@206 Reverse Linked List

Given the head of a singly linked list, reverse the list, and return the reversed list.

ex:
Input: head = [1,2,3,4,5]
Output: [5,4,3,2,1]

The number of nodes in the list is the range [0, 5000].
-5000 <= Node.val <= 5000

A

Store the next node first. Update the direction. After updating the direction, jump to the stored next node. When temp reached nil (the last stored next node), break out of the loop. The last updated previous node is the head of the reversed linked list.

[A, B, C, D]

prev temp next
nil <-change– A –jump-> B
A <-change– B –jump-> C
B <-change– C –jump-> D
C <-change– D –jump-> nil
D <-change– nil (break)

func reverseList(head *ListNode) *ListNode {
    if head == nil {
        return nil
    }

    var prev, next *ListNode

    temp := head
    for temp != nil {
        // After using the stored next node, store the old next node for later jumps.
        next = temp.Next
        // Assign new next to the previos node.
        temp.Next = prev
        // After using previous node, update previous to current.
        prev = temp
        // Jump to the stored next.
        temp = next
    }
    return prev
}

Rememeber to deal with empty inputs (nil head).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
32
Q

@21 Merge Two Sorted Lists

You are given the heads of two sorted linked lists list1 and list2.

Merge the two lists into one sorted list. The list should be made by splicing together the nodes of the first two lists.

Return the head of the merged linked list.

A

Create a placeholder for a new list. Compare through two lists by looping.

Exhaust the list that isn’t empty by directly assigning.

func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
    merged := new(ListNode)
    temp := merged 
    
    for list1 != nil && list2 != nil {
        if list1.Val <= list2.Val {
            temp.Next = list1
            list1 = list1.Next
        } else {
            temp.Next = list2
            list2 = list2.Next
        }
        temp = temp.Next
    }
    if list1 != nil {
        temp.Next = list1  
    } 
    if list2 != nil {
        temp.Next = list2
    }
    return merged.Next
}

Take special care on initializing the result node.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
33
Q

@2 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.

Example 1:
Input: l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
Output: [8,9,9,9,0,0,0,1]

The number of nodes in each linked list is in the range [1, 100].
0 <= Node.val <= 9
It is guaranteed that the list represents a number that does not have leading zeros.

A

Create a new node that traverses when the nodes are adding.
In 10 based system there will be addOns, which will always be 1.
The value of the node will be either
* When l1 != nil && l2 != nil, value = l1.Val + l2.Val + addOn
* When l1 == nil && l2 != nil, value = l2.Val + addOn
* When l1 != nil && l2 == nil, value = l1.Val + addOn
* When both is empty, it’s out of the loop.

After it is out of the loop, if the addOn is not zero, create a new node with value 1 (When the value of the last node is greater than 10, 要進位)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
34
Q

@138 Copy List With Random Pointer

A linked list of length n is given such that each node contains an additional random pointer, which could point to any node in the list, or null.

Construct a deep copy of the list. The deep copy should consist of exactly n brand new nodes, where each new node has its value set to the value of its corresponding original node. Both the next and random pointer of the new nodes should point to new nodes in the copied list such that the pointers in the original list and copied list represent the same list state. None of the pointers in the new list should point to nodes in the original list.

For example, if there are two nodes X and Y in the original list, where X.random –> Y, then for the corresponding two nodes x and y in the copied list, x.random –> y.

Return the head of the copied linked list.

The linked list is represented in the input/output as a list of n nodes. Each node is represented as a pair of [val, random_index] where:

val: an integer representing Node.val
random_index: the index of the node (range from 0 to n-1) that the random pointer points to, or null if it does not point to any node.
Your code will only be given the head of the original linked list.

Ex1:
Input: head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
Output: [[7,null],[13,0],[11,4],[10,2],[1,0]]

0 <= n <= 1000
-104 <= Node.val <= 10^4
Node.random is null or is pointing to some node in the linked list.

A

Since we cannot point to the orginal one, we have to have the address of the new nodes to point to. Create a hashmap that stores the relationship between the old and new (a <-> a’). Use the relations to get temp.Random’ from temp.Random.

13 (temp) -> 13’ (newNode)
|
v
7 (temp.Random)
and since we know who 7 points to (7’), we can know who 13’ should point to, which is 7’, fetched by 7.

func copyRandomList(head *Node) *Node {
    relations := make(map[*Node]*Node)

    dummy := new(Node)
    nNode := dummy

    temp := head
    for temp != nil {
        // Create newNode
        newNode := &Node{Val: temp.Val}
        relations[temp] = newNode
        
        // Assign to the next node
        nNode.Next = newNode
        
        // Jump to next node.
        nNode = nNode.Next
        temp = temp.Next 
    }

    temp = head
    nNode = dummy.Next

    for temp != nil {
        nNode.Random = relations[temp.Random]
        temp = temp.Next
        nNode = nNode.Next
    }

    return dummy.Next
}

The relations between new and old!

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
35
Q

@19 Remove Nth Node From End of List

Given the head of a linked list, remove the nth node from the end of the list and return its head.

Example1:
Input: head = [1,2,3,4,5], n = 2
Output: [1,2,3,5]

Example2:
Input: head = [1,2,3,4,5], n = 5
Output: [2,3,4,5]

The number of nodes in the list is sz.
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz

A

Count the length of the list first.
If n == length, remove the head (return head.Next); else traverse till the previous one, change the next of the previous one to the next of the next node (temp.Next = temp.Next.Next).

func removeNthFromEnd(head *ListNode, n int) *ListNode {
    listLength := length(head)
    if n == listLength {
        return head.Next
    }

    prevIdx := listLength - n - 1

    var idx int
    temp := head
    for temp != nil {
        if idx == prevIdx {
            temp.Next = temp.Next.Next
        }
        temp = temp.Next
        idx++
    }
    return head
}

func length(head *ListNode) int {
    var count int
    temp := head
    for temp != nil {
        count++
        temp = temp.Next
    }
    return count
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
36
Q

@141 Linked List Cycle

Given head, the head of a linked list, determine if the linked list has a cycle in it.

There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the next pointer. Internally, pos is used to denote the index of the node that tail’s next pointer is connected to. Note that pos is not passed as a parameter.

Return true if there is a cycle in the linked list. Otherwise, return false.

Example1:
Input: head = [3,2,0,-4], pos = 1
Output: true
Explanation: There is a cycle in the linked list, where the tail connects to the 1st node (0-indexed).

The number of the nodes in the list is in the range [0, 104].
-10^5 <= Node.val <= 10^5
pos is -1 or a valid index in the linked-list.

A
  • Use a set to check if a node already exist => Space: O(n)
func hasCycle(head *ListNode) bool {
    nodeSet := make(map[*ListNode]struct{})
    temp := head
    var exist bool
    for temp != nil {
        if _, exist = nodeSet[temp]; exist {
            return true
        } else {
            nodeSet[temp] = struct{}{}
        }

        temp = temp.Next
    }
    return false
}
  • Use fast and slow pointer, if they point to the same node (since if there’s a cycle the fast pointer will catch up with the slow one from the back), has cycle.
func hasCycle(head *ListNode) bool {
    fast, slow := head, head
    for fast != nil && fast.Next != nil && slow != nil {
        fast = fast.Next.Next
        slow = slow.Next
        if fast == slow {
            return true
        }
    } 
    return false
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
37
Q

@287 Find the Duplicate Number

Given an array of integers nums containing n + 1 integers where each integer is in the range [1, n] inclusive.

There is only one repeated number in nums, return this repeated number.

You must solve the problem without modifying the array nums and uses only constant extra space.

Example 1:

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

1 <= n <= 10^5
nums.length == n + 1
1 <= nums[i] <= n
All the integers in nums appear only once except for precisely one integer which appears two or more times.

A
  • (Best Solution) Floyd’s Cycle Detection
func findDuplicate(nums []int) int {
    var slow, fast int

    // Find the intersection point of the two pointers
    for {
        slow = nums[slow]
        fast = nums[nums[fast]]

        if slow == fast {
            break
        }
    }

    // Find the entrance to the cycle
    slow = 0
    for slow != fast {
        slow = nums[slow]
        fast = nums[fast]
    }

    return slow
}
  • Hashset: Return the number if it is already in set => Time: O(n), Space: O(n)
func findDuplicate(nums []int) int {
    set := make(map[int]struct{})
    for i := range nums {
        if _, ok := set[nums[i]]; ok {
            return nums[i]
        } else {
            set[nums[i]] = struct{}{}
        }
    }
    return 0
}
  • Sort and compare the adjacent elements => Time: O(nlogn), Space: O(1)
func findDuplicate(nums []int) int {
    sort.Ints(nums)
    for i := 1; i < len(nums); i ++ {
        if nums[i] == nums[i - 1] {
            return nums[i]
        }
    } 
    return 0
}

Floyd’s Cycle Detection is the best

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
38
Q

@146 LRU Cache

Design a data structure that follows the constraints of a Least Recently Used (LRU) cache.

Implement the LRUCache class:

LRUCache(int capacity) Initialize the LRU cache with positive size capacity.
int get(int key) Return the value of the key if the key exists, otherwise return -1.
void put(int key, int value) Update the value of the key if the key exists. Otherwise, add the key-value pair to the cache. If the number of keys exceeds the capacity from this operation, evict the least recently used key.
The functions get and put must each run in O(1) average time complexity.

Example 1:

Input
[“LRUCache”, “put”, “put”, “get”, “put”, “get”, “put”, “get”, “get”, “get”]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
Output
[null, null, null, 1, null, -1, null, -1, 3, 4]

A

Create a data structure that can store the timestamp of the keys.

  • A queue that removes the head when full.
  • A doubly linked list.

Get(): If key is in cache, update timestamp (For doubly linked List, move key to head). Else, return -1.

Put(): If key is in cache, update timestamp. If key not in cache and cache is full, remove the least used element (for a queue it is the head, for the doubly linked list it is the back), delete the last element from cache. Create a new timestamp for element.

type LRUCache struct {
	cache    map[int]*list.Element
	linklist *list.List
	capacity int
}

type Obj struct {
	Key   int
	Value int
}

func Constructor(capacity int) LRUCache {
	return LRUCache{
		cache:    make(map[int]*list.Element, capacity),
		linklist: list.New(),
		capacity: capacity,
	}
}

func (this *LRUCache) Get(key int) int {
	if elem, ok := this.cache[key]; ok {
        // Put the element to head.
		this.linklist.MoveToFront(elem)
		return elem.Value.(Obj).Value
	}
	return -1
}

func (this *LRUCache) Put(key int, value int) {
	if elem, ok := this.cache[key]; ok {
    	// If the key is in list, remove the old timestamp.
		this.linklist.Remove(elem)
	} else if len(this.cache) == this.capacity { 
        // Reached Capacity
        // Last element of the linked list is the least used.
		leastUsedEle := this.linklist.Back()
        // Remove the last element from the list.
		this.linklist.Remove(leastUsedEle)
        // Remove the last element from the map.
		delete(this.cache, leastUsedEle.Value.(Obj).Key)
	}

    // Create a new obj
	newObj := Obj{
		Key:   key,
		Value: value,
	}
	newEle := this.linklist.PushFront(newObj) // New Obj is the recently used, put to head.
	this.cache[key] = newEle
	return
}

We have list in Go Standard Library. It updates the node by directly updating the Next, and Prev pointer.

MoveToFront: O(1)
Remove:O(1)
PushFront: O(1)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
39
Q

@226 Invert Binary Tree

Given the root of a binary tree, invert the tree, and return its root.

Example 1:
Input: root = [4,2,7,1,3,6,9]
Output: [4,7,2,9,6,3,1]

  • The number of nodes in the tree is in the range [0, 100].
  • -100 <= Node.val <= 100
A

Rotate recursively. Observe the base case, where the recursive function should end.

Base case: When node is nil.

Rotate left and right.

func invertTree(root *TreeNode) *TreeNode {
    // If node is nil, return nil. Else rotate left and right.
    if root != nil {
        root.Left, root.Right = invertTree(root.Right), invertTree(root.Left)
        return root
    }    

    return nil
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
40
Q

@104 Maximum Depth of Binary Tree

Given the root of a binary tree, return its maximum depth.

A binary tree’s maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.

Example 1:
Input: root = [3,9,20,null,null,15,7]
Output: 3

The number of nodes in the tree is in the range [0, 104].
-100 <= Node.val <= 100

A

Add height recursively. Add 1 at every layer when node is not nil. Compare the maxDepth(node.Left) and maxDepth(node.Right) before adding it to the current height.

Base Case: When node is nil, then maxDepth(nil) = 0

func maxDepth(root *TreeNode) int {
    // DFS.
    if root == nil {
        return 0
    }

    return 1 + max(maxDepth(root.Left), maxDepth(root.Right))
}

Always think of the base case first.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
41
Q

@543 Diameter of Binary Tree

Given the root of a binary tree, return the length of the diameter of the tree.

The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root.

The length of a path between two nodes is represented by the number of edges between them.

The number of nodes in the tree is in the range [1, 10^4].
-100 <= Node.val <= 100

A

Compare the diameter and the local diameter recursively.

Diameter = CurrMaxLeftHeight, CurrMaxRightHeight

Return max(currMaxLeftHeight, currMaxRightHeight) to the parent. The parent will use it as either it’s currMaxLeftHeight or currMaxRightHeight.

func diameterOfBinaryTree(root *TreeNode) int {
    var diameter int
    // dfs finds the maxDepth of each node and compares the local diameter with the stored diameter.
    // Local diameter is the leftHeight + rightHeight.
    // Only add 1 to the height when a leaf exist.
    var dfs func(node *TreeNode) int
    dfs = func(node *TreeNode) int {
        var leftHeight, rightHeight int
        if node.Left != nil {
            leftHeight = dfs(node.Left) + 1
        } 
        if node.Right != nil {
            rightHeight = dfs(node.Right) + 1
        } 
   
        diameter = max(diameter, leftHeight + rightHeight)
        return max(leftHeight, rightHeight) 
    }
    dfs(root)
    return diameter
}

Diameter = leftHeight + rightHeight

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
42
Q

@110 Balanced Binary Tree

Given a binary tree, determine if it is
height-balanced.

Ex1:
Input: root = [3,9,20,null,null,15,7]
Output: true

A height-balanced binary tree is a binary tree in which the depth of the two subtrees of every node never differs by more than one.

The number of nodes in the tree is in the range [0, 5000].
-10^4 <= Node.val <= 10^4

A

Do the following recursively until the base case: Check the height difference every layer. If height difference is smaller than 2, the node is balanced. Return the height of the subroot to the next layer, and compare again.

func isBalanced(root *TreeNode) bool {
    // Return height, isBalanced
    var dfs func(node *TreeNode) (int, bool) 
    dfs = func(node *TreeNode) (int, bool) {
        if node == nil {
            return 0, true
        }

        leftHeight, leftIsBalanced := dfs(node.Left)
        rightHeight, rightIsBalanced := dfs(node.Right)

        if leftHeight - rightHeight >= 2 || rightHeight - leftHeight >= 2 {
            return -1, false
        } 
        
        return max(leftHeight, rightHeight) + 1, leftIsBalanced && rightIsBalanced
    }
    _, rootBalanced := dfs(root)
    return rootBalanced    
}

Depth First Search

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
43
Q

@100 Same Tree

Given the roots of two binary trees p and q, write a function to check if they are the same or not.

Two binary trees are considered the same if they are structurally identical, and the nodes have the same value.

Ex1:
Input: p = [1,2,3], q = [1,2,3]
Output: true

Ex2:
Input: p = [1,2], q = [1,null,2]
Output: false

The number of nodes in both trees is in the range [0, 100].
-10^4 <= Node.val <= 10^4

A

Do the following recursively until the base case: Check if the node value is the same. If the node value is the same, compare the children.

func isSameTree(p *TreeNode, q *TreeNode) bool {
    if p == nil && q == nil {
        return true
    }

    // In case one of the nodes is nil.
    if p == nil && q != nil {
        return false
    }

    if p != nil && q == nil {
        return false
    }

    return p.Val == q.Val && isSameTree(p.Left, q.Left) && isSameTree(p.Right, q.Right)
}

Depth First Search

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
44
Q

@572 Subtree of Another Tree

Given the roots of two binary trees root and subRoot, return true if there is a subtree of root with the same structure and node values of subRoot and false otherwise.

A subtree of a binary tree tree is a tree that consists of a node in tree and all of this node’s descendants. The tree tree could also be considered as a subtree of itself.

Ex1:
root = [3,4,5,1,2], subRoot = [4,1,2]
Output: true

Ex2:
Input: root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
Output: false

Can have nodes with the same value in a tree.

The number of nodes in the root tree is in the range [1, 2000].
The number of nodes in the subRoot tree is in the range [1, 1000].
-10^4 <= root.val <= 10^4
-10^4 <= subRoot.val <= 10^4

A

Do the following recursively until the base case: Check if a root and a subRoot is a the same tree. If the root is not the same tree as the subRoot, check if any of the children is the same tree as the subRoot.

func isSubtree(root *TreeNode, subRoot *TreeNode) bool {
    if root == nil && subRoot == nil {
        return true
    }
    
    if root == nil && subRoot != nil {
        return false
    }

    if root != nil && subRoot == nil {
        return false
    }

    return isSameTree(root, subRoot) || isSubtree(root.Left, subRoot) || isSubtree(root.Right, subRoot) 
}

func isSameTree(p, q *TreeNode) bool {
    if p == nil && q == nil {
        return true
    }
    
    if p == nil && q != nil {
        return false
    }

    if p != nil && q == nil {
        return false
    }

    return p.Val == q.Val && isSameTree(p.Left, q.Left) && isSameTree(p.Right, q.Right)
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
45
Q

@235 Lowest Common Ancestor of a Binary Search Tree

Given a binary search tree (BST), find the lowest common ancestor (LCA) node of two given nodes in the BST.

According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”

Ex1:
Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
Output: 6
Explanation: The LCA of nodes 2 and 8 is 6.

Ex2:
Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
Output: 2
Explanation: The LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.

Ex3:
Input: root = [2,1], p = 2, q = 1
Output: 2

  • The number of nodes in the tree is in the range [2, 10^5].
  • -10^9 <= Node.val <= 10^9
  • All Node.val are unique.
  • p != q
  • p and q will exist in the BST.
A

Utilize the traits of a binary tree. If p and q are both smaller than the root, the lowest common ancestor is on the left side. If p and q are both greater than the root, the lowest common ancestor is on the right side. Otherwise, it is the root.

func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
	switch {
	case (p.Val < root.Val && q.Val > root.Val), (p.Val > root.Val && q.Val < root.Val):
		return root
	case p.Val == root.Val:
		return p
	case q.Val == root.Val:
		return q
	case p.Val < root.Val && q.Val < root.Val:
		return lowestCommonAncestor(root.Left, p, q)
	case p.Val > root.Val && q.Val > root.Val:
		return lowestCommonAncestor(root.Right, p, q)
	default:
        return nil
    }
}

The Lowest Common Ancestor happens when p and q are on separate sides, or either p or q equals to the root.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
46
Q

@102. Binary Tree Level Order Traversal

Given the root of a binary tree, return the level order traversal of its nodes’ values. (i.e., from left to right, level by level).

Ex1:
Input: root = [3,9,20,4,615,7]
Output: [[3],[9,20],[4,6,15,7]]

  • The number of nodes in the tree is in the range [0, 2000].
  • -1000 <= Node.val <= 1000
A

Breadth First Search. Use a queue to go through every possible node. Use the queue size to know the number of nodes in the current level.

First Level: [3], queueLength = 1, levelSize = 1
Do once:
1. Dequeue once and enqueue the children. => [9, 20]

Second Level: [9, 20], queueLength = 2, levelSize =2
Do twice:
1.Dequeue once and enqueue the children. =>[20, 4, 6]
2.Dequeue once and enqueue the children. => [4, 6, 15,7]

Third Level:
Do four times:
1. Dequeue once and enqueue the children. =>[6, 15, 7]
2. Dequeue once and enqueue the children. =>[15, 7]
3. Dequeue once and enqueue the children. =>[7]
4. Dequeue once and enqueue the children. =>[]

func levelOrder(root *TreeNode) [][]int {
	result := make([][]int, 0)
	if root == nil {
		return result
	}

	// Use a queue for bfs
	q := make(queue, 0)
	q.Enqueue(root)

	var first *TreeNode
	for len(q) != 0 {
		// Determine the number of nodes in the current level (levelSize) by using len(q).
		levelSize := len(q)
		currLevel := make([]int, 0, levelSize)

		// Iterate over exactly those nodes in the current level without processing nodes from subsequent levels.
        // Once we have processed all nodes at the current level, we know that we've finished that level and can move on to the next level
		for i := 0; i < levelSize; i++ {
			first = q.Dequeue()
			currLevel = append(currLevel, first.Val)
			if first.Left != nil {
				q.Enqueue(first.Left)
			}

			if first.Right != nil {
				q.Enqueue(first.Right)
			}
		}
		result = append(result, currLevel)
	}

	return result
}

type queue []*TreeNode

func (q *queue) Enqueue(element *TreeNode) {
	*q = append(*q, element)
}

func (q *queue) Dequeue() *TreeNode {
	if len(*q) != 0 {
		first := (*q)[0]
		(*q) = (*q)[1:]
		return first
	}

	return nil
}

Track level size to know when to stop in the queue.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
47
Q

@199. Binary Tree Right Side View

Given the root of a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom.

Ex1:
Input: root = [1,2,3,null,5,null,4]
Output: [1,3,4]

Ex2:
Input: root = [1,null,3]
Output: [1,3]

  • The number of nodes in the tree is in the range [0, 100].
  • -100 <= Node.val <= 100
A

Breadth First Search. Get nodes in every level. The right most element of every level is the right side view.

func rightSideView(root *TreeNode) []int {
    sideView := make([]int, 0)
    if root == nil {
        return sideView
    }

    levels := make([][]int, 0)
    q := []*TreeNode{root}

    var levelSize int
    var first *TreeNode
    var currLevel []int
    for len(q) != 0 {
        levelSize = len(q)
        currLevel = make([]int, 0, levelSize)  

        for i := 0; i < levelSize; i++ {
            first = q[0]
            currLevel = append(currLevel, first.Val)
            
            q = q[1:]
            if first.Left != nil {
                q = append(q, first.Left)
            }

            if first.Right != nil {
                q = append(q, first.Right)
            }
        } 
        levels = append(levels, currLevel)
    }

    for _, level := range levels {
        sideView = append(sideView, level[len(level) - 1])
    } 
    return sideView
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
48
Q

@1448 Count Good Nodes in Binary Tree

Given a binary tree root, a node X in the tree is named good if in the path from root to X there are no nodes with a value greater than X.

Return the number of good nodes in the binary tree.

Ex1:
Input: root = [3,1,4,3,null,1,5]
Output: 4
Explanation: Nodes in blue are good.
Root Node (3) is always a good node.
Node 4 -> (3,4) is the maximum value in the path starting from the root.
Node 5 -> (3,4,5) is the maximum value in the path
Node 3 -> (3,1,3) is the maximum value in the path.

A

Use DFS (Depth First Search) to traverse the tree, and constantly keep track of the current path maximum at every recursion level.

func goodNodes(root *TreeNode) int {
    count := 0
    var dfs func(node *TreeNode, localMax int)
    dfs = func(node *TreeNode, currMax int){
        if node == nil {
            return 
        }
        if node.Val >= currMax {
            currMax = node.Val
            count++
        }
        dfs(node.Left, currMax)
        dfs(node.Right, currMax)
    }

    dfs(root, root.Val)
    return count
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
49
Q

@230. Kth Smallest Element in a BST

Given the root of a binary search tree, and an integer k, return the kth smallest value (1-indexed) of all the values of the nodes in the tree.

The number of nodes in the tree is n.
1 <= k <= n <= 10^4
0 <= Node.val <= 10^4

A

Keep count when using InOrder Traversal. When count reaches k, return the value of the node.

  • Use an array to store k elements before k and return the last element
func kthSmallest(root *TreeNode, k int) int {
	resultArr := make([]int, 0, k)
	count := 0
	var inOrder func(node *TreeNode)
	inOrder = func(node *TreeNode) {
		if node == nil {
			return
		}
		if count < k {
			inOrder(node.Left)
		}
		if count < k {
			resultArr = append(resultArr, node.Val)
			count++
		}   
		if count < k {
			inOrder(node.Right)
		}
	}
	inOrder(root)

	return resultArr[len(resultArr)-1]
}
  • Keep count and a parameter result (saved the array)
func kthSmallest(root *TreeNode, k int) int {
	var result int
    count := 0

	var inOrder func(node *TreeNode)
	inOrder = func(node *TreeNode) {
		if node == nil || count >= k {
			return
		}

		inOrder(node.Left)

		count++
        if count == k {
            result = node.Val
            return
        }
		inOrder(node.Right)
	}
	inOrder(root)

	return result
}
  • Use channels to keep count, read only k - 1 elements from channel.
func kthSmallest(root *TreeNode, k int) int {
    // Inorder and read from channel
    c := make(chan int)
    go inOrderWalk(root, c)

    for i := 0; i < k - 1; i++ {
        <-c
    }
    return <-c
}

func inOrderWalk(node *TreeNode, c chan int){
    if node == nil {
        return 
    }

    inOrderWalk(node.Left, c)
    c <- node.Val
    inOrderWalk(node.Right, c)
}

InOrder Traversal: Left -> Root -> Right

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
50
Q

@98. Validate Binary Search Tree

Given the root of a binary tree, determine if it is a valid binary search tree (BST).

A valid BST is defined as follows:

The left
subtree
of a node contains only nodes with keys less than the node’s key.
The right subtree of a node contains only nodes with keys greater than the node’s key.
Both the left and right subtrees must also be binary search trees.

The number of nodes in the tree is in the range [1, 10^4].
-2^31 <= Node.val <= 2^31 - 1

A

Use the traits of a binary search tree. Carry the lower and upper bound for each node when validating.

func isValidBST(root *TreeNode) bool {
	if root == nil {
		return true
	}
	var validate func(node *TreeNode, lower int, upper int) bool
	validate = func(node *TreeNode, lower int, upper int) bool {
		if node == nil {
			return true
		}
        if node.Val > lower && node.Val < upper {
            // Update upper for left and update lower for right
            return validate(node.Left, lower, node.Val) && validate(node.Right, node.Val, upper)
        }
        return false
	}
	maxInt := int(^uint(0) >> 1)
	minInt := -maxInt - 1
	return validate(root, minInt, maxInt)
}

For a Binary Search Tree, a left child’s value would be at -INF < node.Left < node.Val, a right child’s value would be at node.Val < node.Right < INF

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
51
Q

@124. Binary Tree Maximum Path Sum

A path in a binary tree is a sequence of nodes where each pair of adjacent nodes in the sequence has an edge connecting them. A node can only appear in the sequence at most once. Note that the path does not need to pass through the root.

The path sum of a path is the sum of the node’s values in the path.

Given the root of a binary tree, return the maximum path sum of any non-empty path.

Ex1:

Input: root = [-10,9,20,null,null,15,7]
Output: 42
Explanation: The optimal path is 15 -> 20 -> 7 with a path sum of 15 + 20 + 7 = 42.

The number of nodes in the tree is in the range [1, 3 * 10^4].
-1000 <= Node.val <= 1000

A

Depth First Search and Dynamic Programming.

PathSum = node.Val + maxLeftPath +maxRightPath.

maxLeftPath is the maximum sum for the left path.
maxRightPath is the maximum sum for the right path.

Compare all the way down using DFS since maxPathSum might not happen at root (could happen anywhere).

Use a DP map that stores the maximum left or right sum to avoid repeated calculation on sum.

func maxPathSum(root *TreeNode) int {
	result := -int(^uint(0)>>1) - 1
    dp := make(map[*TreeNode]int)

    var pathMax func(node *TreeNode) int
    pathMax = func(node *TreeNode) int {
        if node == nil {
		    return 0
	    }
        var result int
        if val, ok := dp[node]; !ok {
            result = node.Val
	        leftPathMax := pathMax(node.Left)
	        rightPathMax := pathMax(node.Right)

	        if max(leftPathMax, rightPathMax) >= 0 {
		        result += max(leftPathMax, rightPathMax)
	        }
            dp[node] = result
        } else {
            result = val
        }

	    return result
    }

	var dfs func(node *TreeNode)
	dfs = func(node *TreeNode) {
		if node == nil {
			return
		}
		
		leftPathMax := max(0, pathMax(node.Left))
		rightPathMax := max(0, pathMax(node.Right))
		result = max(result, node.Val + leftPathMax + rightPathMax)

		dfs(node.Left)
		dfs(node.Right)
	}

	dfs(root)

	return result
}

Break the problem down and find the base problem.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
52
Q

@105. Contruct Binary Tree from Preorder and Inorder Traversal

Given two integer arrays preorder and inorder where preorder is the preorder traversal of a binary tree and inorder is the inorder traversal of the same tree, construct and return the binary tree.

  • 1 <= preorder.length <= 3000
  • inorder.length == preorder.length
  • -3000 <= preorder[i], inorder[i] <= 3000
  • preorder and inorder consist of unique values.
  • Each value of inorder also appears in preorder.
  • preorder is guaranteed to be the preorder traversal of the tree.
  • inorder is guaranteed to be the inorder traversal of the tree.
A

Find the root location and divide the preorder and inorder array to three parts:

  • The root
    preorder[0].
  • The sub-array of left sub-tree
    buildTree(preorder[1:rootLocation+1], inorder[:rootLocation]).
  • The sub-array of right sub-tree
    buildTree(preorder[rootLocation+1:], inorder[rootLocation + 1:]).
func buildTree(preorder []int, inorder []int) *TreeNode {
	// Base case.
	if len(preorder) == 0 {
        return nil
    }
    
	// The first value of preorder is always the root of the result.
	// Find where the root is at in the inorder array. The left part is the left child, right part is the right child.
    var rootLocation int    
    for inorder[rootLocation] != preorder[0] {
        rootLocation++
    }

	return &TreeNode{
		Val:   preorder[0],
		Left:  buildTree(preorder[1:rootLocation+1], inorder[:rootLocation]),
		Right: buildTree(preorder[rootLocation+1:], inorder[rootLocation + 1:]),
	}
} 

Inorder is left -> root -> right. Preorder is root -> left -> right

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
53
Q

@703. Kth Largest Element In a Stream

Design a class to find the kth largest element in a stream. Note that it is the kth largest element in the sorted order, not the kth distinct element.

Implement KthLargest class:

KthLargest(int k, int[] nums) Initializes the object with the integer k and the stream of integers nums.
int add(int val) Appends the integer val to the stream and returns the element representing the kth largest element in the stream.

Example 1:

Input
[“KthLargest”, “add”, “add”, “add”, “add”, “add”]
[[3, [4, 5, 8, 2]], [3], [5], [10], [9], [4]]
Output
[null, 4, 5, 5, 8, 8]

Explanation
KthLargest kthLargest = new KthLargest(3, [4, 5, 8, 2]);
kthLargest.add(3); // return 4
kthLargest.add(5); // return 5
kthLargest.add(10); // return 5
kthLargest.add(9); // return 8
kthLargest.add(4); // return 8

A

Create a minHeap. Compare the head with the new value. If the new value is greater than the head of the min heap, remove the head (which is the smallest value in the heap). Insert the new value to the heap.

type KthLargest struct {
	MinHeap  []int
	HeapSize int
	K        int
}

func Constructor(k int, nums []int) KthLargest {
	sort.Ints(nums)

	var minHeap []int
	var heapSize int

	if len(nums) == 0 {
		minHeap = make([]int, 0)
		heapSize = 0
	} else if len(nums) < k {
		minHeap = nums
		heapSize = len(nums)
	} else {
		minHeap = nums[len(nums)-k:]
		heapSize = k
	}

	return KthLargest{
		MinHeap:  minHeap,
		HeapSize: heapSize,
		K:        k,
	}
}

func ParentIdx(childIdx int) int {
	return (childIdx - 1) / 2
}

func LeftChildIdx(parentIdx int) int {
	return parentIdx<<1 + 1
}

func RightChildIdx(parentIdx int) int {
	return (parentIdx + 1) << 1
}

func (this *KthLargest) MinHeapify(idx int) {
	lowestIdx := idx
	leftChildIdx := LeftChildIdx(idx)
	rightChildIdx := RightChildIdx(idx)

	if leftChildIdx < this.HeapSize && this.MinHeap[leftChildIdx] < this.MinHeap[lowestIdx] {
		lowestIdx = leftChildIdx
	}

	if rightChildIdx < this.HeapSize && this.MinHeap[rightChildIdx] < this.MinHeap[lowestIdx] {
		lowestIdx = rightChildIdx
	}

	if lowestIdx != idx {
		this.MinHeap[idx], this.MinHeap[lowestIdx] = this.MinHeap[lowestIdx], this.MinHeap[idx]
		this.MinHeapify(lowestIdx)
	}
}

func (this *KthLargest) Add(val int) int {
    if this.HeapSize < this.K {
        this.Insert(val)
    } else if this.HeapSize == this.K && val > this.MinHeap[0] {
		this.Delete()
    	this.Insert(val)
	}

	return this.MinHeap[0]
}

func (this *KthLargest) Insert(val int) {
	this.HeapSize++
	this.MinHeap = append(this.MinHeap, val)
	for parentIdx := len(this.MinHeap) - 1; parentIdx >= 0; parentIdx = ParentIdx(parentIdx) {
		this.MinHeapify(parentIdx)
		if parentIdx == 0 {
			return
		}
	}
}

func (this *KthLargest) Delete() {
	this.MinHeap[0], this.MinHeap[len(this.MinHeap)-1] = this.MinHeap[len(this.MinHeap)-1], this.MinHeap[0]
	this.MinHeap = this.MinHeap[:len(this.MinHeap)-1]
	this.HeapSize--

	this.MinHeapify(0)
}

/**
 * Your KthLargest object will be instantiated and called as such:
 * obj := Constructor(k, nums);
 * param_1 := obj.Add(val);
 */
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
54
Q

@78 Subsets

Given an integer array nums of unique elements, return all possible
subsets
(the power set).

The solution set must not contain duplicate subsets. Return the solution in any order.

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

1 <= nums.length <= 10
-10 <= nums[i] <= 10
All the numbers of nums are unique.

A

Backtracking. Use every possible element in the array. Store the susbset and pass it on the the next backtracking function. Change dimension by moving the startIdx in the array, this naturally doesn’t look back.

func subsets(nums []int) [][]int {
    result := [][]int{[]int{}}

    var backtrack func(subset []int, current int)
    backtrack = func(subset []int, current int){
        if len(subset) == len(nums) {
            return 
        }

        // Create a copy of the subset so that we don't update the underlying slices within result
        temp := make([]int, len(subset))
        copy(temp, subset)
        temp = append(temp, nums[current])

        result = append(result, temp)
        
        // Change dimension
        // This naturally doesn't look back, won't pick a used one
        for current = current + 1;current <= len(nums) - 1; current++ {
            backtrack(temp, current) 
        }
    }

    for start := range nums {
        backtrack([]int{}, start)
    }

    return result 
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
55
Q

@39. Combination Sum

Given an array of distinct integers candidates and a target integer target, return a list of all unique combinations of candidates where the chosen numbers sum to target. You may return the combinations in any order.

The same number may be chosen from candidates an unlimited number of times. Two combinations are unique if the
frequency
of at least one of the chosen numbers is different.

The test cases are generated such that the number of unique combinations that sum up to target is less than 150 combinations for the given input.

Example 1:
Input: candidates = [2,3,6,7], target = 7
Output: [[2,2,3],[7]]
Explanation:
2 and 3 are candidates, and 2 + 2 + 3 = 7. Note that 2 can be used multiple times.
7 is a candidate, and 7 = 7.
These are the only two combinations.

1 <= candidates.length <= 30
2 <= candidates[i] <= 40
All elements of candidates are distinct.
1 <= target <= 40

A

Backtracking. Go through every scenario, elminate the one that doesn’t fit the condition, in this case it is when the local sum is greater than the target. Append to combination when the local sum is equal to the target.

func combinationSum(candidates []int, target int) [][]int {
	combinations := make([][]int, 0)

	var backtrack func(currentCandidates []int, currSum int, start int)
	backtrack = func(currentCandidates []int, currSum int, start int) {
		currSum += candidates[start]
		currentCandidates = append(currentCandidates, candidates[start])

		if currSum > target {
			return
		} else if currSum == target {
			combinations = append(combinations, currentCandidates)
			return
		} else { // keep on backtracking when currSum < target
			temp := make([]int, len(currentCandidates))
			copy(temp, currentCandidates)

			for i := start; i < len(candidates); i++ {
				backtrack(temp, currSum, i)
			}
		}
	}

    for i := range candidates {
    	backtrack([]int{}, 0, i)
    }

	return combinations
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
56
Q

@79. Word Search

Given an m x n grid of characters board and a string word, return true if word exists in the grid.

The word can be constructed from letters of sequentially adjacent cells, where adjacent cells are horizontally or vertically neighboring. The same letter cell may not be used more than once.

Example 1:
Input: board = [[“A”,”B”,”C”,”E”],[“S”,”F”,”C”,”S”],[“A”,”D”,”E”,”E”]], word = “ABCCED”
Output: true

m == board.length
n = board[i].length
1 <= m, n <= 6
1 <= word.length <= 15
board and word consists of only lowercase and uppercase English letters.

A

Backtracking. Search every adjacent board blocks. Mark blocks that have already been to “*” and restore it later. Use word indexing for comparison (If we use string comparison it takes too long).

func exist(board [][]byte, word string) bool {
    rows, columns := len(board), len(board[0]) 
    found := false

    var dfs func(row, col, idx int)

    dfs = func(row, col, idx int){
        // 1. Out of bound
        if row < 0 || row >= rows || col < 0 || col >= columns {
            return 
        }
        // 2. Invalid element
        if board[row][col] != word[idx] {
            return 
        }

        // 3. If passed
        if board[row][col] == '*' {
            return 
        }
        
        // 4. Word Found
        if board[row][col] == word[idx] && idx == len(word) - 1 {
            found = true
            return
        }
        temp := board[row][col]
        board[row][col] = '*'
        dfs(row - 1, col, idx + 1)
        dfs(row + 1, col, idx + 1)
        dfs(row, col - 1, idx + 1)
        dfs(row, col + 1, idx + 1)
        board[row][col] = temp
    }

    for row := 0; row < rows; row ++ {
        for col := 0; col < columns; col ++ {
            k := 0 // start index
            dfs(row, col, k)
        }
    }
    return found
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
57
Q

@215. Kth Largest Element in an array

Given an integer array nums and an integer k, return the kth largest element in the array.

Note that it is the kth largest element in the sorted order, not the kth distinct element.

Can you solve it without sorting?

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

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

A

Create a MinHeap of size k. The kth largest is the head of the MinHeap. Insert when the size is smaller than k or the new element is greater than the head.

func findKthLargest(nums []int, k int) int {
	mh := New(k)

	for _, num := range nums {
		if mh.HeapSize < mh.K {
			mh.Insert(num)
			continue
		}

		if num > mh.Heap[0] && mh.HeapSize == mh.K {
			mh.Delete()
			mh.Insert(num)
		}
	}

	return mh.Heap[0]
}

type MinHeap struct {
	Heap     []int
	HeapSize int
	K        int
}

func New(k int) *MinHeap {
	return &MinHeap{
		Heap:     make([]int, 0),
		HeapSize: 0,
		K:        k,
	}
}

func ParentIdx(childIdx int) int {
	return (childIdx - 1) / 2
}

func LeftChildIdx(parentIdx int) int {
	return (parentIdx << 1) + 1

}

func RightChildIdx(parentIdx int) int {
	return (parentIdx + 1) << 1
}

func (m *MinHeap) MinHeapify(idx int) {
	lowest := idx
	leftChildIdx := LeftChildIdx(idx)
	rightChildIdx := RightChildIdx(idx)

	if leftChildIdx < m.HeapSize && m.Heap[leftChildIdx] < m.Heap[lowest] {
		lowest = leftChildIdx
	}

	if rightChildIdx < m.HeapSize && m.Heap[rightChildIdx] < m.Heap[lowest] {
		lowest = rightChildIdx
	}

	if lowest != idx {
		m.Heap[idx], m.Heap[lowest] = m.Heap[lowest], m.Heap[idx]
		m.MinHeapify(lowest)
	}

}

// Delete removes the head from the MinHeap.
func (m *MinHeap) Delete() {
	if m.HeapSize > 0 {
		// Update size.
		m.HeapSize--
		// Swap the head with the end.
		m.Heap[0], m.Heap[len(m.Heap)-1] = m.Heap[len(m.Heap)-1], m.Heap[0]
		// Trim the end.
		m.Heap = m.Heap[:len(m.Heap)-1]
		// MinHeapify the root.
		m.MinHeapify(0)
	}
}

// Insert adds an element into the MinHeap.
func (m *MinHeap) Insert(val int) {
	if m.HeapSize < m.K {
		m.HeapSize++
		m.Heap = append(m.Heap, val)
		for parent := ParentIdx(len(m.Heap) - 1); parent >= 0; parent = ParentIdx(parent) {

			m.MinHeapify(parent)
			if parent == 0 {
				break
			}
		}
	}
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
58
Q

@1046. Last Stone Weight

You are given an array of integers stones where stones[i] is the weight of the ith stone.

We are playing a game with the stones. On each turn, we choose the heaviest two stones and smash them together. Suppose the heaviest two stones have weights x and y with x <= y. The result of this smash is:

If x == y, both stones are destroyed, and
If x != y, the stone of weight x is destroyed, and the stone of weight y has new weight y - x.
At the end of the game, there is at most one stone left.

Return the weight of the last remaining stone. If there are no stones left, return 0.

Example 1:

Input: stones = [2,7,4,1,8,1]
Output: 1
Explanation:
We combine 7 and 8 to get 1 so the array converts to [2,4,1,1,1] then,
we combine 2 and 4 to get 2 so the array converts to [2,1,1,1] then,
we combine 2 and 1 to get 1 so the array converts to [1,1,1] then,
we combine 1 and 1 to get 0 so the array converts to [1] then that’s the value of the last stone.

1 <= stones.length <= 30
1 <= stones[i] <= 1000

A

Create a MaxHeap with a size len(stones). Compare the two left most stones (by deleting twice), and insert the remains back to the max heap. Do it repeatedly until there’s 1 or none elements left in the heap.

func lastStoneWeight(stones []int) int {
    var h1, h2, remain int

    mh := BuildMaxHeap(stones)
    for mh.HeapSize > 1 {
        h1, h2 = mh.Delete(), mh.Delete()
        remain = Compare(h1, h2)
        if remain != 0 {
            mh.Insert(remain)
        }
    }

    if mh.HeapSize == 0 {
        return 0
    } 

	return mh.Heap[0]
}

func Compare(a, b int) int {
	var left int
	switch {
	case a > b:
		left = a - b
	case b > a:
		left = b - a
	}

	return left
}

func ParentIdx(childIdx int) int {
	return (childIdx - 1) / 2
}

func LeftChildIdx(parentIdx int) int {
	return (parentIdx << 1) + 1
}

func RightChildIdx(parentIdx int) int {
	return (parentIdx + 1) << 1
}

type MaxHeap struct {
	Heap     []int
	HeapSize int
}

func BuildMaxHeap(nums []int) *MaxHeap {
	mh := &MaxHeap{
		Heap:     nums,
		HeapSize: len(nums),
	}

	for i := mh.HeapSize / 2; i >= 0; i-- {
		mh.MaxHeapify(i)
	}

	return mh
}

func (m *MaxHeap) MaxHeapify(idx int) {
	largest := idx
	leftChildIdx := LeftChildIdx(idx)
	rightChildIdx := RightChildIdx(idx)

	if leftChildIdx < m.HeapSize && m.Heap[leftChildIdx] > m.Heap[largest] {
		largest = leftChildIdx
	}

	if rightChildIdx < m.HeapSize && m.Heap[rightChildIdx] > m.Heap[largest] {
		largest = rightChildIdx
	}

	if largest != idx {
		m.Heap[idx], m.Heap[largest] = m.Heap[largest], m.Heap[idx]
		m.MaxHeapify(largest)
	}
}

func (m *MaxHeap) Delete() int {
	var head int
	if m.HeapSize > 0 {
		head = m.Heap[0]
		m.Heap[0], m.Heap[len(m.Heap)-1] = m.Heap[len(m.Heap)-1], m.Heap[0]
		m.HeapSize--

		m.Heap = m.Heap[:len(m.Heap)-1]
		m.MaxHeapify(0)
	}

	return head
}

func (m *MaxHeap) Insert(val int) {
	m.HeapSize++
	m.Heap = append(m.Heap, val)

	for parent := ParentIdx(len(m.Heap) - 1); ; parent = ParentIdx(parent) {
		m.MaxHeapify(parent)
		if parent == 0 {
			break
		}
	}
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
59
Q

@621. Task Scheduler

You are given an array of CPU tasks, each represented by letters A to Z, and a cooling time, n. Each cycle or interval allows the completion of one task. Tasks can be completed in any order, but there’s a constraint: identical tasks must be separated by at least n intervals due to cooling time.

​Return the minimum number of intervals required to complete all tasks.

Example 1:
Input: tasks = [“A”,”A”,”A”,”B”,”B”,”B”], n = 2
Output: 8
Explanation: A possible sequence is: A -> B -> idle -> A -> B -> idle -> A -> B.

After completing task A, you must wait two cycles before doing A again. The same applies to task B. In the 3rd interval, neither A nor B can be done, so you idle. By the 4th cycle, you can do A again as 2 intervals have passed.

Example 2:
Input: tasks = [“A”,”C”,”A”,”B”,”D”,”B”], n = 1
Output: 6
Explanation: A possible sequence is: A -> B -> C -> D -> A -> B.

With a cooling interval of 1, you can repeat a task after just one other task.

1 <= tasks.length <= 10^4
tasks[i] is an uppercase English letter.
0 <= n <= 100

A
  • MaxHeap that removes and add according to the logic(complicated, not recommended)
  • Greedy. The least interval is determined by the frequency(maxFrequency) element that occurs the most. There might be multiple elements that have maximum frequency(elementsThatHaveMaxFrequency).The Minimum require time can be calculated by function** (maxFrequency - 1) * (n + 1) + elementsThatHaveMaxFrequency**.

Example:
A = 5, B = 2, C = 1, n = 2

|—| –> This here is n + 1
A _ _ A _ _ A _ _ A _ _ A
|<——————- >| –> (maxFrequency - 1) * (n+ 1)

Since the tail element doesn’t need to add any more intervals, we greedily use (maxFrequency - 1) * (n+ 1). Add the tail elements, for this case it’s A as the tail element (Which is the count of most occured element).

Example2:

A=5, B = 5, n = 3

A _ _ _ A _ _ _ A _ _ _ A _ _ _ A
_ B _ _ _ B _ _ _ B _ _ _ B _ _ _ B
|<—————————->| –> (maxFrequency - 1) * (n+ 1)
|| -> The count of two most elements.

func leastInterval(tasks []byte, n int) int {
    var maxFrequency, elementsThatHaveMaxFrequency int

    frequencyArray := [26]int{}
    for _, task := range tasks {
        frequencyArray[task-'A']++
        maxFrequency = max(maxFrequency, frequencyArray[task-'A'])
    }

    for _, frequencyCount := range frequencyArray {
        if frequencyCount == maxFrequency {
            elementsThatHaveMaxFrequency++
        }
    }

    // Greedy. 算出最少需要多少格剩下就是隨便塞。
    // n + 1 indicates interval + 1 element (which is where the maxFrequency occur).
    lengthWithoutLast := (maxFrequency - 1) * (n + 1)

    // len(tasks) is where n(interval) = 0.  
    return max(len(tasks), lengthWithoutLast + elementsThatHaveMaxFrequency)
}

Greedy. 算出最少需要多少格剩下就是隨便塞。

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
60
Q

@973. K closest to origin

Given an array of points where points[i] = [xi, yi] represents a point on the X-Y plane and an integer k, return the k closest points to the origin (0, 0).
The distance between two points on the X-Y plane is the Euclidean distance (i.e., √(x1 - x2)2 + (y1 - y2)2).
You may return the answer in any order. The answer is guaranteed to be unique (except for the order that it is in).

Example 1:
Input: points = [[1,3],[-2,2]], k = 1
Output: [[-2,2]]
Explanation:
The distance between (1, 3) and the origin is sqrt(10).
The distance between (-2, 2) and the origin is sqrt(8).
Since sqrt(8) < sqrt(10), (-2, 2) is closer to the origin.
We only want the closest k = 1 points from the origin, so the answer is just [[-2,2]].

1 <= k <= points.length <= 10^4
-10^4 <= xi, yi <= 10^4

A

Create a MaxHeap that stores and update when input new coordinate. Add coordinate to heap only when the heap size is smaller than k or when the heap is full and the new coordinate distance is closer to origin.

func kClosest(coordinates [][]int, k int) [][]int {
	mh := New(k)
	var point Point
	for _, coordinate := range coordinates {
		point = Point{
			Coordinate:      coordinate,
			DistanceSquared: coordinate[0]*coordinate[0] + coordinate[1]*coordinate[1],
		}

		if mh.HeapSize < mh.K || point.DistanceSquared < mh.Head() {
			mh.Add(point)
		}
	}
	result := make([][]int, 0)

	for _, p := range mh.Points {
		result = append(result, p.Coordinate)
	}

	return result
}

type Point struct {
	Coordinate      []int
	DistanceSquared int
}

// Use a MaxHeap
type MaxHeap struct {
	Points   []Point
	HeapSize int
	K        int
}

func ParentIdx(childIdx int) int {
	return (childIdx - 1) / 2
}

func LeftChildIdx(parentIdx int) int {
	return (parentIdx << 1) + 1
}

func RightChildIdx(parentIdx int) int {
	return (parentIdx + 1) << 1
}

func New(k int) *MaxHeap {
	return &MaxHeap{
		Points:   make([]Point, 0),
		HeapSize: 0,
		K:        k,
	}
}

func (m *MaxHeap) MaxHeapify(idx int) {
	largest := idx
	leftChildIdx := LeftChildIdx(idx)
	rightChildIdx := RightChildIdx(idx)

	if leftChildIdx < m.HeapSize && m.Points[leftChildIdx].DistanceSquared > m.Points[largest].DistanceSquared {
		largest = leftChildIdx
	}

	if rightChildIdx < m.HeapSize && m.Points[rightChildIdx].DistanceSquared > m.Points[largest].DistanceSquared {
		largest = rightChildIdx
	}

	if largest != idx {
		m.Points[idx], m.Points[largest] = m.Points[largest], m.Points[idx]
		m.MaxHeapify(largest)
	}
}

func (m *MaxHeap) Head() int {
	if len(m.Points) > 0 {
		return m.Points[0].DistanceSquared
	}

	return int(math.Inf(1))
}

func (m *MaxHeap) Add(point Point) {
	if m.HeapSize == m.K {
		// Heap full.
		m.Delete()
	}
	m.Points = append(m.Points, point)
	m.HeapSize++

	for parent := m.HeapSize - 1; parent != 0; parent = ParentIdx(parent) {
		m.MaxHeapify(ParentIdx(parent))
	}
}

func (m *MaxHeap) Delete() {
	if len(m.Points) > 0 {
		m.Points[0], m.Points[m.HeapSize-1] = m.Points[m.HeapSize-1], m.Points[0]
		m.Points = m.Points[:m.HeapSize-1]
		m.HeapSize--
		m.MaxHeapify(0)
	}
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
61
Q

@46. Permutation

Given an array nums of distinct integers, return all the possible permutations. You can return the answer in any order.

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

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

1 <= nums.length <= 6
-10 <= nums[i] <= 10
All the integers of nums are unique.

A

Backtracking. The backtrack condition is where the length of the local permutation reaches the length of nums. Copy the local permutation and current number pool so that we don’t modify the original number array.

func permute(nums []int) [][]int {
    result := make([][]int, 0)
    size := len(nums)

    var backtrack func(numbers []int, permutation []int)
    backtrack = func(numbers []int, permutation []int){
        if len(permutation) ==  size {
            result = append(result, permutation)
            return
        }

        for i := range numbers {
            currentPermutation := make([]int, len(permutation))
            copy(currentPermutation, permutation)

            currentPermutation = append(currentPermutation, numbers[i])

            currentPool := make([]int, len(numbers))
            copy(currentPool, numbers)
            currentPool = append(currentPool[:i], currentPool[i+1:]...)
            backtrack(currentPool, currentPermutation)
        }
    }
    
    backtrack(nums, []int{})

    return result
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
62
Q

@40. Combination Sum 2

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

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

Note: The solution set must not contain duplicate combinations.

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

Example 2:
Input: candidates = [2,5,2,1,2], target = 5
Output:
[[1,2,2], [5]]

1 <= candidates.length <= 100
1 <= candidates[i] <= 50
1 <= target <= 30

A

Backtracking. Sort the array first (so that we can compare duplicates). Note that we allow duplicates as different element in the result. Use a decision tree to think of the conditions to eliminate.

func combinationSum2(candidates []int, target int) [][]int {
	result := make([][]int, 0)
	sort.Ints(candidates)

	var backtrack func(start int, combination []int, currentSum int)
	backtrack = func(start int, combination []int, currentSum int) {
		if currentSum > target {
			return
		}

		if currentSum == target {
			result = append(result, combination)
			return
		}

		for i := start + 1; i < len(candidates); i++ {
            // The duplicate can only be at the start.
            if i-1 != start && candidates[i-1] == candidates[i] {
                continue
            }
                        
			temp := make([]int, len(combination))
			copy(temp, combination)
			temp = append(temp, candidates[i])

			backtrack(i, temp, currentSum+candidates[i])
		}
	}

	backtrack(-1, []int{}, 0)

	return result
}

Use a decision tree for the thinking process.

63
Q

@17. Letter Combinations of a phone number

Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent. Return the answer in any order.

A mapping of digits to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters.

letterMap := map[byte]string{
        '2': "abc", '3': "def", '4': "ghi", '5': "jkl",
        '6': "mno", '7': "pqrs", '8': "tuv", '9': "wxyz",
    }

Example 1:
Input: digits = “23”
Output: [“ad”,”ae”,”af”,”bd”,”be”,”bf”,”cd”,”ce”,”cf”]

0 <= digits.length <= 4
digits[i] is a digit in the range [‘2’, ‘9’].

A

Backtracking. Loop through the digit (which naturally doesn’t look back) as start, and pick from the corresponding letter pool.

func letterCombinations(digits string) []string {
    letterMap := map[byte]string{
        '2': "abc", '3': "def", '4': "ghi", '5': "jkl",
        '6': "mno", '7': "pqrs", '8': "tuv", '9': "wxyz",
    }

    result := make([]string, 0)
    var backtrack func(currentString string, start int)
    backtrack = func(currentString string, start int) {
        if len(currentString) == len(digits) {
            result = append(result, currentString)
            return
        }
        if start >= len(digits) {
            return
        }
        letterPool := letterMap[digits[start]]
        for _, letter := range letterPool {
            backtrack(currentString+string(letter), start+1)
        }
    }
    for start := 0; start < len(digits); start++ {
        backtrack("", start)
    }

    return result
}

Use a decision tree for the thinking process.

64
Q

@90. Subsets 2

Given an integer array nums that may contain duplicates, return all possible
subsets
(the power set).

The solution set must not contain duplicate subsets. Return the solution in any order.

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

Input: nums = [0]
Output: [[],[0]]

1 <= nums.length <= 10
-10 <= nums[i] <= 10

A

Backtracking. Append currSubset (which in Go we need to copy) at every function call. Eliminate duplicates by sorting the array first then compare the element with the previous element. If the element is the same, continue.

func subsetsWithDup(nums []int) [][]int {
	result := make([][]int, 0)
	sort.Ints(nums)

	var backtrack func(start int, currSusbset []int)
	backtrack = func(start int, currSubset []int) {
		// Copy the currSubset so that further modifications to the currSubset won't effect the result 
        temp := make([]int, len(currSubset))
		copy(temp, currSubset)
		result = append(result, temp)

		for i := start; i < len(nums); i++ {
			if i > start && nums[i] == nums[i-1] {
				continue
			}
			backtrack(i+1, append(currSubset, nums[i]))
		}
	}

	backtrack(0, []int{})

	return result
}
65
Q

@200. Number of islands

Given an m x n 2D binary grid grid which represents a map of ‘1’s (land) and ‘0’s (water), return the number of islands.

An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.

Example 1:
Input: grid = [
[“1”,”1”,”1”,”1”,”0”],
[“1”,”1”,”0”,”1”,”0”],
[“1”,”1”,”0”,”0”,”0”],
[“0”,”0”,”0”,”0”,”0”]
]
Output: 1

Example 2:
Input: grid = [
[“1”,”1”,”0”,”0”,”0”],
[“1”,”1”,”0”,”0”,”0”],
[“0”,”0”,”1”,”0”,”0”],
[“0”,”0”,”0”,”1”,”1”]
]
Output: 3

m == grid.length
n == grid[i].length
1 <= m, n <= 300
grid[i][j] is ‘0’ or ‘1’.

A

Depth first search. When we encounter a ‘1’ and it is not connected with any other land, itself is a start of a new island, add one to count. Then exhaust every adjacent lands by marking them as ‘*’.

func numIslands(grid [][]byte) int {
    var islands int
    // Walk exhausts the island area.
    var walk func(row, col int, isConnected bool)
    walk = func(row, col int, isConnected bool){
        // Out of range.
        if row < 0 || row >= len(grid) {
            return
        }

        if col < 0 || col >= len(grid[0]){
            return
        }
        
        // Been there, mark as island.
        // If a land is marked, it's already considered as a part of one of the counted island.
        if grid[row][col] == '*' {
            return 
        }

        // Is land.
        if grid[row][col] == '1' {
            if !isConnected {
                islands++
                isConnected = true
            }
            grid[row][col] = '*'

            walk(row - 1, col, isConnected)
            walk(row + 1, col, isConnected)
            walk(row, col - 1, isConnected)
            walk(row, col + 1, isConnected)
        } 

        isConnected = false
    }

    for row := range grid {
        for col := range grid[0] {
            walk(row, col, false)
        }
    }

    return islands
}
66
Q

@208. Implement a trie

A trie (pronounced as “try”) or prefix tree is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker.

Implement the Trie class:

Trie() Initializes the trie object.
void insert(String word) Inserts the string word into the trie.
boolean search(String word) Returns true if the string word is in the trie (i.e., was inserted before), and false otherwise.
boolean startsWith(String prefix) Returns true if there is a previously inserted string word that has the prefix prefix, and false otherwise.

Example 1:
Input
[“Trie”, “insert”, “search”, “search”, “startsWith”, “insert”, “search”]
[[], [“apple”], [“apple”], [“app”], [“app”], [“app”], [“app”]]
Output
[null, null, true, false, true, null, true]

Explanation
Trie trie = new Trie();
trie.insert(“apple”);
trie.search(“apple”); // return True
trie.search(“app”); // return False
trie.startsWith(“app”); // return True
trie.insert(“app”);
trie.search(“app”); // return True

1 <= word.length, prefix.length <= 2000
word and prefix consist only of lowercase English letters.
At most 3 * 104 calls in total will be made to insert, search, and startsWith.

A

Create an array that has 26 slots with the value of the children trie address.

type Trie struct {
    Children []*Trie
    IsEnd    bool
}

// Constuctor is simply a wrapper. Normally I don't prefer returning a copy.
func Constructor() Trie {
    return *New()
}

func New() *Trie {
    return &Trie{
        Children: make([]*Trie, 26),
        IsEnd:    false,
    }
}

func (this *Trie) Insert(word string) {
    var position byte
    temp := this
    for i := range word {
        position = word[i] - 'a'
        if temp.Children[position] == nil {
            temp.Children[position] = New()
        }
        temp = temp.Children[position]
    }
    temp.IsEnd = true

}

func (this *Trie) Search(word string) bool {
    var position byte
    temp := this
    for i := range word {
        position = word[i] - 'a'
        if temp.Children[position] == nil {
            return false
        }
        temp = temp.Children[position]
    }
    return temp.IsEnd
}

func (this *Trie) StartsWith(prefix string) bool{
    var position byte
    temp := this
    for i := range prefix {
        position = prefix[i] - 'a'
        if temp.Children[position] == nil {
            return false
        }
        temp = temp.Children[position]
    }

    return true
}
67
Q

@695 Max Area of Island

You are given an m x n binary matrix grid. An island is a group of 1’s (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water.

The area of an island is the number of cells with a value 1 in the island.

Return the maximum area of an island in grid. If there is no island, return 0.

Example 1:
Input: grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]]
Output: 6
Explanation: The answer is not 11, because the island must be connected 4-directionally.
Example 2:

Input: grid = [[0,0,0,0,0,0,0,0]]
Output: 0

m == grid.length
n == grid[i].length
1 <= m, n <= 50
grid[i][j] is either 0 or 1

A

Depth First Search. If encounter land “1”, exhaust all ajacent land and update the local area. After finishing with the node, compare to the max area.

func maxAreaOfIsland(grid [][]int) int {
	maxArea := 0

	var walk func(row, col int, localArea *int)
	walk = func(row, col int, localArea *int) {
		if row < 0 || row >= len(grid) || col < 0 || col >= len(grid[0]) || grid[row][col] != 1 {
			return
		}

		(*localArea)++
		grid[row][col] = -1

		walk(row-1, col, localArea)
		walk(row+1, col, localArea)
		walk(row, col-1, localArea)
		walk(row, col+1, localArea)

	}

	for row := range grid {
		for col := range grid[0] {
			area := 0 // Initialize area for each new island
			walk(row, col, &area)
	    	// Update maxArea after traversing the island
    		maxArea = max(maxArea, area)
		}
	}

	return maxArea
}
68
Q

@133. Clone Graph

Given a reference of a node in a connected undirected graph.

Return a deep copy (clone) of the graph.

Each node in the graph contains a value (int) and a list (List[Node]) of its neighbors.

class Node {
public int val;
public List<Node> neighbors;
}</Node>

Test case format:

For simplicity, each node’s value is the same as the node’s index (1-indexed). For example, the first node with val == 1, the second node with val == 2, and so on. The graph is represented in the test case using an adjacency list.

An adjacency list is a collection of unordered lists used to represent a finite graph. Each list describes the set of neighbors of a node in the graph.

The given node will always be the first node with val = 1. You must return the copy of the given node as a reference to the cloned graph.

Input: adjList = [[2,4],[1,3],[2,4],[1,3]]
Output: [[2,4],[1,3],[2,4],[1,3]]
Explanation: There are 4 nodes in the graph.
1st node (val = 1)’s neighbors are 2nd node (val = 2) and 4th node (val = 4).
2nd node (val = 2)’s neighbors are 1st node (val = 1) and 3rd node (val = 3).
3rd node (val = 3)’s neighbors are 2nd node (val = 2) and 4th node (val = 4).
4th node (val = 4)’s neighbors are 1st node (val = 1) and 3rd node (val = 3).

The number of nodes in the graph is in the range [0, 100].
1 <= Node.val <= 100
Node.val is unique for each node.
There are no repeated edges and no self-loops in the graph.
The Graph is connected and all nodes can be visited starting from the given node.

A
  • Iterative, traverse the graph first and create a clone map. Copy the cloned neighbors in the next loop.
/**
 * Definition for a Node.
 * type Node struct {
 *     Val int
 *     Neighbors []*Node
 * }
 */

func cloneGraph(node *Node) *Node {
	if node == nil {
		return nil
	}

	cloneMap := make(map[*Node]*Node)

	been := make(map[*Node]struct{})
	queue := []*Node{node}

	for len(queue) != 0 {
		head := queue[0]
		if _, ok := been[head]; !ok {
			been[head] = struct{}{}
			cloneMap[head] = &Node{
				Val:       head.Val,
				Neighbors: make([]*Node, 0),
			}
		}

		queue = queue[1:]

		for _, neighbor := range head.Neighbors {
			if _, ok := been[neighbor]; !ok {
				queue = append(queue, neighbor)
			}
		}
	}

	been = make(map[*Node]struct{})
	queue = []*Node{node}

	for len(queue) != 0 {
		head := queue[0]
		if _, ok := been[head]; !ok {
			been[head] = struct{}{}
			for _, neighbor := range head.Neighbors {
				cloneMap[head].Neighbors = append(cloneMap[head].Neighbors, cloneMap[neighbor])
			}
		}

		queue = queue[1:]
		for _, neighbor := range head.Neighbors {
			if _, ok := been[neighbor]; !ok {
				queue = append(queue, neighbor)
			}
		}
	}

	return cloneMap[node]
}
  • Recursive. Clone the neighbors recursively.
    ~~~
    /**
  • Definition for a Node.
  • type Node struct {
  • Val int
  • Neighbors []*Node
  • }
    */

func cloneGraph(node Node) Node {
clonedNodes := make(map[
Node]
Node)

var clone func(node *Node) *Node
clone = func(node *Node) *Node {
    if node == nil {
        return nil
    }
    
    cloned, ok := clonedNodes[node]
    if ok {
        return cloned 
    }

    clonedNode := &Node{
        Val: node.Val,
        Neighbors: make([]*Node, 0),
    }

    clonedNodes[node] = clonedNode

    for _, neighborNode := range node.Neighbors {
        clonedNode.Neighbors = append(clonedNode.Neighbors, clone(neighborNode))
    }

    return clonedNode
}

return clone(node) } ~~~
69
Q

@994. Rotten Orange

You are given an m x n grid where each cell can have one of three values:

0 representing an empty cell,
1 representing a fresh orange, or
2 representing a rotten orange.
Every minute, any fresh orange that is 4-directionally adjacent to a rotten orange becomes rotten.

Return the minimum number of minutes that must elapse until no cell has a fresh orange. If this is impossible, return -1.

Example1:
Input: grid = [[2,1,1],[1,1,0],[0,1,1]]
Output: 4

Example 2:
Input: grid = [[2,1,1],[0,1,1],[1,0,1]]
Output: -1
Explanation: The orange in the bottom left corner (row 2, column 0) is never rotten, because rotting only happens 4-directionally.

Example 3:
Input: grid = [[0,2]]
Output: 0
Explanation: Since there are already no fresh oranges at minute 0, the answer is just 0.

m == grid.length
n == grid[i].length
1 <= m, n <= 10
grid[i][j] is 0, 1, or 2.

A

Breath first search. Use a coordinates queue to keep rotten oranges at every minute. Exhaust all rotten orange at from the queue and append adjacent contaminated rotten orange to the queue. The new queue length is the oranges we need to go through at the next minute. Do this till there’s no more rotten orange in the queue. Since there might be fresh oranges that are never contaminated, we’ll apply another check at the end.

func orangesRotting(grid [][]int) int {
	queue := make([][]int, 0) // Coordinates queue.

    // Find the rotten tomatos. 
	for row := range grid {
		for col := range grid[0] {
			if grid[row][col] == 2 {
				queue = append(queue, []int{row, col})
			}
		}
	}

    // Breadth first search, contaminate and push to queue.
	var contaminate func(coordinate []int)
	contaminate = func(coordinate []int) {
		row, col := coordinate[0], coordinate[1]
		if row > 0 && grid[row-1][col] == 1 {
			grid[row-1][col] = 2
			queue = append(queue, []int{row - 1, col})
		}

		if row < len(grid)-1 && grid[row+1][col] == 1 {
			grid[row+1][col] = 2
			queue = append(queue, []int{row + 1, col})
		}

		if col > 0 && grid[row][col-1] == 1 {
			grid[row][col-1] = 2
			queue = append(queue, []int{row, col - 1})
		}

		if col < len(grid[0])-1 && grid[row][col+1] == 1 {
			grid[row][col+1] = 2
			queue = append(queue, []int{row, col + 1})
		}
	}

	var count int
    // rottenOranges is the numbers of rotten orange within the minute.
	rottenOranges := len(queue)
	for rottenOranges != 0 {
        // Pop all rotten oranges from the current image.
		for i := 0; i < rottenOranges; i++ {
			head := queue[0]
			queue = queue[1:]
			contaminate(head)
		}

        // The current queue is the rotten orange at the next minute.
		rottenOranges = len(queue)
		if rottenOranges != 0 {
			count++
		}
	}

	// Check if there's still fresh orange.
	for row := range grid {
		for col := range grid[0] {
			if grid[row][col] == 1 {
				return -1
			}
		}
	}

	return count
}
70
Q

@70 Climbing Stairs

You are climbing a staircase. It takes n steps to reach the top.

Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?

Example 1:
Input: n = 2
Output: 2
Explanation: There are two ways to climb to the top.
1. 1 step + 1 step
2. 2 steps

Example 2:
Input: n = 3
Output: 3
Explanation: There are three ways to climb to the top.
1. 1 step + 1 step + 1 step
2. 1 step + 2 steps
3. 2 steps + 1 step

1 <= n <= 45

A

It’s a Fibonacci List.
* Iterative Bottom Up Dynamic Programming.

func climbStairs(n int) int {
    fibTable := make([]int, n)
    fibTable[0] = 1
    if len(fibTable) > 1 {
        fibTable[1] = 2
    }

    for i := 2; i < n; i++ {
        fibTable[i] = fibTable[i - 1] + fibTable[i - 2]
    }

    return fibTable[n - 1]
}

It’s a Fibonacci Series.

71
Q

@746. Min Cost Climbing Stairs

You are given an integer array cost where cost[i] is the cost of ith step on a staircase. Once you pay the cost, you can either climb one or two steps.

You can either start from the step with index 0, or the step with index 1.

Return the minimum cost to reach the top of the floor.

Example 1:
Input: cost = [10,15,20]
Output: 15
Explanation: You will start at index 1.
- Pay 15 and climb two steps to reach the top.
The total cost is 15.

Example 2:
Input: cost = [1,100,1,1,1,100,1,1,100,1]
Output: 6
Explanation: You will start at index 0.
- Pay 1 and climb two steps to reach index 2.
- Pay 1 and climb two steps to reach index 4.
- Pay 1 and climb two steps to reach index 6.
- Pay 1 and climb one step to reach index 7.
- Pay 1 and climb two steps to reach index 9.
- Pay 1 and climb one step to reach the top.
The total cost is 6.

2 <= cost.length <= 1000
0 <= cost[i] <= 999

A

Dynamic Programming. Calculate the last two cost first. Then look backwards, cost is adding current cost with the minimum from the next two cost. Pick the minimum between the first or second cost in the table (since we can start at step 1 or step 2).

func minCostClimbingStairs(cost []int) int {
    stairs := len(cost)
    costTable := make([]int, stairs)
    costTable[stairs - 1] = cost[stairs - 1]
    costTable[stairs - 2] = min(cost[stairs - 1] + cost[stairs - 2], cost[stairs - 2])
    
    for i := stairs - 3; i >= 0; i-- {
        costTable[i] = cost[i] + min(costTable[i+1], costTable[i+2])
    }
    
    return min(costTable[0], costTable[1])
}
72
Q

@198. House Robber

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security systems connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.

Example 1:
Input: nums = [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.

Example 2:
Input: nums = [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
Total amount you can rob = 2 + 9 + 1 = 12.

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

A

Dynamic Programming. Form a dp table that stores the local max amount. Every new house needs to adds onto the max amount from max(dpTable[i-2], dpTable[i-3]), meaning that we’re checking which house has more amount, 2 house before or 3 house before.

1 _ 2 => 2 + 1
1, 8 _ 2 => 2 + 8
1, 3 , 100 _ 2 => 2 + 100 or 2 + 3, wouldn’t jump directly to 1 because we miss a viable number 100 in between.

func rob(nums []int) int {

	houses := len(nums)
	dpTable := make([]int, houses)

	dpTable[0] = nums[0]
	maxAmount := dpTable[0]

	for i := 1; i < houses; i++ {
		switch i {
		case 1:
			dpTable[i] = nums[i]
		case 2:
			dpTable[i] = dpTable[0] + nums[i]
		default:
			dpTable[i] = nums[i] + max(dpTable[i-2], dpTable[i-3])
		}

		maxAmount = max(maxAmount, dpTable[i])
	}

	return maxAmount
}
73
Q

@213. House Robber 2

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have a security system connected, and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.

Example 1:
Input: nums = [2,3,2]
Output: 3
Explanation: You cannot rob house 1 (money = 2) and then rob house 3 (money = 2), because they are adjacent houses.

Example 2:
Input: nums = [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.

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

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

A

Since House[1] and House[n] are adjacent, they cannot be robbed together. Therefore, the problem becomes to rob either House[1]-House[n-1] or House[2]-House[n], depending on which choice offers more money. Now the problem has degenerated to the House Robber, which is already been solved.

func rob(nums []int) int {
	houses := len(nums)
	if houses == 1 {
		return nums[0]
	}
	return max(houseRob(nums[:houses-1]), houseRob(nums[1:houses]))

}

func houseRob(nums []int) int {
	houses := len(nums)
    if houses == 0 {
        return 0
    }

	dpTable := make([]int, houses)
	dpTable[0] = nums[0]
	maxAmount := dpTable[0]

	for i := 1; i < houses; i++ {
		switch i {
		case 1:
			dpTable[i] = nums[i]
		case 2:
			dpTable[i] = nums[i] + nums[i-2]
		default:
			dpTable[i] = nums[i] + max(dpTable[i-2], dpTable[i-3])
		}
		maxAmount = max(maxAmount, dpTable[i])
	}
	return maxAmount
}
74
Q

@55. Jump Game

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.

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

A
  • Dynamic Programming( Slower ). Keep a table that stores whether the location can reach the end.
func canJump(nums []int) bool {
	canReachEnd := make([]bool, len(nums))

    for i := len(nums) - 1; i >= 0; i-- {
        if i + nums[i] >= len(nums) - 1 {
            canReachEnd[i] = true
        } else {
            for step := 1; step <= nums[i]; step++ {
                if i + step < len(nums) {
                    if canReachEnd[i + step] {
                        canReachEnd[i] = true
                    }
                }
            }
        }
    }

	
	return canReachEnd[0]
}
75
Q

@53. Maximum Subarray

Given an integer array nums, find the
subarray
with the largest sum, and return its sum.

Example 1:
Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6
Explanation: The subarray [4,-1,2,1] has the largest sum 6.

Example 2:
Input: nums = [1]
Output: 1
Explanation: The subarray [1] has the largest sum 1.

Example 3:
Input: nums = [5,4,-1,7,8]
Output: 23
Explanation: The subarray [5,4,-1,7,8] has the largest sum 23.

Follow up: If you have figured out the O(n) solution, try coding another

Constraints:

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

A

Greedy. If the carryOn is negative, discard the previous array. Otherwise add the carryOn to the current number and compare to the previously-stored maxSum.

It is greedy because there could be a negative carryOn in the middle of the array and might corrupt the previous max. We wouldn’t know if there’s another max after the negative carryOn, thus we should compare all the way to the end of the list.

func maxSubArray(nums []int) int {
    maxSum := -math.MaxInt
    carryOn := 0

    for i := range nums {
        // max(carryOn, 0) checks if the carryOn is negative.
        // if the carryOn is negative, discard the carryOn.
        carryOn = max(carryOn, 0) + nums[i]
        maxSum = max(maxSum, carryOn)
    }

    return maxSum
}
76
Q

@134. 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.

n == gas.length == cost.length
1 <= n <= 10^5
0 <= gas[i], cost[i] <= 10^4

A

Greedy. Calculate the difference betweem cost and gas.(gas-cost = diff). If diff[i] is smaller or equal to 0, we can’t start at that point. Check every diff[i] that is greater than 0. Every positive cost can possibly complete the circuit, thus we have to check every costs spent on each round, and if we reached the start and the total is still greater than 0, we have a valid answer.

gas = [1, 2, 3, 4, 5]
cost = [3, 4, 5, 1, 2]
diff = [-2, -2, -2, 3, 3] // The surplus of gas.

func canCompleteCircuit(gas []int, cost []int) int {
	diff := make([]int, len(gas))

	for i := 0; i < len(diff); i++ {
		diff[i] = gas[i] - cost[i]
	}

	if len(diff) == 1 && diff[0] >= 0 {
		return 0
	}

	for start := 0; start < len(diff); start++ {
		if diff[start] <= 0 {
			continue
		}
		total := diff[start]
		next := start
		for {
			next++
			if next == len(gas) {
				next -= len(gas)
			}

			if next == start {
				break
			}

			total += diff[next]
			if total < 0 {
				break
			}
		}
		if total >= 0 {
			return start
		}
	}

	return -1
}
77
Q

@5. Longest Palindromic Substring

Given a string s, return the longest
palindromic

substring
in s.

Example 1:
Input: s = “babad”
Output: “bab”
Explanation: “aba” is also a valid answer.

Example 2:
Input: s = “cbbd”
Output: “bb”

1 <= s.length <= 1000
s consist of only digits and English letters.

A

A palindrome has two forms: One with a single core ‘aba’ and another with a two-element core ‘abba’. By expanding left and right around the cores, we can know if the expanded string is a palindrome. Compare all possible palindromes, return the longest palindromic substring.

func longestPalindrome(s string) string {
	if len(s) == 1 {
		return s
	}

	var longestSubstring string
	// Check palindrome that has core with 1 element.
	for i := 0; i < len(s); i++ {
		longestSubstring = maxSubstring(longestSubstring, string(s[i]))

		left, right := i-1, i+1
		for left >= 0 && right <= len(s)-1 {
			if s[left] == s[right] {
				longestSubstring = maxSubstring(longestSubstring, s[left:right+1])
				left--
				right++
			} else {
				break
			}
		}
	}

	// Check palindrome that has core with 2 element.
    for i := 1; i < len(s); i++ {
        if s[i] != s[i-1] {
            continue
        }
        longestSubstring = maxSubstring(longestSubstring, s[i - 1: i + 1])

        left, right := i - 2, i + 1
        for left >= 0 && right <= len(s) - 1 {
            if s[left] == s[right] {
                longestSubstring = maxSubstring(longestSubstring, s[left: right + 1])
                left--
                right++
            } else {
                break
            }
        }
    }

	return longestSubstring
}

func maxSubstring(a, b string) string {
	if len(a) > len(b) {
		return a
	}

	return b
}

A palindrome has two forms: One with a single core ‘aba’ and another with a two-element core ‘abba’

78
Q

@647. Palindromic Substring

Given a string s, return the number of palindromic substrings in it.

A string is a palindrome when it reads the same backward as forward.

A substring is a contiguous sequence of characters within the string.

Example 1:
Input: s = “abc”
Output: 3
Explanation: Three palindromic strings: “a”, “b”, “c”.

Example 2:
Input: s = “aaa”
Output: 6
Explanation: Six palindromic strings: “a”, “a”, “a”, “aa”, “aa”, “aaa”.

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

A

Expand the substring around possible palindrome cores. Add 1 to count when encounter a valid palindrome.

func countSubstrings(s string) int {
	if len(s) == 1 {
		return 1
	}

	var count int
	for i := 0; i < len(s); i++ {
		count++
		left, right := i-1, i+1
		for left >= 0 && right <= len(s)-1 {
			if s[left] == s[right] {
				count++
				left--
				right++
			} else {
				break
			}
		}
	}

	for i := 1; i < len(s); i++ {
		if s[i] == s[i-1] {
			count++
			left, right := i-2, i+1
			for left >= 0 && right <= len(s)-1 {
				if s[left] == s[right] {
					count++
					left--
					right++
				} else {
                    break
                }
			}
		}
	}

	return count
}

A palindrome has two forms: One with a single core ‘aba’ and another with a two-element core ‘abba’

79
Q

@1899. Merge Triplets to Form Target TripletA triplet is an array of thr

A triplet is an array of three integers. You are given a 2D integer array triplets, where triplets[i] = [ai, bi, ci] describes the ith triplet. You are also given an integer array target = [x, y, z] that describes the triplet you want to obtain.

To obtain target, you may apply the following operation on triplets any number of times (possibly zero):

Choose two indices (0-indexed) i and j (i != j) and update triplets[j] to become [max(ai, aj), max(bi, bj), max(ci, cj)].
For example, if triplets[i] = [2, 5, 3] and triplets[j] = [1, 7, 5], triplets[j] will be updated to [max(2, 1), max(5, 7), max(3, 5)] = [2, 7, 5].
Return true if it is possible to obtain the target triplet [x, y, z] as an element of triplets, or false otherwise.

Example 1:
Input: triplets = [[2,5,3],[1,8,4],[1,7,5]], target = [2,7,5]
Output: true
Explanation: Perform the following operations:
- Choose the first and last triplets [[2,5,3],[1,8,4],[1,7,5]]. Update the last triplet to be [max(2,1), max(5,7), max(3,5)] = [2,7,5]. triplets = [[2,5,3],[1,8,4],[2,7,5]]
The target triplet [2,7,5] is now an element of triplets.

Example 2:
Input: triplets = [[3,4,5],[4,5,6]], target = [3,2,5]
Output: false
Explanation: It is impossible to have [3,2,5] as an element because there is no 2 in any of the triplets.

Example 3:
Input: triplets = [[2,5,3],[2,3,4],[1,2,5],[5,2,3]], target = [5,5,5]
Output: true
Explanation: Perform the following operations:
- Choose the first and third triplets [[2,5,3],[2,3,4],[1,2,5],[5,2,3]]. Update the third triplet to be [max(2,1), max(5,2), max(3,5)] = [2,5,5]. triplets = [[2,5,3],[2,3,4],[2,5,5],[5,2,3]].
- Choose the third and fourth triplets [[2,5,3],[2,3,4],[2,5,5],[5,2,3]]. Update the fourth triplet to be [max(2,5), max(5,2), max(5,3)] = [5,5,5]. triplets = [[2,5,3],[2,3,4],[2,5,5],[5,5,5]].
The target triplet [5,5,5] is now an element of triplets.

1 <= triplets.length <= 10^5
triplets[i].length == target.length == 3
1 <= ai, bi, ci, x, y, z <= 1000

A

Filter invalid triplets.
We will never pick a triplet that it’s triplet[i] is greater than the target[i]. => If picked, the target can never be formed.

  • Elegant way
func mergeTriplets(triplets [][]int, target []int) bool {
    res := make([]int, 3)
    for _, triplet := range triplets {
        // Ignore triplets that have any value greater than the target.
        if triplet[0] > target[0] || triplet[1] > target[1] || triplet[2] > target[2] {
            continue
        }

        res[0] = max(triplet[0], res[0])
        res[1] = max(triplet[1], res[1])
        res[2] = max(triplet[2], res[2])
    }

    // The formed res should equal to the target.
    return res[0] == target[0] && res[1] == target[1] && res[2] == target[2]
}
  • Ugly Way
    ~~~
    func mergeTriplets(triplets [][]int, target []int) bool {
    // Filter invalid triplets.
    // We will never pick a triplet that it’s triplet[i] is greater than the target[i]. => If picked, the target can never be formed.
    toBeRemoved := make(map[int]struct{})for i, num := range target {
    for j, triplet := range triplets {
    if triplet[i] > num {
    toBeRemoved[j] = struct{}{}
    }
    }
    }filteredTriplets := make([][]int, 0)
    for i, triplet := range triplets {
    if _, ok := toBeRemoved[i]; !ok {
    filteredTriplets = append(filteredTriplets, triplet)
    }
    }first, second, third := make(map[int]struct{}), make(map[int]struct{}), make(map[int]struct{})
    for _, triplet := range filteredTriplets {
    for j, num := range triplet {
    switch j {
    case 0:
    first[num] = struct{}{}
    case 1:
    second[num] = struct{}{}
    case 2:
    third[num] = struct{}{}
    }
    }
    }for i, num := range target {
    var ok bool
    switch i {
    case 0:
    _, ok = first[num]
    case 1:
    _, ok = second[num]
    case 2:
    _, ok = third[num]
    }
    if !ok {
    return false
    }
    }return true
    }
    ~~~
80
Q

@91. Decode Ways

A message containing letters from A-Z can be encoded into numbers using the following mapping:

‘A’ -> “1”
‘B’ -> “2”

‘Z’ -> “26”
To decode an encoded message, all the digits must be grouped then mapped back into letters using the reverse of the mapping above (there may be multiple ways). For example, “11106” can be mapped into:

“AAJF” with the grouping (1 1 10 6)
“KJF” with the grouping (11 10 6)
Note that the grouping (1 11 06) is invalid because “06” cannot be mapped into ‘F’ since “6” is different from “06”.

Given a string s containing only digits, return the number of ways to decode it.

The test cases are generated so that the answer fits in a 32-bit integer.

Example 1:
Input: s = “12”
Output: 2
Explanation: “12” could be decoded as “AB” (1 2) or “L” (12).

Example 2:
Input: s = “226”
Output: 3
Explanation: “226” could be decoded as “BZ” (2 26), “VF” (22 6), or “BBF” (2 2 6).

Example 3:
Input: s = “06”
Output: 0
Explanation: “06” cannot be mapped to “F” because of the leading zero (“6” is different from “06”).

1 <= s.length <= 100
s contains only digits and may contain leading zero(s).

A

Back tracking and dynamic programming. Figure out the brute force way and store the result. If 0, return 0, if at the end string, return 1.

func numDecodings(s string) int {
        dpTable := make(map[int]int)

        var exhaust func(start int) int
        exhaust = func(start int) int {
            if start < len(s) && s[start] == '0' {
                return 0
            }

            if start >= len(s)-1 {
                return 1
            }
            // If already calculated, return the calculated result.
            if _, ok := dpTable[start]; ok {
                return dpTable[start]
            }

            switch s[start] {
            case '1':
                // If encounter 1, jumping by 1 and by 2 are both valid.
                dpTable[start] = exhaust(start + 1) + exhaust(start + 2)
            case '2':
                // If encounter 2, jumping by 1 is valid.
                dpTable[start] = exhaust(start + 1)

            // Need to check if the next value is smaller than 7.
            if start+1 < len(s) {
                if s[start+1] < 55 {
                    dpTable[start] += exhaust(start + 2)
                }
            }
            default:
                // Anything that aren't 1 or 2 should jump 1.
                dpTable[start] = exhaust(start + 1)
            }

            return dpTable[start]
        }

        return exhaust(0)
    }
81
Q

@2243. Calculate Digit Sum of a String

You are given a string s consisting of digits and an integer k.

A round can be completed if the length of s is greater than k. In one round, do the following:

Divide s into consecutive groups of size k such that the first k characters are in the first group, the next k characters are in the second group, and so on. Note that the size of the last group can be smaller than k.
Replace each group of s with a string representing the sum of all its digits. For example, “346” is replaced with “13” because 3 + 4 + 6 = 13.
Merge consecutive groups together to form a new string. If the length of the string is greater than k, repeat from step 1.
Return s after all rounds have been completed.

Example 1:
Input: s = “11111222223”, k = 3
Output: “135”
Explanation:
- For the first round, we divide s into groups of size 3: “111”, “112”, “222”, and “23”.
​​​​​Then we calculate the digit sum of each group: 1 + 1 + 1 = 3, 1 + 1 + 2 = 4, 2 + 2 + 2 = 6, and 2 + 3 = 5.
So, s becomes “3” + “4” + “6” + “5” = “3465” after the first round.
- For the second round, we divide s into “346” and “5”.
Then we calculate the digit sum of each group: 3 + 4 + 6 = 13, 5 = 5.
So, s becomes “13” + “5” = “135” after second round.
Now, s.length <= k, so we return “135” as the answer.

Example 2:
Input: s = “00000000”, k = 3
Output: “000”
Explanation:
We divide s into “000”, “000”, and “00”.
Then we calculate the digit sum of each group: 0 + 0 + 0 = 0, 0 + 0 + 0 = 0, and 0 + 0 = 0.
s becomes “0” + “0” + “0” = “000”, whose length is equal to k, so we return “000”.

1 <= s.length <= 100
2 <= k <= 100
s consists of digits only.

A

Separate string into groups by mod(%), add all the numbers and replace the original one with the calculated result. Loop until the length of the digits is smaller or equal to k.

func digitSum(s string, k int) string {
	for len(s) > k {
		var newString string
		var currentGroup string
		for i := 0; i < len(s); i++ {
			if i%k != 0 {
				currentGroup += string(s[i])
			} else {
				if len(currentGroup) != 0 {
					newString += add(currentGroup)
				}
				currentGroup = string(s[i])
			}
		}

		newString += add(currentGroup)
		s = newString
	}

	return s
}

func add(sGroup string) string {
	var result int
    for i := 0; i < len(sGroup); i++ {
        num, _ := strconv.Atoi(string(sGroup[i]))
        result += num
    }
    return strconv.Itoa(result)
}
82
Q

@678. Valid Parenthesis String

Given a string s containing only three types of characters: ‘(‘, ‘)’ and ‘*’, return true if s is valid.

The following rules define a valid string:

Any left parenthesis ‘(‘ must have a corresponding right parenthesis ‘)’.
Any right parenthesis ‘)’ must have a corresponding left parenthesis ‘(‘.
Left parenthesis ‘(‘ must go before the corresponding right parenthesis ‘)’.
‘*’ could be treated as a single right parenthesis ‘)’ or a single left parenthesis ‘(‘ or an empty string “”.

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

Example 2:
Input: s = “(*)”
Output: true

Example 3:
Input: s = “(*))”
Output: true

  • 1 <= s.length <= 100
  • s[i] is ‘(‘, ‘)’ or ‘*’
A

Create a stack that stores the location of idle brackets. During the first loop, remove from stackLeft when encounter right bracket; If length of stackLeft is 0, append right bracket location to stackRight. At the second loop, check the location of the asterisk and pop from stacks. Asterisk location should be smaller than the head of stackLeft, and should be greater than the head of stackRight.

At the end, both stack should be empty.

func checkValidString(s string) bool {
    // Stack that stores the location of idle brackets. 
	stackLeft := make([]int, 0)
	stackRight := make([]int, 0)

	for i, ch := range s {
		if ch == '(' {
			stackLeft = append(stackLeft, i)
		}

		if ch == ')' {
			if len(stackLeft) > 0 {
				stackLeft = stackLeft[:len(stackLeft)-1]
			} else {
				stackRight = append(stackRight, i)
			}
		}
	}

	if len(stackLeft) > 0 || len(stackRight) > 0 {
		for i := len(s) - 1; i >= 0; i-- {
			if s[i] == '*' {
				if len(stackLeft) > 0 && i > stackLeft[len(stackLeft)-1] {
					//    12   27
					//    (    *  => can pop
					// Pop from stack left if current i is greater than where the left paranthesis happen.
					stackLeft = stackLeft[:len(stackLeft)-1]
				} else if len(stackRight) > 0 && i < stackRight[len(stackRight)-1] {
					//    12   27
					//    *    )  => can pop
					// Pop from stack right if current i is smaller than where the left paranthesis happen.
					stackRight = stackRight[:len(stackRight)-1]
				}

				if len(stackLeft) == 0 && len(stackRight) == 0 {
					break
				}
			}
		}
	}

	return len(stackLeft) == 0 && len(stackRight) == 0
}
83
Q

@1480. Running Sum of 1D array

Given an array nums. We define a running sum of an array as runningSum[i] = sum(nums[0]…nums[i]).

Return the running sum of nums.

Example 1:
Input: nums = [1,2,3,4]
Output: [1,3,6,10]
Explanation: Running sum is obtained as follows: [1, 1+2, 1+2+3, 1+2+3+4].

Example 2:
Input: nums = [1,1,1,1,1]
Output: [1,2,3,4,5]
Explanation: Running sum is obtained as follows: [1, 1+1, 1+1+1, 1+1+1+1, 1+1+1+1+1].

Example 3:
Input: nums = [3,1,2,10,1]
Output: [3,4,6,16,17]

1 <= nums.length <= 1000
-10^6 <= nums[i] <= 10^6

A

Dynamic Programming.

func runningSum(nums []int) []int {
    dpTable := make([]int, len(nums))
    dpTable[0] = nums[0]
    for i := 1; i < len(nums); i++ {
        dpTable[i] = nums[i] + dpTable[i - 1]
    }

    return dpTable
}
84
Q

@338. Counting Bits

Given an integer n, return an array ans of length n + 1 such that for each i (0 <= i <= n), ans[i] is the number of 1’s in the binary representation of i.

Example 1:

Input: n = 2
Output: [0,1,1]
Explanation:
0 –> 0
1 –> 1
2 –> 10
Example 2:

Input: n = 5
Output: [0,1,1,2,1,2]
Explanation:
0 –> 0
1 –> 1
2 –> 10
3 –> 11
4 –> 100
5 –> 101

0 <= n <= 10^5

A
  • Use the AND operator. Anything AND with 1(0001) returns 1(0001) if the right most bit is 1, else 0.
func countBits(n int) []int {
    ones := make([]int, n + 1)

    for n != 0 {
        var count int
        for k := n; k > 0; k >>= 1 {
            count += int(k & 1)
        }
        ones[n] = count 
        n--        
    }

    return ones
}
  • Use dynamic programming. The idea here is to use the number of 1’s in i&raquo_space; 1 (i.e., i divided by 2) and the last bit in i to find the number of 1’s in i.

Initialization: Create an array ans of length n + 1, initialized with zeros.
Main Algorithm: Iterate from 1 to n, and for each i, set ans[i] = ans[i&raquo_space; 1] + (i & 1).

0(0000), 1(0001), 2(0010), 3(0011), 4(0100), 5(0101), 6(0110)

5(0101) = 2(010) + last bit (i & 1)
6(0110) = 3(011) + lastbit (i & 1)

func countBits(n int) []int {
    ones := make([]int, n + 1)

    for i := 1; i <= n; i++ {
        ones[i] = ones[i>>1] + (i & 1)
    }

    return ones
}
85
Q

@190. Reverse Bit

Reverse bits of a given 32 bits unsigned integer.

Note:

Note that in some languages, such as Java, there is no unsigned integer type. In this case, both input and output will be given as a signed integer type. They should not affect your implementation, as the integer’s internal binary representation is the same, whether it is signed or unsigned.
In Java, the compiler represents the signed integers using 2’s complement notation. Therefore, in Example 2 above, the input represents the signed integer -3 and the output represents the signed integer -1073741825.

Example 1:
Input: n = 00000010100101000001111010011100
Output: 964176192 (00111001011110000010100101000000)
Explanation: The input binary string 00000010100101000001111010011100 represents the unsigned integer 43261596, so return 964176192 which its binary representation is 00111001011110000010100101000000.

Example 2:
Input: n = 11111111111111111111111111111101
Output: 3221225471 (10111111111111111111111111111111)
Explanation: The input binary string 11111111111111111111111111111101 represents the unsigned integer 4294967293, so return 3221225471 which its binary representation is 10111111111111111111111111111111.

The input must be a binary string of length 32

A

Use the OR(|) operator to copy the last bit. Fetch the last bit by the AND(&) operator.
~~~
func reverseBits(num uint32) uint32 {
var reversed uint32

// Have to move 32 times.
for i := 0; i < 32; i++ {
	reversed |= num & 1 // Copy the last bit to 'reversed' last bit.
	num >>= 1           // Discard the last bit.
    if i < 31 { // After we copy the last, we don't want to shift left.
		reversed <<= 1      // Shift 'reversed' left, now we have a placeholder (last bit 0) to write copied last bit to it.
    }
}

return reversed } ~~~
86
Q

@268. Missing Number

Given an array nums containing n distinct numbers in the range [0, n], return the only number in the range that is missing from the array.

Example 1:
Input: nums = [3,0,1]
Output: 2
Explanation: n = 3 since there are 3 numbers, so all numbers are in the range [0,3]. 2 is the missing number in the range since it does not appear in nums.

Example 2:
Input: nums = [0,1]
Output: 2
Explanation: n = 2 since there are 2 numbers, so all numbers are in the range [0,2]. 2 is the missing number in the range since it does not appear in nums.

Example 3:
Input: nums = [9,6,4,2,3,5,7,0,1]
Output: 8
Explanation: n = 9 since there are 9 numbers, so all numbers are in the range [0,9]. 8 is the missing number in the range since it does not appear in nums.

Implement a solution using only O(1) extra space complexity an

n == nums.length
1 <= n <= 10^4
0 <= nums[i] <= n
All the numbers of nums are unique.

A
  • HashMap
  • Utilize the concept of XOR cancelling out each other, and the order doesn’t matter. Start with missing = 0, XOR the original array first, then XOR the entire range. We will have the missing number at the end.

// Cancelling
0001 ^ 0001 = 0000
0010 ^ 0010 = 0010

// XOR 0 with any number is any number.
0000 ^ 0001 = 0001

func missingNumber(nums []int) int {
    size := len(nums)
    var missing int
    // XOR cancels identical numbers.
    for i := 0; i < size; i++ {
        missing ^= nums[i]
    }

    for i := 0; i <= size; i++ {
        missing ^= i
    }

    return missing
}
  • The missing number is ( 等差級數的合 ) - (sum of nums)
    ~~~
    func missingNumber(nums []int) int {
    size := len(nums)sumOfSeries := ((1 + size) * size) / 2
    var sumOfNums int
    for i := 0; i < size; i++ {
    sumOfNums += nums[i]
    }return sumOfSeries - sumOfNums
    }
    ~~~
87
Q

@371. Sum of Two Integers

Given two integers a and b, return the sum of the two integers without using the operators + and -.

Example 1:
Input: a = 1, b = 2
Output: 3

Example 2:
Input: a = 2, b = 3
Output: 5

-1000 <= a, b <= 1000

A

Use XOR for keeping the 1’s, cancelling out the same (1 and 1, 0 and 0). Use AND and Left Shift to calculate the carries. Add the sum and carry until the carry is 0.

func getSum(a int, b int) int {
    var sum, carry int
    for {
        // Four scenarios:
        // 1. Bit in a and b are both 0 => sum = 0
        // 2, 3. Either one of a or b is 1 => sum = 1
        // 4. Bit in a and b are both 1 => sum = 0, carry = 10  
        
        // Use XOR to check the difference.
        sum = a ^ b
        
        // Use AND to get carry, 01 + 01 = 10, which is AND first then shift left.
        carry = (a & b) << 1
        if carry == 0 {
            break
        }

        // We want to add the current sum and carry, thus casting value sum and curry to a and b.
        a, b = sum, carry
    }

    return sum
}
88
Q

@461. Hamming Distance

The Hamming distance between two integers is the number of positions at which the corresponding bits are different.

Given two integers x and y, return the Hamming distance between them.

Example 1:
Input: x = 1, y = 4
Output: 2
Explanation:
1 (0 0 0 1)
4 (0 1 0 0)
↑ ↑
The above arrows point to positions where the corresponding bits are different.

Example 2:
Input: x = 3, y = 1
Output: 1

A

Count the difference between the two integers. Use XOR to get the difference, then count the 1’s by using AND with 0001.

func hammingDistance(x int, y int) int {
    var distance int
    
    diff := x ^ y
    for diff != 0 {
        distance += diff & 1
        diff >>= 1
    }

    return distance
}
89
Q

@693. Binary Number with Alternating Bits

Given a positive integer, check whether it has alternating bits: namely, if two adjacent bits will always have different values.

Example 1:
Input: n = 5
Output: true
Explanation: The binary representation of 5 is: 101

Example 2:
Input: n = 7
Output: false
Explanation: The binary representation of 7 is: 111.

Example 3:
Input: n = 11
Output: false
Explanation: The binary representation of 11 is: 1011.

1 <= n <= 2^31 - 1

A

Use AND with 1 to check the last bit, loop until current == leading (return fasle) or when n == 0.

func hasAlternatingBits(n int) bool {
    leading := n & 1
    n >>= 1

    for n != 0 {
        if (n & 1) == leading {
            return false
        }
        leading = n & 1
        n >>= 1
    }

    return true
}
90
Q

@139. Word Break

Given a string s and a dictionary of strings wordDict, return true if s can be segmented into a space-separated sequence of one or more dictionary words.

Note that the same word in the dictionary may be reused multiple times in the segmentation.

Example 1:

Input: s = “leetcode”, wordDict = [“leet”,”code”]
Output: true
Explanation: Return true because “leetcode” can be segmented as “leet code”.

Example 2:
Input: s = “applepenapple”, wordDict = [“apple”,”pen”]
Output: true
Explanation: Return true because “applepenapple” can be segmented as “apple pen apple”.
Note that you are allowed to reuse a dictionary word.

Example 3:
Input: s = “catsandog”, wordDict = [“cats”,”dog”,”sand”,”and”,”cat”]
Output: false

1 <= s.length <= 300
1 <= wordDict.length <= 1000
1 <= wordDict[i].length <= 20
s and wordDict[i] consist of only lowercase English letters.
All the strings of wordDict are unique.

A

Create a dynamic programming table that has the size len(s) + 1. Set dp[len(s)] = true, meaning that any word that reaches this position by calling dp[len(s)] is a successful word break. Use a decision tree to visualize the process.

func wordBreak(s string, wordDict []string) bool {
    dpTable := make([]bool, len(s) + 1)
    dpTable[len(s)] = true

    // Loop reversely: Bottom Up.
    for i := len(s) - 1; i >= 0; i -- {
        // Decision Tree: Check every word in wordDict.
        for _, word := range wordDict {
            if i + len(word) <= len(s) && s[i: i + len(word)] == word {
                // The segment of the word has a match in the dictionary.
                // 1. neetcode, ["nee"], i = 0 has a match, but i = 4 doesn't have a match. 
                dpTable[i] = dpTable[i + len(word)] // Check whether the rest of the word segment have a match.
            }
            if dpTable[i] {
                break
            } 
        }
    }

    return dpTable[0]
}
91
Q

@7. Reverese Integer

Given a signed 32-bit integer x, return x with its digits reversed. If reversing x causes the value to go outside the signed 32-bit integer range [-231, 231 - 1], then return 0.

Assume the environment does not allow you to store 64-bit integers (signed or unsigned).

Example 1:

Input: x = 123
Output: 321
Example 2:

Input: x = -123
Output: -321
Example 3:

Input: x = 120
Output: 21

-2^31 <= x <= 2^31 - 1

A

Use Mod.

func reverse(x int) int {
    digits := make([]int, 0)

    for x != 0 {
        digits = append(digits, x % 10)
        x /= 10
    }

    var result int
    for i, j := 0, len(digits) - 1; j >= 0; j-- {
        result += digits[i] * int(math.Pow(10, float64(j)))
        i++
    }

    if result > int(math.Pow(2, 31)) - 1 || result < -int(math.Pow(2, 31)) {
        result = 0
    }

    return result
}
92
Q

@50. Pow(x, n)

Implement pow(x, n), which calculates x raised to the power n (i.e., xn).

Example 1:
Input: x = 2.00000, n = 10
Output: 1024.00000

Example 2:
Input: x = 2.10000, n = 3
Output: 9.26100

Example 3:
Input: x = 2.00000, n = -2
Output: 0.25000
Explanation: 2-2 = 1/22 = 1/4 = 0.25

  • -100.0 < x < 100.0
  • -2^31 <= n <= 2^31-1
  • n is an integer.
  • Either x is not zero or n > 0.
  • -10^4 <= x^n <= 10^4
A
  • Use math.Pow() from the standard library.
    ~~~
    func myPow(x float64, n int) float64 {
    return math.Pow(x, float64(n))
    }
    ~~~
  • Use the trait of power.
func myPow(x float64, n int) float64 {
	// Early end.
	if n == 0 || x == 1 {
		return 1
	}

	var negative bool
	if n < 0 {
		negative = true
		n = -n
	}

	result := float64(1)
	for n != 0 {
		if n%2 != 0 {
			n--
            result *= x
            continue
		}
        x *= x
		n >>= 1
	}

	if negative {
		result = 1 / result
	}

	return result
}
93
Q

@1732. Find the Highest Altitude

There is a biker going on a road trip. The road trip consists of n + 1 points at different altitudes. The biker starts his trip on point 0 with altitude equal 0.

You are given an integer array gain of length n where gain[i] is the net gain in altitude between points i​​​​​​ and i + 1 for all (0 <= i < n). Return the highest altitude of a point.

Example 1:

Input: gain = [-5,1,5,0,-7]
Output: 1
Explanation: The altitudes are [0,-5,-4,1,1,-6]. The highest is 1.
Example 2:

Input: gain = [-4,-3,-2,-1,4,3,2]
Output: 0
Explanation: The altitudes are [0,-4,-7,-9,-10,-6,-3,-1]. The highest is 0.

  • n == gain.length
  • 1 <= n <= 100
  • -100 <= gain[i] <= 100
A

Running Sum and Local Max.

func largestAltitude(gain []int) int {
    var largest int

    largest = max(largest, gain[0])
    
    // Running Sum.
    for i := 1; i < len(gain); i++ {
        gain[i] += gain[i-1]
        largest = max(largest, gain[i])
    }

    return largest
}
94
Q

@1456. Maximum Number of Vowels in a SubString of a Given Length

Given a string s and an integer k, return the maximum number of vowel letters in any substring of s with length k.

Vowel letters in English are ‘a’, ‘e’, ‘i’, ‘o’, and ‘u’.

Example 1:

Input: s = “abciiidef”, k = 3
Output: 3
Explanation: The substring “iii” contains 3 vowel letters.
Example 2:

Input: s = “aeiou”, k = 2
Output: 2
Explanation: Any substring of length 2 contains 2 vowels.
Example 3:

Input: s = “leetcode”, k = 3
Output: 2
Explanation: “lee”, “eet” and “ode” contain 2 vowels.

1 <= s.length <= 10^5
s consists of lowercase English letters.
1 <= k <= s.length

A

Sliding Window. Subtract one if head is vowel; add one if tail is vowel. Compare the stored largest vowels and the local.

func maxVowels(s string, k int) int {
    var vowels int
    vowelsMap := map[byte]struct{}{
		'a': struct{}{}, 'e': struct{}{}, 'i': struct{}{}, 'o': struct{}{}, 'u': struct{}{},
	}

    for i := 0; i < k; i++ {
        _, ok := vowelsMap[s[i]]
        if ok {
            vowels++
        }
    }

    localVowels := vowels
    for i := k; i < len(s); i++ {
        if _, ok := vowelsMap[s[i-k]]; ok {
            localVowels--
        }
        if _, ok := vowelsMap[s[i]]; ok {
            localVowels++
        }

        vowels = max(vowels, localVowels)
    }

    return vowels
}
95
Q

@1679. Max Number of K-Sum Pairs

You are given an integer array nums and an integer k.

In one operation, you can pick two numbers from the array whose sum equals k and remove them from the array.

Return the maximum number of operations you can perform on the array.

Example 1:
Input: nums = [1,2,3,4], k = 5
Output: 2
Explanation: Starting with nums = [1,2,3,4]:
- Remove numbers 1 and 4, then nums = [2,3]
- Remove numbers 2 and 3, then nums = []
There are no more pairs that sum up to 5, hence a total of 2 operations.

Example 2:
Input: nums = [3,1,3,4,3], k = 6
Output: 1
Explanation: Starting with nums = [3,1,3,4,3]:
- Remove the first two 3’s, then nums = [1,4,3]
There are no more pairs that sum up to 6, hence a total of 1 operation.

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

Two Pointers. Sort the array first, pick from the head and the tail. Compare the sum of the head and the tail. Add 1 to pairs if the sum is equal to k.
~~~
func maxOperations(nums []int, k int) int {
sort.Ints(nums)

var pairs int
i, j := 0, len(nums) - 1
for i < j {
    sum := nums[i] + nums[j]
    switch {
    case sum > k:
        j--
    case sum < k:
        i++
    default:
        pairs++
        i++
        j--
    }
}

return pairs } ~~~
96
Q

@2390. Removing Stars From a String

You are given a string s, which contains stars *.

In one operation, you can:

Choose a star in s.
Remove the closest non-star character to its left, as well as remove the star itself.
Return the string after all stars have been removed.

Note:

The input will be generated such that the operation is always possible.
It can be shown that the resulting string will always be unique.

Example 1:
Input: s = “leetcode”
Output: “lecoe”
Explanation: Performing the removals from left to right:
- The closest character to the 1st star is ‘t’ in “leet**cod
e”. s becomes “leecode”.
- The closest character to the 2nd star is ‘e’ in “leecode”. s becomes “lecode”.
- The closest character to the 3rd star is ‘d’ in “lecod
e”. s becomes “lecoe”.
There are no more stars, so we return “lecoe”.

Example 2:
Input: s = “erase*****”
Output: “”
Explanation: The entire string is removed, so we return an empty string.

  • 1 <= s.length <= 105
  • s consists of lowercase English letters and stars *.
  • The operation above can be performed on s.
A

Use a stack. Push when the character isn’t a star, otherwise pop from it.

func removeStars(s string) string {
    stack := make([]byte, 0)

    // Push to stack when the char is a letter.
    // Pop from the stack when the char is a '*'.

    for i := range s {
        switch s[i]{
        case '*':
            stack = stack[:len(stack) - 1]
        default:
            stack = append(stack, s[i])
        }
    }

    // Join the byte array.
    return string(stack)
}
97
Q

@605. Can place flower

You have a long flowerbed in which some of the plots are planted, and some are not. However, flowers cannot be planted in adjacent plots.

Given an integer array flowerbed containing 0’s and 1’s, where 0 means empty and 1 means not empty, and an integer n, return true if n new flowers can be planted in the flowerbed without violating the no-adjacent-flowers rule and false otherwise.

Example 1:

Input: flowerbed = [1,0,0,0,1], n = 1
Output: true
Example 2:

Input: flowerbed = [1,0,0,0,1], n = 2
Output: false

  • 1 <= flowerbed.length <= 2 * 10^4
  • flowerbed[i] is 0 or 1.
  • There are no two adjacent flowers in flowerbed.
  • 0 <= n <= flowerbed.length
A

Loop through the array in place. Change the flower that fits the condition accordingly.

func canPlaceFlowers(flowerbed []int, n int) bool {
    if len(flowerbed) == 1 {
        if n > 0 && flowerbed[0] == 0 {
            flowerbed[0] = 1
            n-- 
        }
    }

    if len(flowerbed) > 1 {
        if flowerbed[0] == 0 && flowerbed[1] == 0 {
            flowerbed[0] = 1
            n--
        }
    }

    for i := 1; i < len(flowerbed) - 1; i++ {
        switch flowerbed[i - 1]{
        case 0:
            if flowerbed[i] == 0 && flowerbed[i+1] == 0 {
                flowerbed[i] = 1
                n--
            }
        }
    }

    if len(flowerbed) > 1 {
        if flowerbed[len(flowerbed) - 1] == 0 && flowerbed[len(flowerbed) - 2] == 0 {
            flowerbed[len(flowerbed) - 1] = 1
            n--
        }
    }
    
    return n <= 0
}
98
Q

@933. Number of Recent Calls

You have a RecentCounter class which counts the number of recent requests within a certain time frame.

Implement the RecentCounter class:

RecentCounter() Initializes the counter with zero recent requests.
int ping(int t) Adds a new request at time t, where t represents some time in milliseconds, and returns the number of requests that has happened in the past 3000 milliseconds (including the new request). Specifically, return the number of requests that have happened in the inclusive range [t - 3000, t].
It is guaranteed that every call to ping uses a strictly larger value of t than the previous call.

Example 1:
Input
[“RecentCounter”, “ping”, “ping”, “ping”, “ping”]
[[], [1], [100], [3001], [3002]]
Output
[null, 1, 2, 3, 3]

Explanation
RecentCounter recentCounter = new RecentCounter();
recentCounter.ping(1); // requests = [1], range is [-2999,1], return 1
recentCounter.ping(100); // requests = [1, 100], range is [-2900,100], return 2
recentCounter.ping(3001); // requests = [1, 100, 3001], range is [1,3001], return 3
recentCounter.ping(3002); // requests = [1, 100, 3001, 3002], range is [2,3002], return 3

1 <= t <= 10^9
Each test case will call ping with strictly increasing values of t.
At most 104 calls will be made to ping.

A

Implement a queue.
~~~
type RecentCounter struct {
Upper int
Lower int
Queue []int
Head int
}

func Constructor() RecentCounter {
return RecentCounter{
Queue: make([]int, 0),
}
}

func (this *RecentCounter) Ping(t int) int {
// When there’s nothing in queue.
if len(this.Queue) == 0 {
this.Queue = append(this.Queue, t)
this.Upper = t
this.Lower = t-3000
this.Head = 0
return 1
}

this.Queue = append(this.Queue, t)
this.Upper = t
this.Lower = t-3000

head := this.Head
for i := head; i < len(this.Queue); i++ {
    if this.Queue[i] < this.Lower {
        this.Head++
    }
}

return len(this.Queue[this.Head:]) }

/**
* Your RecentCounter object will be instantiated and called as such:
* obj := Constructor();
* param_1 := obj.Ping(t);
*/
~~~

99
Q

@901. Online Stock

Design an algorithm that collects daily price quotes for some stock and returns the span of that stock’s price for the current day.

The span of the stock’s price in one day is the maximum number of consecutive days (starting from that day and going backward) for which the stock price was less than or equal to the price of that day.

For example, if the prices of the stock in the last four days is [7,2,1,2] and the price of the stock today is 2, then the span of today is 4 because starting from today, the price of the stock was less than or equal 2 for 4 consecutive days.
Also, if the prices of the stock in the last four days is [7,34,1,2] and the price of the stock today is 8, then the span of today is 3 because starting from today, the price of the stock was less than or equal 8 for 3 consecutive days.
Implement the StockSpanner class:

StockSpanner() Initializes the object of the class.
int next(int price) Returns the span of the stock’s price given that today’s price is price.

Example 1:
Input
[“StockSpanner”, “next”, “next”, “next”, “next”, “next”, “next”, “next”]
[[], [100], [80], [60], [70], [60], [75], [85]]
Output
[null, 1, 1, 1, 2, 1, 4, 6]

Explanation
StockSpanner stockSpanner = new StockSpanner();
stockSpanner.next(100); // return 1
stockSpanner.next(80); // return 1
stockSpanner.next(60); // return 1
stockSpanner.next(70); // return 2
stockSpanner.next(60); // return 1
stockSpanner.next(75); // return 4, because the last 4 prices (including today’s price of 75) were less than or equal to today’s price.
stockSpanner.next(85); // return 6

  • 1 <= price <= 105
  • At most 104 calls will be made to next
A

Dynamic Programming and Monotonic Decreasing Stack. If a price is greater or equal to the tail of the monotonic decreasing stack, it inherits the span from the tail.

type StockSpanner struct {
    Price []int
    Span []int
}

func Constructor() StockSpanner {
    return StockSpanner{
        Price: make([]int, 0),
        Span: make([]int, 0),
    }
}

func (this *StockSpanner) Next(price int) int {
    span := 1
    if len(this.Price) == 0 {
        this.Price = append(this.Price, price)
        this.Span = append(this.Span, span)
        return span
    }

    // When the current price is greater than the last element in the montonic decreasing stack, 
    // add the previous stored span to the current and pop the previous.
    for len(this.Price) > 0 && price >= this.Price[len(this.Price) - 1] {
        // This is what is important.
        // When the price is greater than the last price, the span is inherited.
        span += this.Span[len(this.Span) - 1]

        this.Price = this.Price[:len(this.Price) - 1]
        this.Span = this.Span[:len(this.Span) - 1]
    }

    this.Price = append(this.Price, price)
    this.Span = append(this.Span, span)

    return span
}
100
Q

@328. Odd Even List

Given the head of a singly linked list, group all the nodes with odd indices together followed by the nodes with even indices, and return the reordered list.

The first node is considered odd, and the second node is even, and so on.

Note that the relative order inside both the even and odd groups should remain as it was in the input.

You must solve the problem in O(1) extra space complexity and O(n) time complexity.

Example 1:
Input: head = [1,2,3,4,5]
Output: [1,3,5,2,4]

Example 2:
Input: head = [2,1,3,5,6,4,7]
Output: [2,3,6,7,1,5,4]

  • The number of nodes in the linked list is in the range [0, 10^4].
  • -10^6 <= Node.val <= 10^6
A

Store the second node. Jump to next.next for odd and even nodes in one loop. Cast the second node to the last node of the odd node. Remeber to set the next of temp2 to nil, otherwise there will be cases where it still point to an odd node.

func oddEvenList(head *ListNode) *ListNode {
    if head == nil {
        return nil
    }

	temp := head

	second := temp.Next
	temp2 := second

    for temp.Next != nil && temp2.Next != nil {
        if temp.Next != nil && temp.Next.Next != nil {
            temp.Next = temp.Next.Next
            temp = temp.Next
        }

        if temp2.Next != nil && temp2.Next.Next != nil {
            temp2.Next = temp2.Next.Next
            temp2 = temp2.Next
        }
    }

	temp.Next = second
    // Remember to cast the next of temp2 to nil, otherwise there will be cases where it still point to an odd node.
    if temp2 != nil {
        temp2.Next = nil 
    }
	return head
}
101
Q

@643. Maximum Average Subarray l

You are given an integer array nums consisting of n elements, and an integer k.

Find a contiguous subarray whose length is equal to k that has the maximum average value and return this value. Any answer with a calculation error less than 10-5 will be accepted.

Example 1:
Input: nums = [1,12,-5,-6,50,3], k = 4
Output: 12.75000
Explanation: Maximum average is (12 - 5 - 6 + 50) / 4 = 51 / 4 = 12.75

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

  • n == nums.length
  • 1 <= k <= n <= 105
  • -10^4 <= nums[i] <= 10^4
A

Sliding Window.
~~~
func findMaxAverage(nums []int, k int) float64 {
var maxSum int
// Sliding window.
for i := 0; i < k; i++ {
maxSum += nums[i]
}

localSum := maxSum
for i := k; i < len(nums); i++ {
    localSum = localSum - nums[i-k] + nums[i]
    maxSum = max(maxSum, localSum)
}

return float64(maxSum) / float64(k) } ~~~
102
Q

@2215. Find the Difference of Two Arrays

Given two 0-indexed integer arrays nums1 and nums2, return a list answer of size 2 where:

answer[0] is a list of all distinct integers in nums1 which are not present in nums2.
answer[1] is a list of all distinct integers in nums2 which are not present in nums1.
Note that the integers in the lists may be returned in any order.

Example 1:
Input: nums1 = [1,2,3], nums2 = [2,4,6]
Output: [[1,3],[4,6]]
Explanation:
For nums1, nums1[1] = 2 is present at index 0 of nums2, whereas nums1[0] = 1 and nums1[2] = 3 are not present in nums2. Therefore, answer[0] = [1,3].
For nums2, nums2[0] = 2 is present at index 1 of nums1, whereas nums2[1] = 4 and nums2[2] = 6 are not present in nums2. Therefore, answer[1] = [4,6].

Example 2:
Input: nums1 = [1,2,3,3], nums2 = [1,1,2,2]
Output: [[3],[]]
Explanation:
For nums1, nums1[2] and nums1[3] are not present in nums2. Since nums1[2] == nums1[3], their value is only included once and answer[0] = [3].
Every integer in nums2 is present in nums1. Therefore, answer[1] = [].

  • 1 <= nums1.length, nums2.length <= 1000
  • -1000 <= nums1[i], nums2[i] <= 1000
A
  • Use integer array as hash set (Fast).
func findDifference(nums1 []int, nums2 []int) [][]int {
    set1, set2 := make([]int, 2001), make([]int, 2001)

    for _, num := range nums1 {
        set1[num+1000]++
    }

    for _, num := range nums2 {
        set2[num+1000]++
    }

    ans1, ans2 := make([]int, 0), make([]int, 0)
    for i := 0; i < len(set1); i++ {
        if set1[i] != 0 && set2[i] == 0 {
            ans1 = append(ans1, i - 1000)
        }

        if set1[i] == 0 && set2[i] != 0 {
            ans2 = append(ans2, i - 1000)
        }
    }

    return [][]int{ans1, ans2}
}
  • Stupid hashmap way ( Slow ).
    ~~~
    func findDifference(nums1 []int, nums2 []int) [][]int {
    set1, set2 := make(map[int]int), make(map[int]int)for _, num := range nums1 {
    if _, ok := set1[num]; !ok {
    set1[num] = 0
    }
    set1[num]++
    }for _, num := range nums2 {
    if _, ok := set2[num]; !ok {
    set2[num] = 0
    }
      set2[num]++   }
    ansSet1 := make(map[int]struct{})
    for _, num := range nums1 {
    if _, ok := set2[num]; !ok {
    ansSet1[num] = struct{}{}
    }
    }ansSet2 := make(map[int]struct{})
    for _, num := range nums2 {
    if _, ok := set1[num]; !ok {
    ansSet2[num] = struct{}{}
    }
    }ans1, ans2 := make([]int, 0), make([]int, 0)
    for k := range ansSet1 {
    ans1 = append(ans1, k)
    }for k := range ansSet2 {
    ans2 = append(ans2, k)
    }return [][]int{ans1, ans2}
    }
    ~~~
103
Q

@735. Asteroid Collision

We are given an array asteroids of integers representing asteroids in a row.

For each asteroid, the absolute value represents its size, and the sign represents its direction (positive meaning right, negative meaning left). Each asteroid moves at the same speed.

Find out the state of the asteroids after all collisions. If two asteroids meet, the smaller one will explode. If both are the same size, both will explode. Two asteroids moving in the same direction will never meet.

Example 1:

Input: asteroids = [5,10,-5]
Output: [5,10]
Explanation: The 10 and -5 collide resulting in 10. The 5 and 10 never collide.
Example 2:

Input: asteroids = [8,-8]
Output: []
Explanation: The 8 and -8 collide exploding each other.
Example 3:

Input: asteroids = [10,2,-5]
Output: [10]
Explanation: The 2 and -5 collide resulting in -5. The 10 and -5 collide resulting in 10.

  • 2 <= asteroids.length <= 10^4
  • -1000 <= asteroids[i] <= 1000
  • asteroids[i] != 0
A

Create a stack. Append to the stack whenever the stack is empty or the newcomer is positive. If the asteroid is negative, pop if condition meet. Notice that the asteroid might pop all the element in the stack, remember to append to stack when all pops are done.

func asteroidCollision(asteroids []int) []int {
	stack := make([]int, 0)

	for _, asteroid := range asteroids {
		if len(stack) == 0 || asteroid > 0 {
			// Append both positive or negative to stack when nothings in it or the stack is homogeneous (all postive, no collision).
			stack = append(stack, asteroid)
			continue
		}

		// Collides - when newcomer is negative.
        for len(stack) > 0 && stack[len(stack) - 1] > 0 && asteroid < 0 {
            switch {
            case asteroid + stack[len(stack) - 1] == 0:
                // Pop and break.
                stack = stack[:len(stack) - 1]
                asteroid = 0
                break
            case asteroid + stack[len(stack) - 1] > 0:
                asteroid = 0
                break
            case asteroid + stack[len(stack) - 1] < 0:
                // Pop.
                stack = stack[:len(stack) - 1]
            }
        }

        if asteroid != 0 {
            stack = append(stack, asteroid)
        }
	}

	return stack
} 
104
Q

@872. Leaf-Similar Tree

Consider all the leaves of a binary tree, from left to right order, the values of those leaves form a leaf value sequence.

For example, in the given tree above, the leaf value sequence is (6, 7, 4, 9, 8).

Two binary trees are considered leaf-similar if their leaf value sequence is the same.

Return true if and only if the two given trees with head nodes root1 and root2 are leaf-similar.

Example 1:
Input: root1 = [3,5,1,6,2,9,8,null,null,7,4], root2 = [3,5,1,6,7,4,2,null,null,null,null,null,null,9,8]
Output: true

Example 2:
Input: root1 = [1,2,3], root2 = [1,3,2]
Output: false

  • The number of nodes in each tree will be in the range [1, 200].
  • Both of the given trees will have values in the range [0, 200].
A

PreOrder traversal, root-> left -> right. Check Left then check right.

func leafSimilar(root1 *TreeNode, root2 *TreeNode) bool {
    leaves1, leaves2 := getLeaves(root1), getLeaves(root2)
    return compareLeaves(leaves1, leaves2)
}

func getLeaves(root *TreeNode) []int {
    leaves := make([]int, 0)

    var dfs func(node *TreeNode)
    dfs = func(node *TreeNode) {
        if node == nil {
            return
        } 

        if node.Left == nil && node.Right == nil {
            leaves = append(leaves, node.Val)
            return 
        }

        if node.Left != nil {
            dfs(node.Left)
        }

        if node.Right != nil {
            dfs(node.Right)
        }
    }

    dfs(root)
    return leaves
}

func compareLeaves(leaves1, leaves2 []int) bool {
    if len(leaves1) != len(leaves2) {
        return false
    }

    for i := 0; i < len(leaves1); i++ {
        if leaves1[i] != leaves2[i] {
            return false
        }
    }

    return true
}
105
Q

@841. Keys and Rooms

There are n rooms labeled from 0 to n - 1 and all the rooms are locked except for room 0. Your goal is to visit all the rooms. However, you cannot enter a locked room without having its key.

When you visit a room, you may find a set of distinct keys in it. Each key has a number on it, denoting which room it unlocks, and you can take all of them with you to unlock the other rooms.

Given an array rooms where rooms[i] is the set of keys that you can obtain if you visited room i, return true if you can visit all the rooms, or false otherwise.

Example 1:
Input: rooms = [[1],[2],[3],[]]
Output: true
Explanation:
We visit room 0 and pick up key 1.
We then visit room 1 and pick up key 2.
We then visit room 2 and pick up key 3.
We then visit room 3.
Since we were able to visit every room, we return true.

Example 2:
Input: rooms = [[1,3],[3,0,1],[2],[0]]
Output: false
Explanation: We can not enter room number 2 since the only key that unlocks it is in that room.

  • n == rooms.length
  • 2 <= n <= 1000
  • 0 <= rooms[i].length <= 1000
  • 1 <= sum(rooms[i].length) <= 3000
  • 0 <= rooms[i][j] < n
  • All the values of rooms[i] are unique.
A

Backtracking. Return if we already visited the room. Otherwise loop through all the keys and visit the room. Keep track of all the rooms that are visited.

Go through the visited array, return false if there’s room that isn’t visited.

func canVisitAllRooms(rooms [][]int) bool {
	visited := make([]int, len(rooms))

	var visit func(roomIdx int)
	visit = func(roomIdx int) {
		if visited[roomIdx] == 1 {
			return
		}

		visited[roomIdx] = 1

		for _, nextRoom := range rooms[roomIdx] {
			visit(nextRoom)
		}
	}

	visit(0)

	for _, beenTo := range visited {
		if beenTo == 0 {
			return false
		}
	}

	return true
}
106
Q

@701. Insert Into a Binary Search Tree

You are given the root node of a binary search tree (BST) and a value to insert into the tree. Return the root node of the BST after the insertion. It is guaranteed that the new value does not exist in the original BST.

Notice that there may exist multiple valid ways for the insertion, as long as the tree remains a BST after insertion. You can return any of them.

Example 1:
Input: root = [4,2,7,1,3], val = 5
Output: [4,2,7,1,3,5]
Explanation: Another accepted tree is:

Example 2:
Input: root = [40,20,60,10,30,50,70], val = 25
Output: [40,20,60,10,30,50,70,null,null,25]

Example 3:
Input: root = [4,2,7,1,3,null,null,null,null,null,null], val = 5
Output: [4,2,7,1,3,5]

  • The number of nodes in the tree will be in the range [0, 10^4].
  • -10^8 <= Node.val <= 10^8
  • All the values Node.val are unique.
  • -10^8 <= val <= 10^8
  • It’s guaranteed that val does not exist in the original BST.
A

Maintain the BST property.
* Iterative
~~~
func insertIntoBST(root *TreeNode, val int) *TreeNode {
// Empty BST.
if root == nil {
return &TreeNode {Val: val}
}

temp := root 

for {
    if val < temp.Val {
        if temp.Left == nil {
            temp.Left = &TreeNode{Val:val}
            break
        } else {
            temp = temp.Left
        }
    }

    if val > temp.Val {
        if temp.Right == nil {
            temp.Right = &TreeNode{Val: val}
            break
        } else {
            temp = temp.Right
        }
    }
}

return root } ~~~
  • Recursive
    ~~~
    func insertIntoBST(root *TreeNode, val int) *TreeNode {
    // Empty BST.
    if root == nil {
    return &TreeNode {Val: val}
    }if val < root.Val {
    root.Left = insertIntoBST(root.Left, val)
    } else {
    root.Right = insertIntoBST(root.Right, val)
    }return root
    }
    ~~~
107
Q

@283. Move Zeros

Given an integer array nums, move all 0’s to the end of it while maintaining the relative order of the non-zero elements.

Note that you must do this in-place without making a copy of the array.

Example 1:
Input: nums = [0,1,0,3,12]
Output: [1,3,12,0,0]

Example 2:
Input: nums = [0]
Output: [0]

Follow up: Could you minimize the total number of operations done?

  • 1 <= nums.length <= 10^4
  • -2^31 <= nums[i] <= 2^31 - 1
A
  • Swap in-place (slow).
    ~~~
    func moveZeroes(nums []int) {
    // Swapping in place?
    // Swap with a non-zero element when looping in place.for i := 0; i < len(nums); i++ {
    if nums[i] == 0 {
    for j := i + 1; j < len(nums); j++ {
    if nums[j] != 0 {
    nums[i], nums[j] = nums[j], nums[i]
    break
    }
    }
    }
    }
    }
    ~~~
  • Keep a zero pointer and swap in-place (fast).
    ~~~
    func moveZeroes(nums []int) {
    zeroPointer := 0
    for idx, num := range nums {
    if num != 0 {
    nums[idx], nums[zeroPointer] = nums[zeroPointer], nums[idx]
    zeroPointer++
    }
    }
    }
    ~~~
108
Q

@2095. Delete the Middle Node of a Linked List

You are given the head of a linked list. Delete the middle node, and return the head of the modified linked list.

The middle node of a linked list of size n is the ⌊n / 2⌋th node from the start using 0-based indexing, where ⌊x⌋ denotes the largest integer less than or equal to x.

For n = 1, 2, 3, 4, and 5, the middle nodes are 0, 1, 1, 2, and 2, respectively.

Example 1:
Input: head = [1,3,4,7,1,2,6]
Output: [1,3,4,1,2,6]
Explanation:
The above figure represents the given linked list. The indices of the nodes are written below.
Since n = 7, node 3 with value 7 is the middle node, which is marked in red.
We return the new list after removing this node.

Example 2:
Input: head = [1,2,3,4]
Output: [1,2,4]
Explanation:
The above figure represents the given linked list.
For n = 4, node 2 with value 3 is the middle node, which is marked in red.

Example 3:
Input: head = [2,1]
Output: [2]
Explanation:
The above figure represents the given linked list.
For n = 2, node 1 with value 1 is the middle node, which is marked in red.
Node 0 with value 2 is the only node remaining after removing node 1.

  • The number of nodes in the list is in the range [1, 10^5].
  • 1 <= Node.val <= 10^5
A

Find the node before the middle and change the next node to the next.next.
Find the middle with the below ways:
* Tortoise and the Hare (Fast Slow pointer)

func deleteMiddle(head *ListNode) *ListNode {
    if head.Next == nil {
        return nil
    }

    slow, fast := head, head.Next.Next

    for fast != nil && fast.Next != nil {
        slow = slow.Next
        fast = fast.Next.Next
    }

    slow.Next = slow.Next.Next

    return head
}
  • Count length
    ~~~
    func deleteMiddle(head *ListNode) *ListNode {
    var length int
    // Count length, get the middle index.
    temp := head
    for temp != nil {
    length++
    temp = temp.Next
    }if length == 1 {
    return nil
    }temp = head
    // Perform delete on the middle index.
    count := 0
    for count != (length / 2) - 1 {
    temp = temp.Next
    count++
    }temp.Next = temp.Next.Nextreturn head
    }
    ~~~
109
Q

@1161. Maximum Level Sum of a Binary Tree

Given the root of a binary tree, the level of its root is 1, the level of its children is 2, and so on.

Return the smallest level x such that the sum of all the values of nodes at level x is maximal.

Example 1:
Input: root = [1,7,0,7,-8,null,null]
Output: 2
Explanation:
Level 1 sum = 1.
Level 2 sum = 7 + 0 = 7.
Level 3 sum = 7 + -8 = -1.
So we return the level with the maximum sum which is level 2.

Example 2:
Input: root = [989,null,10250,98693,-89388,null,null,null,-32127]
Output: 2

  • The number of nodes in the tree is in the range [1, 10^4].
  • -10^5 <= Node.val <= 10^5
A

Breadth First Search. Use the queue length to keep track of the nodes in a level. Only update the maxLevel when a sum greater than maxLevelSum occurs. When a maxSum occurs the second time, don’t do anything: we already have a lower level that has a maxSum.

func maxLevelSum(root *TreeNode) int {
    maxLevelSum := root.Val
    maxLevel := 1
    queue := []*TreeNode{root}
    
    currLevel := 0
    levelNodes := len(queue)
    for len(queue) != 0 {
        currLevel++
        localLevelSum := 0
        for i := 0; i < levelNodes; i++ {
            localLevelSum += queue[0].Val

            // Append children to the queue.
            if queue[0].Left != nil {
                queue = append(queue, queue[0].Left)
            }

            if queue[0].Right != nil {
                queue = append(queue, queue[0].Right)
            }
            // Pop current node from the queue.
            queue = queue[1:]
        }

        // Only update when localLevelSum > maxLevelSum.
        if localLevelSum > maxLevelSum {
            maxLevelSum = localLevelSum
            maxLevel = currLevel
        }

        // We reached the next level.
        levelNodes = len(queue)
    }
    
    return maxLevel
}
110
Q

@450. Delete node in BST

Given a root node reference of a BST and a key, delete the node with the given key in the BST. Return the root node reference (possibly updated) of the BST.

Basically, the deletion can be divided into two stages:

Search for a node to remove.
If the node is found, delete the node.

Example 1:
Input: root = [5,3,6,2,4,null,7], key = 3
Output: [5,4,6,2,null,null,7]
Explanation: Given key to delete is 3. So we find the node with value 3 and delete it.
One valid answer is [5,4,6,2,null,null,7], shown in the above BST.
Please notice that another valid answer is [5,2,6,null,4,null,7] and it’s also accepted.

Example 2:
Input: root = [5,3,6,2,4,null,7], key = 0
Output: [5,3,6,2,4,null,7]
Explanation: The tree does not contain a node with value = 0.

Example 3:
Input: root = [], key = 0
Output: []

  • The number of nodes in the tree is in the range [0, 10^4].
  • -10^5 <= Node.val <= 10^5
  • Each node has a unique value.
  • root is a valid binary search tree.
  • -105 <= key <= 10
    *
A

Find the successor of the node we want to delete. Copy the successor value to the node we want to delete. Traverse the subtree and delete the successor node.

func deleteNode(root *TreeNode, key int) *TreeNode {
    // Case 0, key not found.
    if root == nil {
        return nil
    }

    // Find the node to be deleted
    if key < root.Val {
        root.Left = deleteNode(root.Left, key)
    } else if key > root.Val {
        root.Right = deleteNode(root.Right, key)
    } else {
        // Node found.
        if root.Left == nil {
            return root.Right
        } else if root.Right == nil {
            return root.Left
        }

        // Node with two children: Get the inorder successor (smallest in the right subtree)
        successor := minValueNode(root.Right)

        // Copy the successor value to the current value.
        root.Val = successor.Val

        // The problem is now reduces to the upper case.
        // Now we only have to delete the original successor node in the subtree.
        // This also handles the scenario where there's no children
        root.Right = deleteNode(root.Right, successor.Val)
    }

    return root
}

// Helper function to find the minimum value node in a given BST
func minValueNode(node *TreeNode) *TreeNode {
    current := node
    for current.Left != nil {
        current = current.Left
    }
    return current
}
111
Q

@3162. Find the number of good pairs

You are given 2 integer arrays nums1 and nums2 of lengths n and m respectively. You are also given a positive integer k.

A pair (i, j) is called good if nums1[i] is divisible by nums2[j] * k (0 <= i <= n - 1, 0 <= j <= m - 1).

Return the total number of good pairs.

Example 1:
Input: nums1 = [1,3,4], nums2 = [1,3,4], k = 1

Output: 5

Explanation:

The 5 good pairs are (0, 0), (1, 0), (1, 1), (2, 0), and (2, 2).

Example 2:
Input: nums1 = [1,2,4,12], nums2 = [2,4], k = 3

Output: 2

Explanation:

The 2 good pairs are (3, 0) and (3, 1).

  • 1 <= n, m <= 50
  • 1 <= nums1[i], nums2[j] <= 50
  • 1 <= k <= 50
A

Brute Force.

func numberOfPairs(nums1 []int, nums2 []int, k int) int {
    var count int
    for i := range nums1 {
        for j := range nums2 {
            if nums1[i] % (nums2[j] * k) == 0 {
                count++
            }
        }
    }
    return count
}
112
Q

@3163. String Compression lll

Given a string word, compress it using the following algorithm:

Begin with an empty string comp. While word is not empty, use the following operation:
Remove a maximum length prefix of word made of a single character c repeating at most 9 times.
Append the length of the prefix followed by c to comp.
Return the string comp.

Example 1:
Input: word = “abcde”

Output: “1a1b1c1d1e”

Explanation:

Initially, comp = “”. Apply the operation 5 times, choosing “a”, “b”, “c”, “d”, and “e” as the prefix in each operation.

For each prefix, append “1” followed by the character to comp.

Example 2:
Input: word = “aaaaaaaaaaaaaabb”

Output: “9a5a2b”

Explanation:

Initially, comp = “”. Apply the operation 3 times, choosing “aaaaaaaaa”, “aaaaa”, and “bb” as the prefix in each operation.

For prefix “aaaaaaaaa”, append “9” followed by “a” to comp.
For prefix “aaaaa”, append “5” followed by “a” to comp.
For prefix “bb”, append “2” followed by “b” to comp.

  • 1 <= word.length <= 2 * 10^5
  • word consists only of lowercase English letters.
A

Two Pointers that meets the requirements.

  • Elegant way.
func compressedString(word string) string {
    comp := make([]byte, 0)
    i, j := 0, 0
    for i < len(word) {
        var count int
        for j < len(word) && word[i] == word[j] && count < 9 {
            j++
            count++
        }

        // Append to comp.
        comp = append(comp, []byte(strconv.Itoa(count))[0])
        comp = append(comp, word[i])
        // Update i to j.
        i = j   
    }
    
    return string(comp)
}
  • My Way.
func compressedString(word string) string {
    comp := make([]byte, 0)
    for i := 0; i < len(word); i++ {
        var j int
        start := word[i]
        count := 1
        for j = i + 1; j < len(word); j++ {
            if count == 9 || word[j] != start {
                break
            }
            count++
        }
        
        
        
        // Append to comp.
        comp = append(comp, []byte(strconv.Itoa(count))...)
        comp = append(comp, start)
        // Update i to j.
        i = j - 1   
    }
    
    return string(comp)
}
113
Q

@443. String Compression

Given an array of characters chars, compress it using the following algorithm:

Begin with an empty string s. For each group of consecutive repeating characters in chars:

If the group’s length is 1, append the character to s.
Otherwise, append the character followed by the group’s length.
The compressed string s should not be returned separately, but instead, be stored in the input character array chars. Note that group lengths that are 10 or longer will be split into multiple characters in chars.

After you are done modifying the input array, return the new length of the array.

You must write an algorithm that uses only constant extra space.

Example 1:
Input: chars = [“a”,”a”,”b”,”b”,”c”,”c”,”c”]
Output: Return 6, and the first 6 characters of the input array should be: [“a”,”2”,”b”,”2”,”c”,”3”]
Explanation: The groups are “aa”, “bb”, and “ccc”. This compresses to “a2b2c3”.

Example 2:
Input: chars = [“a”]
Output: Return 1, and the first character of the input array should be: [“a”]
Explanation: The only group is “a”, which remains uncompressed since it’s a single character.

Example 3:
Input: chars = [“a”,”b”,”b”,”b”,”b”,”b”,”b”,”b”,”b”,”b”,”b”,”b”,”b”]
Output: Return 4, and the first 4 characters of the input array should be: [“a”,”b”,”1”,”2”].
Explanation: The groups are “a” and “bbbbbbbbbbbb”. This compresses to “ab12”.

  • 1 <= chars.length <= 2000
  • chars[i] is a lowercase English letter, uppercase English letter, digit, or symbol.
A

Two Pointers. Keep a trace i and a write pointer.
Loop: Count with i and write to the write position until trace i reaches the end of chars.

func compress(chars []byte) int {
    var i, write int
    for i < len(chars) {
        char := chars[i]
        count := 0
        // Count occurrences of the current character
        for i < len(chars) && chars[i] == char {
            i++
            count++
        }
        // Write the character to the write position
        chars[write] = char
        write++
        // If count is more than 1, write the count to the array
        if count > 1 {
            countStr := strconv.Itoa(count)
            for k := 0; k < len(countStr); k++ {
                chars[write] = countStr[k]
                write++
            }
        }
    }
    return write
}
114
Q

@1137. N-th Tribonacci Number

The Tribonacci sequence Tn is defined as follows:

T0 = 0, T1 = 1, T2 = 1, and Tn+3 = Tn + Tn+1 + Tn+2 for n >= 0.

Given n, return the value of Tn.

Example 1:
Input: n = 4
Output: 4
Explanation:
T_3 = 0 + 1 + 1 = 2
T_4 = 1 + 1 + 2 = 4

Example 2:
Input: n = 25
Output: 1389537

  • 0 <= n <= 37
  • The answer is guaranteed to fit within a 32-bit integer, ie. answer <= 2^31 - 1.
A

Dynamic Programming.

func tribonacci(n int) int {
    if n == 0 {
        return 0
    } else if n == 1 || n == 2 {
        return 1
    }
    
    
    dpTable := make([]int, n + 1)
    dpTable[0] = 0
    dpTable[1] = 1
    dpTable[2] = 1

    for i := 3; i <= n; i++ {
        dpTable[i] = dpTable[i - 1] + dpTable[i - 2] + dpTable[i -3]
    }
    
    return dpTable[n]
}
115
Q

@374. Guess Number Higher or Lower

We are playing the Guess Game. The game is as follows:

I pick a number from 1 to n. You have to guess which number I picked.

Every time you guess wrong, I will tell you whether the number I picked is higher or lower than your guess.

You call a pre-defined API int guess(int num), which returns three possible results:

-1: Your guess is higher than the number I picked (i.e. num > pick).
1: Your guess is lower than the number I picked (i.e. num < pick).
0: your guess is equal to the number I picked (i.e. num == pick).
Return the number that I picked.

Example 1:

Input: n = 10, pick = 6
Output: 6
Example 2:

Input: n = 1, pick = 1
Output: 1
Example 3:

Input: n = 2, pick = 1
Output: 1

  • 1 <= n <= 2^31 - 1
  • 1 <= pick <= n
A

Binary Search.

/** 
 * Forward declaration of guess API.
 * @param  num   your guess
 * @return 	     -1 if num is higher than the picked number
 *			      1 if num is lower than the picked number
 *               otherwise return 0
 * func guess(num int) int;
 */

func guessNumber(n int) int {
    i, j := 1, n
    mid := (i + j) / 2

    for i <= j {
        switch guess(mid) {
        case 0:
            return mid
        case 1:
            i = mid + 1
        case -1:
            j = mid - 1
        }
        mid = (i + j) / 2 
    }

    // This will never happen.
    return -1
}
116
Q

@547. Number of Provinces

There are n cities. Some of them are connected, while some are not. If city a is connected directly with city b, and city b is connected directly with city c, then city a is connected indirectly with city c.

A province is a group of directly or indirectly connected cities and no other cities outside of the group.

You are given an n x n matrix isConnected where isConnected[i][j] = 1 if the ith city and the jth city are directly connected, and isConnected[i][j] = 0 otherwise.

Return the total number of provinces.

  • 1 <= n <= 200
  • n == isConnected.length
  • n == isConnected[i].length
  • isConnected[i][j] is 1 or 0.
  • isConnected[i][i] == 1
  • isConnected[i][j] == isConnected[j][i]
A

Depth First Search. Exhaust all connected nodes and store it in a visited table. Add 1 to province when we reached it and haven’t exhaust it from other connected nodes yet ( which means this current node is a tip of one of the provinces).

func findCircleNum(isConnected [][]int) int {
    var provinces int
    visited := make([]int, len(isConnected))

    var exhaust func(provinceIdx int)
    exhaust = func(provinceIdx int){
        if visited[provinceIdx] == 1 {
            return
        }
        
        visited[provinceIdx] = 1

        for connectedProvinceIdx, connected := range isConnected[provinceIdx] {
            if connected == 1 {
                exhaust(connectedProvinceIdx)
            }
        }
    }

    for i := 0; i < len(isConnected); i++ {
        if visited[i] == 0 {
            // Haven't visit yet, the current index is a tip of a new province.
            provinces++
            exhaust(i)
        }
    }

    return provinces
}
117
Q

@700. Search in a Binary Search Tree

You are given the root of a binary search tree (BST) and an integer val.

Find the node in the BST that the node’s value equals val and return the subtree rooted with that node. If such a node does not exist, return null.

Example 1:
Input: root = [4,2,7,1,3], val = 2
Output: [2,1,3]

Example 2:
Input: root = [4,2,7,1,3], val = 5
Output: []

  • The number of nodes in the tree is in the range [1, 5000].
  • 1 <= Node.val <= 10^7
  • root is a binary search tree.
  • 1 <= val <= 10^7
A
  • Recursive
func searchBST(root *TreeNode, val int) *TreeNode {
    if root == nil {
        return nil
    }

    if root.Val == val {
        return root
    } else if val < root.Val {
        return searchBST(root.Left, val)
    } else {
        return searchBST(root.Right, val)
    }
}
  • Iterative
func searchBST(root *TreeNode, val int) *TreeNode {
    temp := root

    for temp != nil {
        if temp.Val == val {
            return temp
        } else if val < temp.Val {
            temp = temp.Left
        } else {
            temp = temp.Right
        }
    }

    return nil
}
118
Q

@394. Decode String

Given an encoded string, return its decoded string.

The encoding rule is: k[encoded_string], where the encoded_string inside the square brackets is being repeated exactly k times. Note that k is guaranteed to be a positive integer.

You may assume that the input string is always valid; there are no extra white spaces, square brackets are well-formed, etc. Furthermore, you may assume that the original data does not contain any digits and that digits are only for those repeat numbers, k. For example, there will not be input like 3a or 2[4].

The test cases are generated so that the length of the output will never exceed 105.

Example 1:

Input: s = “3[a]2[bc]”
Output: “aaabcbc”
Example 2:

Input: s = “3[a2[c]]”
Output: “accaccacc”
Example 3:

Input: s = “2[abc]3[cd]ef”
Output: “abcabccdcdcdef”

  • 1 <= s.length <= 30
  • s consists of lowercase English letters, digits, and square brackets ‘[]’.
  • s is guaranteed to be a valid input.
  • All the integers in s are in the range [1, 300].
A

Stack. Append all chars, pop when encounter ‘]’. Check the chars infront of ‘[’ to get the count.

func decodeString(s string) string {
	stack := make([]byte, 0)

	for i := range s {
		stack = append(stack, s[i])
		if s[i] == ']' {
			// Pop from stack until '['.
			// Find chars
			chars := make([]byte, 0)
			for stack[len(stack)-1] != '[' {
				if stack[len(stack)-1] != ']' {
					chars = append([]byte{stack[len(stack) -1]},chars...)
				}
				stack = stack[:len(stack)-1]
			}

			// Pop '['
			stack = stack[:len(stack)-1]

			// Find count.
            countSlice := make([]byte, 0)
            for len(stack) > 0 && isDigit(stack[len(stack) - 1]) {
                countSlice = append([]byte{stack[len(stack) -1]}, countSlice...)
                stack = stack[:len(stack) - 1]             
            }

            count, _ := strconv.Atoi(string(countSlice))
            for k := 0; k < count; k++ {
                stack = append(stack, chars...)
            }
		}
	}
	return string(stack)
}

func isDigit(char byte) bool {
    return char >= '0' && char <= '9'
}
119
Q

@1372. Longest ZigZag Path in a Binary Tree

You are given the root of a binary tree.

A ZigZag path for a binary tree is defined as follow:

Choose any node in the binary tree and a direction (right or left).
If the current direction is right, move to the right child of the current node; otherwise, move to the left child.
Change the direction from right to left or from left to right.
Repeat the second and third steps until you can’t move in the tree.
Zigzag length is defined as the number of nodes visited - 1. (A single node has a length of 0).

Return the longest ZigZag path contained in that tree.

Example 1:
Input: root = [1,null,1,1,1,null,null,1,1,null,1,null,null,null,1]
Output: 3
Explanation: Longest ZigZag path in blue nodes (right -> left -> right).

Example 2:
Input: root = [1,1,1,null,1,null,null,1,1,null,1]
Output: 4
Explanation: Longest ZigZag path in blue nodes (left -> right -> left -> right).

Example 3:
Input: root = [1]
Output: 0

  • The number of nodes in the tree is in the range [1, 5 * 10^4].
  • 1 <= Node.val <= 100
A

Depth First Search. Count from 0 at every node if they have the same direction. Add 1 to the current zigzag if we’re going on a different direction.

const (
	LEFT  = "left"
	RIGHT = "right"
)

func longestZigZag(root *TreeNode) int {
	var maxZigZag int

	var dfs func(node *TreeNode, currDirection string, currZigZag int)
	dfs = func(node *TreeNode, currDirection string, currZigZag int) {
		if node == nil {
			maxZigZag = max(maxZigZag, currZigZag)
			return
		}

		if currDirection == LEFT {
			dfs(node.Right, RIGHT, currZigZag+1)
            // Same direction not a ZigZag, start counting at zero. 
            dfs(node.Left, LEFT, 0)
		} else if currDirection == RIGHT {
			dfs(node.Left, LEFT, currZigZag+1)

            // Same direction not a ZigZag, start counting at zero. 
    		dfs(node.Right, RIGHT, 0)
        } else {
            // We're at root (where there is no direction).
		    dfs(node.Left, LEFT, 0)
		    dfs(node.Right, RIGHT, 0)
        }
	}

	dfs(root, "", 0)
	return maxZigZag
}
120
Q

@724. Pivot Index

Given an array of integers nums, calculate the pivot index of this array.

The pivot index is the index where the sum of all the numbers strictly to the left of the index is equal to the sum of all the numbers strictly to the index’s right.

If the index is on the left edge of the array, then the left sum is 0 because there are no elements to the left. This also applies to the right edge of the array.

Return the leftmost pivot index. If no such index exists, return -1.

Example 1:
Input: nums = [1,7,3,6,5,6]
Output: 3
Explanation:
The pivot index is 3.
Left sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11
Right sum = nums[4] + nums[5] = 5 + 6 = 11

Example 2:
Input: nums = [1,2,3]
Output: -1
Explanation:
There is no index that satisfies the conditions in the problem statement.

Example 3:
Input: nums = [2,1,-1]
Output: 0
Explanation:
The pivot index is 0.
Left sum = 0 (no elements to the left of index 0)
Right sum = nums[1] + nums[2] = 1 + -1 = 0

1 <= nums.length <= 10^4
-1000 <= nums[i] <= 1000

A

Running Sum. Calculate the running sum from left and right and store the results in an array separately.
Compare the left and right from the left.

func pivotIndex(nums []int) int {
	left := make([]int, len(nums))
	left[0] = 0
	for i := 1; i < len(nums); i++ {
		left[i] = left[i-1] + nums[i-1]
	}

	right := make([]int, len(nums))
    right[len(nums) - 1] = 0
    for i := len(nums) - 2; i >= 0; i-- {
        right[i] = right[i + 1] + nums[i + 1]
    }

	for i := range nums {
		if left[i] == right[i] {
			return i
		}
	}
	return -1
}
121
Q

@1208. Get Equal Substrings Within Budget

You are given two strings s and t of the same length and an integer maxCost.

You want to change s to t. Changing the ith character of s to ith character of t costs |s[i] - t[i]| (i.e., the absolute difference between the ASCII values of the characters).

Return the maximum length of a substring of s that can be changed to be the same as the corresponding substring of t with a cost less than or equal to maxCost. If there is no substring from s that can be changed to its corresponding substring from t, return 0.

Example 1:
Input: s = “abcd”, t = “bcdf”, maxCost = 3
Output: 3
Explanation: “abc” of s can change to “bcd”.
That costs 3, so the maximum length is 3.

Example 2:
Input: s = “abcd”, t = “cdef”, maxCost = 3
Output: 1
Explanation: Each character in s costs 2 to change to character in t, so the maximum length is 1.

Example 3:
Input: s = “abcd”, t = “acde”, maxCost = 0
Output: 1
Explanation: You cannot make any change, so the maximum length is 1.

  • 1 <= s.length <= 10^5
  • t.length == s.length
  • 0 <= maxCost <= 10^6
  • s and t consist of only lowercase English letters.
A

Sliding window. Store the absolute distance as a table. Slide through the window and see what window sum fits the budget (maxCost).

func equalSubstring(s string, t string, maxCost int) int {
    var maxLength int
    
    // Sliding Window.
    var distance int

    costTable := make([]int, len(s))
    for i := range s {
        distance = int(t[i]) - int(s[i])
        if distance < 0 {
            distance *= -1
        }

        costTable[i] = distance 
    }
    
    var i int
    var currSum int
    for j := 0; j < len(costTable); j++ {
        currSum += costTable[j]
        for currSum > maxCost && i <= j {
            currSum -= costTable[i]
            i++
        }

        if maxCost >= currSum {
            maxLength = max(maxLength, j - i + 1)
        }
    }

    return maxLength
}
122
Q

@1404. Number of Steps to Reduce a Num in Binary Representation to One

Given the binary representation of an integer as a string s, return the number of steps to reduce it to 1 under the following rules:

If the current number is even, you have to divide it by 2.

If the current number is odd, you have to add 1 to it.

It is guaranteed that you can always reach one for all test cases.

Example 1:
Input: s = “1101”
Output: 6
Explanation: “1101” corressponds to number 13 in their decimal representation.
Step 1) 13 is odd, add 1 and obtain 14.
Step 2) 14 is even, divide by 2 and obtain 7.
Step 3) 7 is odd, add 1 and obtain 8.
Step 4) 8 is even, divide by 2 and obtain 4.
Step 5) 4 is even, divide by 2 and obtain 2.
Step 6) 2 is even, divide by 2 and obtain 1.

Example 2:
Input: s = “10”
Output: 1
Explanation: “10” corressponds to number 2 in their decimal representation.
Step 1) 2 is even, divide by 2 and obtain 1.

Example 3:
Input: s = “1”
Output: 0

Casting the string directly back to integer causes TLE.

  • 1 <= s.length <= 500
  • s consists of characters ‘0’ or ‘1’
  • s[0] == ‘1’
A
  • carry = 0 and current = 0, number is even, have to divide it by 2, step + 1
  • carry = 0 and current = 1, number is odd, have to add 1 and divide it by 2, step + 2
  • carry = 1 and current = 1, number is even, divide it by 2, step + 1
  • carry = 1 and current = 0, number is odd, have to add 1 and divide it by 2, step + 2
func numSteps(s string) int {
    var steps, carry int
    for i := len(s) - 1; i > 0; i-- {
        switch s[i] {
        case '0':
            if carry == 0 {
                // When carry is 0 and current is 0, divide.
                steps++
            } else {
                // When carry is 1 and current is 0 => new current is 1, need another two steps.
                // Flip 1 to 0, divide.
                // And the carry is also carried on.
                steps += 2
            }
        case '1':
            if carry == 0 {
                // When carry is 0, flip 1 to 0, divide.
                steps+=2
            } else {
                // When current is 1 and carry is 1, flip.
                steps++
            }
            carry = 1
        }
    }

    // If carry is not zero when we reach the head of the string, we have an overflow. 
    // Need to divide it by two once more. Hence adding 1.
    if carry != 0 {
        return steps + 1
    }

    return steps
}
123
Q

@2336. Smallest Number in Infinite Set

You have a set which contains all positive integers [1, 2, 3, 4, 5, …].

Implement the SmallestInfiniteSet class:

SmallestInfiniteSet() Initializes the SmallestInfiniteSet object to contain all positive integers.
int popSmallest() Removes and returns the smallest integer contained in the infinite set.
void addBack(int num) Adds a positive integer num back into the infinite set, if it is not already in the infinite set.

Example 1:
Input
[“SmallestInfiniteSet”, “addBack”, “popSmallest”, “popSmallest”, “popSmallest”, “addBack”, “popSmallest”, “popSmallest”, “popSmallest”]
[[], [2], [], [], [], [1], [], [], []]
Output
[null, null, 1, 2, 3, null, 1, 4, 5]

Explanation
SmallestInfiniteSet smallestInfiniteSet = new SmallestInfiniteSet();
smallestInfiniteSet.addBack(2); // 2 is already in the set, so no change is made.
smallestInfiniteSet.popSmallest(); // return 1, since 1 is the smallest number, and remove it from the set.
smallestInfiniteSet.popSmallest(); // return 2, and remove it from the set.
smallestInfiniteSet.popSmallest(); // return 3, and remove it from the set.
smallestInfiniteSet.addBack(1); // 1 is added back to the set.
smallestInfiniteSet.popSmallest(); // return 1, since 1 was added back to the set and
// is the smallest number, and remove it from the set.
smallestInfiniteSet.popSmallest(); // return 4, and remove it from the set.
smallestInfiniteSet.popSmallest(); // return 5, and remove it from the set.

  • 1 <= num <= 1000
  • At most 1000 calls will be made in total to popSmallest and addBack.
A

Create a min heap of size 1000. Use a set to keep track of numbers that already exists in the heap.

type SmallestInfiniteSet struct {
    MinHeap []int
    HeapSize int
    Set map[int]struct{}
}

func Constructor() SmallestInfiniteSet {
    s := SmallestInfiniteSet{
        MinHeap: make([]int, 0),
        Set: make(map[int]struct{}),
    }

    for i := 1; i <= 1000; i++ {
        s.MinHeap = append(s.MinHeap, i)
        s.Set[i] = struct{}{}
        s.HeapSize++
    }

    for i := s.HeapSize / 2; i >= 0; i-- {
        s.MinHeapify(i)
    }
    return s
}

func (this *SmallestInfiniteSet) PopSmallest() int {
    if this.HeapSize == 0 {
        return -1
    }

    smallest := this.MinHeap[0]
    this.MinHeap[0], this.MinHeap[this.HeapSize - 1] = this.MinHeap[this.HeapSize - 1], this.MinHeap[0]
    this.MinHeap = this.MinHeap[:this.HeapSize - 1]
    this.HeapSize--

    this.MinHeapify(0)

    delete(this.Set, smallest)
    return smallest
}

func (this *SmallestInfiniteSet) AddBack(num int)  {
    if _, ok := this.Set[num]; ok {
        return    
    }    

    this.Set[num] = struct{}{}

    // Insert to minHeap.
    this.HeapSize++
    this.MinHeap = append(this.MinHeap, num)

    for j := ParentIdx(this.HeapSize - 1); ; j = ParentIdx(j) {
        this.MinHeapify(j)
        if j == 0 {
            break
        }
    }
}

func (this *SmallestInfiniteSet) MinHeapify(idx int) {
    lowestIdx := idx
    leftChildIdx := LeftChildIdx(idx)
    rightChildIdx := RightChildIdx(idx)

    if leftChildIdx < this.HeapSize && this.MinHeap[leftChildIdx] < this.MinHeap[lowestIdx] {
        lowestIdx = leftChildIdx
    }

    if rightChildIdx < this.HeapSize && this.MinHeap[rightChildIdx] < this.MinHeap[lowestIdx] {
        lowestIdx = rightChildIdx
    }

    if lowestIdx != idx {
        this.MinHeap[idx], this.MinHeap[lowestIdx] = this.MinHeap[lowestIdx], this.MinHeap[idx]
        this.MinHeapify(lowestIdx)
    }
}

func ParentIdx(idx int) int {
    return (idx - 1) >> 1

}

func LeftChildIdx(idx int) int {
    return (idx << 1) + 1
}

func RightChildIdx(idx int) int {
    return (idx + 1) << 1
}
124
Q

@790. Domino and Tromino Tiling

You have two types of tiles: a 2 x 1 domino shape and a tromino shape. You may rotate these shapes.

Given an integer n, return the number of ways to tile an 2 x n board. Since the answer may be very large, return it modulo 109 + 7.

In a tiling, every square must be covered by a tile. Two tilings are different if and only if there are two 4-directionally adjacent cells on the board such that exactly one of the tilings has both squares occupied by a tile.

Example 1:
Input: n = 3
Output: 5
Explanation: The five different ways are show above.

Example 2:
Input: n = 1
Output: 1

1 <= n <= 1000

A

Dynamic Programming.
dp[n] = 2 * dp[n - 1] + dp[n - 3]

func numTilings(n int) int {
    if n == 0 {
        return 0 // no need, just a placeholder.
    }

    if n == 1 {
        return 1
    }

    if n == 2 {
        return 2
    }

    if n == 3 {
        return 5
    }

    dp := make([]int, n+1)

    dp[1] = 1
    dp[2] = 2
    dp[3] = 5

    for i := 4; i <= n; i++ {
        dp[i] = (2 * dp[i-1] + dp[i-3]) % 1000000007
    }

    return dp[n]
}
125
Q

@62. Unique Paths

There is a robot on an m x n grid. The robot is initially located at the top-left corner (i.e., grid[0][0]). The robot tries to move to the bottom-right corner (i.e., grid[m - 1][n - 1]). The robot can only move either down or right at any point in time.

Given the two integers m and n, return the number of possible unique paths that the robot can take to reach the bottom-right corner.

The test cases are generated so that the answer will be less than or equal to 2 * 109.

Example 1:
Input: m = 3, n = 7
Output: 28
Example 2:

Input: m = 3, n = 2
Output: 3
Explanation: From the top-left corner, there are a total of 3 ways to reach the bottom-right corner:
1. Right -> Down -> Down
2. Down -> Down -> Right
3. Down -> Right -> Down

1 <= m, n <= 100

A

Dynamic Programming. Create a table that stores the result.

func uniquePaths(m int, n int) int {
    table := make([][]int, m)

    for i := 0; i < m; i++ {
        table[i] = make([]int, n)
    }

    table[m-1][n-1] = 1

    // Bottom Up approach.
    for row := len(table) - 1; row >= 0; row-- {
        for col := len(table[0]) - 1; col >=0; col-- {
            if table[row][col] != 0 {
                continue
            } 
            // Border
            if row != len(table) - 1 && col == len(table[0]) - 1 {
                table[row][col] += table[row + 1][col]
            } else if row == len(table) - 1 && col != len(table[0]) - 1 {
                table[row][col] += table[row][col + 1]
            } else {
                table[row][col] = table[row + 1][col] + table[row][col + 1]
            }
        }
    }

    return table[0][0]
}
126
Q

@6. ZigZag Conversion

The string “PAYPALISHIRING” is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

P A H N
A P L S I I G
Y I R
And then read line by line: “PAHNAPLSIIGYIR”

Write the code that will take a string and make this conversion given a number of rows:

string convert(string s, int numRows);

Example 1:
Input: s = “PAYPALISHIRING”, numRows = 3
Output: “PAHNAPLSIIGYIR”

Example 2:
Input: s = “PAYPALISHIRING”, numRows = 4
Output: “PINALSIGYAHRPI”
Explanation:
P I N
A L S I G
Y A H R
P I

Example 3:
Input: s = “A”, numRows = 1
Output: “A”

  • 1 <= s.length <= 1000
  • s consists of English letters (lower-case and upper-case), ‘,’ and ‘.’.
  • 1 <= numRows <= 1000
A

Find the zigzag pattern of a string and jump the index respectively.

func convert(s string, numRows int) string {
	if numRows == 1 || len(s) == 1 {
		return s
	}

	original := make([]byte, 0)
	fullGap := (numRows - 1) * 2
	gap := fullGap
	var i int

	// First Row.
	j := i
	for j < len(s) {
		original = append(original, s[j])
		j += fullGap
	}
	gap -= 2

	// Row in middle.
	for i = 1; i < numRows-1; i++ {
		// Jump gap respectively.
		j = i
		for j < len(s) {
			if j < len(s) {
				original = append(original, s[j])
			}
			j += gap
			if j < len(s) {
				original = append(original, s[j])
			}
			j += fullGap - gap
		}
		gap -= 2
	}

	// Last Row
	j = i
	for j < len(s) {
		original = append(original, s[j])
		j += fullGap
	}

	return string(original)
}
127
Q

@260. Single Number lll

Given an integer array nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once. You can return the answer in any order.

You must write an algorithm that runs in linear runtime complexity and uses only constant extra space.

Example 1:
Input: nums = [1,2,1,3,2,5]
Output: [3,5]
Explanation: [5, 3] is also a valid answer.

Example 2:
Input: nums = [-1,0]
Output: [-1,0]

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

  • 2 <= nums.length <= 3 * 10^4
  • -2^31 <= nums[i] <= 2^31 - 1
  • Each integer in nums will appear twice, only two integers will appear once.
A

Use XOR to fetch a ^ b. Find the different bit from the found result. Use the different bit to organize the nums into two separate groups: At the different bit the number is either 1 or either 0. XOR the two groups to get the two unique numbers.

func singleNumber(nums []int) []int {
    var xor int // The XOR result of the two single number/
    for i := range nums {
        xor ^= nums[i]
    } 

    // Find the location first different number in a and b from xor.
    bitDiffLocation := 0
    for (xor >> bitDiffLocation) & 1 != 1{
        bitDiffLocation++
    }

    var uniqueA, uniqueB int
    // Now we can separate nums into two groups
    // 1. A group at bitDiffLocation has the same bit as xor (which is 1)
    // 2. A group at bitDiffLocation is different from xor (which is 0)

    for i := range nums {
        if (nums[i] >> bitDiffLocation) & 1 == 1 {
            uniqueA ^= nums[i]
        } else {
            uniqueB ^= nums[i]
        }
    }

    return []int{uniqueA, uniqueB}
}
128
Q

@1768. Merge String Alternatively

You are given two strings word1 and word2. Merge the strings by adding letters in alternating order, starting with word1. If a string is longer than the other, append the additional letters onto the end of the merged string.

Return the merged string.

Example 1:
Input: word1 = “abc”, word2 = “pqr”
Output: “apbqcr”
Explanation: The merged string will be merged as so:
word1: a b c
word2: p q r
merged: a p b q c r

Example 2:
Input: word1 = “ab”, word2 = “pqrs”
Output: “apbqrs”
Explanation: Notice that as word2 is longer, “rs” is appended to the end.
word1: a b
word2: p q r s
merged: a p b q r s

Example 3:
Input: word1 = “abcd”, word2 = “pq”
Output: “apbqcd”
Explanation: Notice that as word1 is longer, “cd” is appended to the end.
word1: a b c d
word2: p q
merged: a p b q c d

  • 1 <= word1.length, word2.length <= 100
  • word1 and word2 consist of lowercase English letters.
A

Loop through two strings alternatively.

func mergeAlternately(word1 string, word2 string) string {
    result := make([]byte, 0)

    var i, j int
    for i < len(word1) || j < len(word2) {
        if i < len(word1) {
            result = append(result, word1[i])
            i++
        }

        if j < len(word2) {
            result = append(result, word2[j])
            j++
        }
    }

    return string(result)
}
129
Q

@3110. Score of a String

You are given a string s. The score of a string is defined as the sum of the absolute difference between the ASCII values of adjacent characters.

Return the score of s.

Example 1:

Input: s = “hello”

Output: 13

Explanation:

The ASCII values of the characters in s are: ‘h’ = 104, ‘e’ = 101, ‘l’ = 108, ‘o’ = 111. So, the score of s would be |104 - 101| + |101 - 108| + |108 - 108| + |108 - 111| = 3 + 7 + 0 + 3 = 13.

Example 2:

Input: s = “zaz”

Output: 50

Explanation:

The ASCII values of the characters in s are: ‘z’ = 122, ‘a’ = 97. So, the score of s would be |122 - 97| + |97 - 122| = 25 + 25 = 50.

  • 2 <= s.length <= 100
  • s consists only of lowercase English letters.
A

Loop through the string and get the absolute difference from the current and the previous one.

func scoreOfString(s string) int {
    var score int

    var absDiff int
    for i := 1; i < len(s); i++ {
        absDiff = int(s[i]) - int(s[i - 1])
        if absDiff < 0 {
            absDiff *= -1
        }

        score += absDiff
    }

    return score
}
130
Q

@322. Coin Change

You are given an integer array coins representing coins of different denominations and an integer amount representing a total amount of money.

Return the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.

You may assume that you have an infinite number of each kind of coin.

Example 1:
Input: coins = [1,2,5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1

Example 2:
Input: coins = [2], amount = 3
Output: -1

Example 3:
Input: coins = [1], amount = 0
Output: 0

  • 1 <= coins.length <= 12
  • 1 <= coins[i] <= 2^31 - 1
  • 0 <= amount <= 10^4
A

DFS + dynamic programming. Store the result from the depth first search to a table. During the depth first search, check if there’s already result in the memoization table.

func coinChange(coins []int, amount int) int {
	memo := make([]*int, amount+1)
	
    var dfs func(remain int) int
	dfs = func(remain int) int {
		if memo[remain] != nil {
			return *memo[remain]
		}
		if remain == 0 {
			return 0
		}

		numberOfCoins := math.MaxInt32
		for _, c := range coins {
			if c > remain {
				continue
			}
			numberOfCoins = min(numberOfCoins, 1+dfs(remain-c))
		}
		memo[remain] = &numberOfCoins
		return numberOfCoins
	}
    
	numberOfCoins := dfs(amount)
	if numberOfCoins == math.MaxInt32 {
		return -1
	}
	return numberOfCoins
}
131
Q

@2486. Append Characters to String to Make Subsequence

You are given two strings s and t consisting of only lowercase English letters.

Return the minimum number of characters that need to be appended to the end of s so that t becomes a subsequence of s.

A subsequence is a string that can be derived from another string by deleting some or no characters without changing the order of the remaining characters.

Example 1:
Input: s = “coaching”, t = “coding”
Output: 4
Explanation: Append the characters “ding” to the end of s so that s = “coachingding”.
Now, t is a subsequence of s (“coachingding”).
It can be shown that appending any 3 characters to the end of s will never make t a subsequence.

Example 2:
Input: s = “abcde”, t = “a”
Output: 0
Explanation: t is already a subsequence of s (“abcde”).

Example 3:
Input: s = “z”, t = “abcde”
Output: 5
Explanation: Append the characters “abcde” to the end of s so that s = “zabcde”.
Now, t is a subsequence of s (“zabcde”).
It can be shown that appending any 4 characters to the end of s will never make t a subsequence.

  • 1 <= s.length, t.length <= 10^5
  • s and t consist only of lowercase English letters.
A

Two Pointers. Jump the pointer(i) in t when reached a location in s where s[j] == t[i].

func appendCharacters(s string, t string) int {
	var i int

	for j := 0; j < len(s); j++ {
		if s[j] == t[i] {
			i++
		}
        if i == len(t) {
            break
        }
	}

	return len(t) - i
}
132
Q

@2352. Equal Row and Column Pairs

Given a 0-indexed n x n integer matrix grid, return the number of pairs (ri, cj) such that row ri and column cj are equal.

A row and column pair is considered equal if they contain the same elements in the same order (i.e., an equal array).

Example 1:
Input: grid = [[3,2,1],[1,7,6],[2,7,7]]
Output: 1
Explanation: There is 1 equal row and column pair:
- (Row 2, Column 1): [2,7,7]

Example 2:
Input: grid = [[3,1,2,2],[1,4,4,5],[2,4,2,2],[2,4,2,2]]
Output: 3
Explanation: There are 3 equal row and column pairs:
- (Row 0, Column 0): [3,1,2,2]
- (Row 2, Column 2): [2,4,2,2]
- (Row 3, Column 2): [2,4,2,2]

  • n == grid.length == grid[i].length
  • 1 <= n <= 200
  • 1 <= grid[i][j] <= 10^5
A

Store the row and col string separately in a rowMap and a colMap. The count of an identical pair is the multiplcation of both the values with the same key.

func equalPairs(grid [][]int) int {
	var count int

	rowMap := make(map[string]int)
	colMap := make(map[string]int)
	n := len(grid)

	for i := 0; i < n; i++ {
		var colKey string
		var rowKey string
		for j := 0; j < n; j++ {
			rowKey += (strconv.Itoa(grid[i][j]) + ",")
			colKey += (strconv.Itoa(grid[j][i]) + ",")
		}
		rowMap[rowKey]++
		colMap[colKey]++
	}

    fmt.Println(rowMap, colMap)

	for key, val := range rowMap {
        // If we have two identical rows and two identical cols
        // The total pair is 2 * 2 = 4.
		count += val * colMap[key]
	}

	return count
}
133
Q

@409. Longest Palindrome

Given a string s which consists of lowercase or uppercase letters, return the length of the longest
palindrome
that can be built with those letters.

Letters are case sensitive, for example, “Aa” is not considered a palindrome.

Example 1:
Input: s = “abccccdd”
Output: 7
Explanation: One longest palindrome that can be built is “dccaccd”, whose length is 7.

Example 2:
Input: s = “a”
Output: 1
Explanation: The longest palindrome that can be built is “a”, whose length is 1.

  • 1 <= s.length <= 2000
  • s consists of lowercase and/or uppercase English letters only.
A

Form a hashset that stores the frequencies of characters. If we have an odd number, we have a palindrome that can have core with one character. Add the all the odd number - 1 and all the even number to the maxLength.

func longestPalindrome(s string) int {
	count := make(map[byte]int)

	for i := range s {
		count[s[i]] += 1
	}

	var maxLength int
	var haveSingle bool
	for _, v := range count {
		switch v % 2 {
		case 0:
			maxLength += v
		case 1:
			haveSingle = true
			maxLength += v - 1
		}
	}

	if haveSingle {
		maxLength++
	}

	return maxLength
}
134
Q

@345. Reverse Vowels of a String

Given a string s, reverse only all the vowels in the string and return it.

The vowels are ‘a’, ‘e’, ‘i’, ‘o’, and ‘u’, and they can appear in both lower and upper cases, more than once.

Example 1:
Input: s = “hello”
Output: “holle”

Example 2:
Input: s = “leetcode”
Output: “leotcede”

Constraints:

  • 1 <= s.length <= 3 * 10^5
  • s consist of printable ASCII characters.
A

Two Pointers. Reverse accordingly when going through the string.

func reverseVowels(s string) string {
	byteStr := []byte(s)

	i, j := 0, len(byteStr)-1

	for i < j {
		for i < len(s) && !isVowel(byteStr[i]) {
			i++
		}

		for j >= 0 && !isVowel(byteStr[j]) {
			j--
		}
        

		if i < j {
			byteStr[i], byteStr[j] = byteStr[j], byteStr[i]
			i++
			j--
		}
	}

	return string(byteStr)
}

func isVowel(char byte) bool {
	switch char {
	case 'A', 'E', 'I', 'O', 'U', 'a', 'e', 'i', 'o', 'u':
		return true
	default:
		return false
	}
}
135
Q

@437. Path Sum lll

Given the root of a binary tree and an integer targetSum, return the number of paths where the sum of the values along the path equals targetSum.

The path does not need to start or end at the root or a leaf, but it must go downwards (i.e., traveling only from parent nodes to child nodes).

Example 1:

Input: root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
Output: 3
Explanation: The paths that sum to 8 are shown.
Example 2:

Input: root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
Output: 3

  • The number of nodes in the tree is in the range [0, 1000].
  • -10^9 <= Node.val <= 10^9
  • -1000 <= targetSum <= 1000
A

Depth First Search. Add 1 to the return value when the node value is equal to the remains.

Each pathSum function calculates from that node till the end.

func pathSum(root *TreeNode, targetSum int) int {
	if root == nil {
		return 0
	}

	
	var dfs func(node *TreeNode, remains int) int
	dfs = func(node *TreeNode, remains int) int {
		if node == nil {
			return 0
		}
        var pair int
        remains -= node.Val
        if remains == 0 {
            // A pair occurred
            pair++
        }

        return pair + dfs(node.Left, remains) + dfs(node.Right, remains)
	}

	
	return dfs(root, targetSum) + 
            pathSum(root.Left, targetSum) +
            pathSum(root.Right, targetSum);
}
136
Q

@1002. Find Common Characters

Given a string array words, return an array of all characters that show up in all strings within the words (including duplicates). You may return the answer in any order.

Example 1:

Input: words = [“bella”,”label”,”roller”]
Output: [“e”,”l”,”l”]
Example 2:

Input: words = [“cool”,”lock”,”cook”]
Output: [“c”,”o”]

  • 1 <= words.length <= 100
  • 1 <= words[i].length <= 100
  • words[i] consists of lowercase English letters.
A

Create hashsets and compare the frequencies.

func commonChars(words []string) []string {
    common := make([]string, 0)
    arrs := make([][]int, 0)
    
    for _, word := range words {
        arrs = append(arrs, createHashSet(word))
    }

    for i := 0; i < 26; i++ {
        currChar := i + 'a'
        minFrequency := 101
        for j := 0; j < len(arrs); j++ {
            minFrequency = min(minFrequency, arrs[j][i])
        }

        if minFrequency != 101 {
            for k := minFrequency; k > 0; k-- {
                common = append(common, string(currChar))
            }
        }
    }
    return common
}

func createHashSet(word string) []int {
    hashSet := make([]int, 26)
    
    for i := range word {
        hashSet[word[i] - 'a']++
    }

    return hashSet
}
137
Q

@151. Reverse Words in a String

Given an input string s, reverse the order of the words.

A word is defined as a sequence of non-space characters. The words in s will be separated by at least one space.

Return a string of the words in reverse order concatenated by a single space.

Note that s may contain leading or trailing spaces or multiple spaces between two words. The returned string should only have a single space separating the words. Do not include any extra spaces.

Example 1:

Input: s = “the sky is blue”
Output: “blue is sky the”
Example 2:

Input: s = “ hello world “
Output: “world hello”
Explanation: Your reversed string should not contain leading or trailing spaces.
Example 3:

Input: s = “a good example”
Output: “example good a”
Explanation: You need to reduce multiple spaces between two words to a single space in the reversed string.

  • 1 <= s.length <= 10^4
  • s contains English letters (upper-case and lower-case), digits, and spaces ‘ ‘.
  • There is at least one word in s
A

Parse the original string. Append to the word list when encounter space. Read the word list reversely.

func reverseWords(s string) string {
    resultArr := make([]string, 0)
    
    currStr := make([]byte, 0)

    for i := range s {
        switch s[i] {
        case ' ':
            if len(currStr) != 0 {
                resultArr = append(resultArr, string(currStr))
                currStr = make([]byte, 0)
            }
        default:
            currStr = append(currStr, s[i])
        }
    }

    if len(currStr) != 0 {
        resultArr = append(resultArr, string(currStr))
    }

    var result string

    for i := len(resultArr) - 1; i >= 0; i-- {
        if len(result) != 0 {
            result += " "
        }

        result += resultArr[i]
    }
    
    return result
}
138
Q

@846. Hand of Straights

Alice has some number of cards and she wants to rearrange the cards into groups so that each group is of size groupSize, and consists of groupSize consecutive cards.

Given an integer array hand where hand[i] is the value written on the ith card and an integer groupSize, return true if she can rearrange the cards, or false otherwise.

Example 1:
Input: hand = [1,2,3,6,2,3,4,7,8], groupSize = 3
Output: true
Explanation: Alice’s hand can be rearranged as [1,2,3],[2,3,4],[6,7,8]

Example 2:
Input: hand = [1,2,3,4,5], groupSize = 4
Output: false
Explanation: Alice’s hand can not be rearranged into groups of 4.

  • 1 <= hand.length <= 10^4
  • 0 <= hand[i] <= 10^9
  • 1 <= groupSize <= hand.length
A

Keep the used card and the currHand as queue. Only clear the queue when it reached the desired group size. Check if the next card is a valid card to put to hand. If equal, jump. If is valid card, append. If it’s a jumped card, return false.

At the end the currHand should be empty(since all card appended to the hand is at valid size and discarded.).

func isNStraightHand(hand []int, groupSize int) bool {
	// 1. CurrHand empty, append to it
	// 2. CurrHand not empty, check if we can append to it
	//   a. hand[i] is the sequence of the last element of currhand
	//   b. hand[i] is not the sequence of the last element
	//     1. Equals to the last element
	//     2. Jumped, return false

	sort.Ints(hand)
	used := make([]bool, len(hand))

	// Store the index.
	currHand := make([]int, 0)

	for i := 0; i < len(hand); i++ {
		if used[i] {
			continue
		}
		j := i
		for len(currHand) < groupSize && j < len(hand) {

			if used[j] {
				j++
				continue
			}

			// CurrHand empty, append anything that comes after.
			if len(currHand) == 0 {
				currHand = append(currHand, j)
				used[i] = true
				j++
				continue
			}

			// CurrHand not empty, check if the next card is valid.
			if hand[j] == hand[currHand[len(currHand)-1]] {
				j++
			} else if hand[j] == hand[currHand[len(currHand)-1]]+1 {
				currHand = append(currHand, j)
				used[j] = true
				j++
			} else {
				return false
			}
		}

		// Only clear the currHand if the hand size equals to the group size.
		if len(currHand) == groupSize {
			currHand = make([]int, 0)
		}
	}

	// Meaning that the hand didn't reached the group size, didn't renew.
	if len(currHand) != 0 {
		return false
	}

	return true
}
139
Q

@1143. Longest Common Subsequence

Given two strings text1 and text2, return the length of their longest common subsequence. If there is no common subsequence, return 0.

A subsequence of a string is a new string generated from the original string with some characters (can be none) deleted without changing the relative order of the remaining characters.

For example, “ace” is a subsequence of “abcde”.
A common subsequence of two strings is a subsequence that is common to both strings.

Example 1:
Input: text1 = “abcde”, text2 = “ace”
Output: 3
Explanation: The longest common subsequence is “ace” and its length is 3.

Example 2:
Input: text1 = “abc”, text2 = “abc”
Output: 3
Explanation: The longest common subsequence is “abc” and its length is 3.

Example 3:
Input: text1 = “abc”, text2 = “def”
Output: 0
Explanation: There is no such common subsequence, so the result is 0.

  • 1 <= text1.length, text2.length <= 1000
  • text1 and text2 consist of only lowercase English characters.
A

2D Dynamic Programming.
Find the relationship between the strings.
Concept here is
~~~
if len(text1) == 0 || len(text2) == 0, return 0
if text1[0] == text[0], return 1 + lcs(text1[1:], text2[1:])
else, return max(lcs(text1[1:], text2), lcs(text1, text2[1:]))
~~~

// abcde
// ace
// head match => find the longest common subsequence of 1 + lcs(“bcde”, “ce”)

// bcde
// ce
// head doesn’t match => find the longest common subsequence by max(lcs(“bcde”, “ce”), lcs(“cde”, “ce”))

// if any string is empty, return 0

// e
// e
// head match => find the longest subsequence of 1 + lcs(“”, “”) => 1

// e
// “”
// head match => return 0

func longestCommonSubsequence(text1 string, text2 string) int {    
    // Add one more row and column as boundaries.
    dpTable := make([][]int, len(text1) + 1)
    for i := range dpTable {
        dpTable[i] = make([]int, len(text2) + 1)
    }
    
    // Bottom-up approach.
    // 
    // Start from the last second row and column within the dpTable.
    for i := len(text1) - 1; i >= 0; i-- {
        for j := len(text2) - 1; j >= 0; j-- {
            if text1[i] == text2[j] {
                dpTable[i][j] = 1 + dpTable[i + 1][j + 1]
            } else {
                dpTable[i][j] = max(dpTable[i][j + 1], dpTable[i + 1][j])
            }
        }
    }

    return dpTable[0][0]
}
140
Q

@648. Replace word

In English, we have a concept called root, which can be followed by some other word to form another longer word - let’s call this word derivative. For example, when the root “help” is followed by the word “ful”, we can form a derivative “helpful”.

Given a dictionary consisting of many roots and a sentence consisting of words separated by spaces, replace all the derivatives in the sentence with the root forming it. If a derivative can be replaced by more than one root, replace it with the root that has the shortest length.

Return the sentence after the replacement.

Example 1:
Input: dictionary = [“cat”,”bat”,”rat”], sentence = “the cattle was rattled by the battery”
Output: “the cat was rat by the bat”

Example 2:
Input: dictionary = [“a”,”b”,”c”], sentence = “aadsfasf absbs bbab cadsfafs”
Output: “a a b c”

A
  • Brute Force
func replaceWords(dictionary []string, sentence string) string {
    resultSlice := make([]string, 0)
    
    sort.Strings(dictionary)
    
    // Brute force => O(n^3)

    words := strings.Split(sentence, " ")

    for _, word := range words {
        replacement := word

        for _, option := range dictionary {
            // if option in replacement and option.length < replacement
            if in(replacement, option) {
                replacement = option
            }
        } 

        resultSlice = append(resultSlice, replacement)
    }
    
    var result string

    for i, word := range resultSlice {
        if i != len(resultSlice) - 1 {
            result += word + " "
        } else {
            result += word
        }
    }

    return result
}

func in(word1, word2 string) bool {
    if len(word2) >= len(word1) {
        return false
    }

    var i int
    for j := 0; j < len(word2); j++ {
        if word2[j] != word1[i] {
            return false
        }
        i++
    }

    return true
}
``` 

* HashSet. Put all words in the dictionary into a map. Compare and replace the words if we found a match in the map. 

func replaceWords(dictionary []string, sentence string) string {
dic := make(map[string]struct{})

for _, word := range dictionary {
	dic[word] = struct{}{}
}

resultSlice := make([]string, 0)
words := strings.Split(sentence, " ")
for _, word := range words {
	replacement := word

	for j := 0; j < len(word); j++ {
		if _, ok := dic[string(word[:j])]; ok && len(string(word[:j])) < len(replacement){
			replacement = string(word[:j])
		}
	}

	resultSlice = append(resultSlice, replacement)
}

return strings.Join(resultSlice, " ") } ~~~
  • Trie
141
Q

@523. Continuous Subarray Sum

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

  • 1 <= nums.length <= 10^5
  • 0 <= nums[i] <= 10^9
  • 0 <= sum(nums[i]) <= 2^31 - 1
  • 1 <= k <= 2^31 - 1
A

Store the first location of the prefix mod in a hashset. Utilize the fact that mod cycles. If a mode cycles, it either is adding 0 to the previous number, or adding a number that equals to k.

So if a prefix mod is already in the hashset, check the location difference.
If the location difference is greater than 1, we got our answer.

func checkSubarraySum(nums []int, k int) bool {
    // Utilize the trait of a mod: it Cycles.

    // Store prefix mod in a hashset. If the prefix mod is in the hashset
    // It means that we either added 0 or a multiple of k to the sum
    // Check the size of the subarray
    // If the size is not 1, return true => we got a valid subarray.

    // prefixMod = (nums[i] +prefixMod[i - 1]) % k
    modSet := make(map[int]int) // mod: locationIdx
    modSet[0] = -1
    
    prefixMod := 0

	for i := 0; i < len(nums); i++ {
		prefixMod = (nums[i] + prefixMod) % k
        if prevLocation, ok := modSet[prefixMod]; ok {
            if i - prevLocation > 1 {
                return true
            }
        } else {
            modSet[prefixMod] = i
        }
	}
	return false
}
142
Q

@1071. Greatest Common Divisor of Strings

For two strings s and t, we say “t divides s” if and only if s = t + t + t + … + t + t (i.e., t is concatenated with itself one or more times).

Given two strings str1 and str2, return the largest string x such that x divides both str1 and str2.

Example 1:
Input: str1 = “ABCABC”, str2 = “ABC”
Output: “ABC”

Example 2:
Input: str1 = “ABABAB”, str2 = “ABAB”
Output: “AB”

Example 3:
Input: str1 = “LEET”, str2 = “CODE”
Output: “”

  • 1 <= str1.length, str2.length <= 1000
  • str1 and str2 consist of English uppercase letters.
A

Recursion. Trim the assumes gcd from the longest one until either of situtations:
1. The two string equals each other, gcd is the shorter string.
2. First few letters that of the longer string doesn’t equal to the divisor.

func gcdOfStrings(str1 string, str2 string) string {
    if str1 == str2 {
        return str1
    }

    if len(str2) > len(str1) {
        str1, str2 = str2, str1 // so that str1 is always longer.
    }

    // Recursion
    if str1[:len(str2)] != str2 {
        return ""
    }

    // Assume that str2 is the gcd and trim str2 from str1.
    return gcdOfStrings(str1[len(str2):], str2)
}
143
Q

@974. Subarray Sums Divisible by K

Given an integer array nums and an integer k, return the number of non-empty subarrays that have a sum divisible by k.

A subarray is a contiguous part of an array.

Example 1:
Input: nums = [4,5,0,-2,-3,1], k = 5
Output: 7
Explanation: There are 7 subarrays with a sum divisible by k = 5:
[4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]

Example 2:
Input: nums = [5], k = 9
Output: 0

  • 1 <= nums.length <= 3 * 10^4
  • -10^4 <= nums[i] <= 10^4
  • 2 <= k <= 10^4
A

Utilize the trait of cycled modulo.
Given r is smaller than i and j, i is also smaller than j. If prefixSum[r: i] % k = s and prefixSum[r: j] % k = s, then prefixSum[i + 1:j] % k = s.

func subarraysDivByK(nums []int, k int) int {
    remainderMap := make([]int, k)
    remainderMap[0] = 1

    var count int
    var prefixMod int
    for _, num := range nums {
        prefixMod = (prefixMod + num) % k
        if prefixMod < 0 {
            prefixMod += k // Handling negative mod
        }
        
        count+= remainderMap[prefixMod]        
        remainderMap[prefixMod]++
    }
		
    return count
}
144
Q

@1051. Height Checker

A school is trying to take an annual photo of all the students. The students are asked to stand in a single file line in non-decreasing order by height. Let this ordering be represented by the integer array expected where expected[i] is the expected height of the ith student in line.

You are given an integer array heights representing the current order that the students are standing in. Each heights[i] is the height of the ith student in line (0-indexed).

Return the number of indices where heights[i] != expected[i].

Example 1:
Input: heights = [1,1,4,2,1,3]
Output: 3
Explanation:
heights: [1,1,4,2,1,3]
expected: [1,1,1,2,3,4]
Indices 2, 4, and 5 do not match.

Example 2:
Input: heights = [5,1,2,3,4]
Output: 5
Explanation:
heights: [5,1,2,3,4]
expected: [1,2,3,4,5]
All indices do not match.

Example 3:
Input: heights = [1,2,3,4,5]
Output: 0
Explanation:
heights: [1,2,3,4,5]
expected: [1,2,3,4,5]
All indices match.

  • 1 <= heights.length <= 100
  • 1 <= heights[i] <= 100
A

Sort and compare the difference.
~~~
func heightChecker(heights []int) int {
// Sort and compare the difference
sortedHeights := make([]int, len(heights))
copy(sortedHeights, heights)

sort.Ints(sortedHeights)

var diff int
for i := range heights {
    if heights[i] != sortedHeights[i] {
        diff++
    }
}

return diff } ~~~
145
Q

@1122. Relatvie Sort Arrray

Given two arrays arr1 and arr2, the elements of arr2 are distinct, and all elements in arr2 are also in arr1.

Sort the elements of arr1 such that the relative ordering of items in arr1 are the same as in arr2. Elements that do not appear in arr2 should be placed at the end of arr1 in ascending order.

Example 1:
Input: arr1 = [2,3,1,3,2,4,6,7,9,2,19], arr2 = [2,1,4,3,9,6]
Output: [2,2,2,1,4,3,3,9,6,7,19]

Example 2:
Input: arr1 = [28,6,22,8,44,17], arr2 = [22,28,8,6]
Output: [22,28,8,6,17,44]

  • 1 <= arr1.length, arr2.length <= 1000
  • 0 <= arr1[i], arr2[i] <= 1000
  • All the elements of arr2 are distinct.
  • Each arr2[i] is in arr1.
A
  • Sort in-place
func relativeSortArray(arr1 []int, arr2 []int) []int {
	var sortedIdx int
	// Sort relatively first.
	for i := 0; i < len(arr2); i++ {
		for j := sortedIdx; j < len(arr1); j++ {
			if arr1[j] == arr2[i] {
				arr1[j], arr1[sortedIdx] = arr1[sortedIdx], arr1[j]
				sortedIdx++
			}
		}
	}

	// Start sorting the rest in ascending from index == sortedIdx
    bubbles := len(arr1[sortedIdx:])
	for i := 0; i < bubbles; i++ {
		for j := len(arr1) - 1; j > sortedIdx; j-- {
			if arr1[j] < arr1[j-1] {
				arr1[j], arr1[j-1] = arr1[j-1], arr1[j]
			}
		}
		sortedIdx++
	}

	return arr1
}
  • Counting Sort. Create buckets that stores the frequency of an element.
func relativeSortArray(arr1 []int, arr2 []int) []int {
    existSet := make(map[int]int)
    for i := range arr2 {
        existSet[arr2[i]] = 0
    }

    notExistMap := make([]int, 1001)
    for i := range arr1 {
        if _, ok := existSet[arr1[i]]; ok {
            existSet[arr1[i]]++
        } else {
            notExistMap[arr1[i]]++
        }
    }

    sortArr := make([]int, 0)

    for _, num := range arr2 {
        count := existSet[num]
        for count > 0 {
            sortArr = append(sortArr, num)
            count--
        }
    }

    for num, freq := range notExistMap {
        count := freq
        for count > 0 {
            sortArr = append(sortArr, num)
            count--
        }
    }

    return sortArr
}
146
Q

@75. Sort Colors

Given an array nums with n objects colored red, white, or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white, and blue.

We will use the integers 0, 1, and 2 to represent the color red, white, and blue, respectively.

You must solve this problem without using the library’s sort function.

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

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

  • n == nums.length
  • 1 <= n <= 300
  • nums[i] is either 0, 1, or 2
A

Sorting in place with constant space: Bubble sort.

func sortColors(nums []int)  {
    // Bubble sort.
    for j := len(nums) - 1; j >= 0; j-- {
        for i := 0; i < j; i++ {
            if nums[i] > nums[i + 1] {
                nums[i], nums[i + 1] = nums[i + 1], nums[i]
            }
        }
    } 
}
147
Q

@2037. Minimum Number of Moves to Seat Everyone

There are n seats and n students in a room. You are given an array seats of length n, where seats[i] is the position of the ith seat. You are also given the array students of length n, where students[j] is the position of the jth student.

You may perform the following move any number of times:

Increase or decrease the position of the ith student by 1 (i.e., moving the ith student from position x to x + 1 or x - 1)
Return the minimum number of moves required to move each student to a seat such that no two students are in the same seat.

Note that there may be multiple seats or students in the same position at the beginning.

Example 1:

Input: seats = [3,1,5], students = [2,7,4]
Output: 4
Explanation: The students are moved as follows:
- The first student is moved from from position 2 to position 1 using 1 move.
- The second student is moved from from position 7 to position 5 using 2 moves.
- The third student is moved from from position 4 to position 3 using 1 move.
In total, 1 + 2 + 1 = 4 moves were used.
Example 2:

Input: seats = [4,1,5,9], students = [1,3,2,6]
Output: 7
Explanation: The students are moved as follows:
- The first student is not moved.
- The second student is moved from from position 3 to position 4 using 1 move.
- The third student is moved from from position 2 to position 5 using 3 moves.
- The fourth student is moved from from position 6 to position 9 using 3 moves.
In total, 0 + 1 + 3 + 3 = 7 moves were used.
Example 3:

Input: seats = [2,2,6,6], students = [1,3,2,6]
Output: 4
Explanation: Note that there are two seats at position 2 and two seats at position 6.
The students are moved as follows:
- The first student is moved from from position 1 to position 2 using 1 move.
- The second student is moved from from position 3 to position 6 using 3 moves.
- The third student is not moved.
- The fourth student is not moved.
In total, 1 + 3 + 0 + 0 = 4 moves were used.

  • n == seats.length == students.length
  • 1 <= n <= 100
  • 1 <= seats[i], students[j] <= 100
A
  • Greedily compare sorted array.
func minMovesToSeat(seats []int, students []int) int {
    // Greedily move to the position closest?
    sort.Ints(seats)
    sort.Ints(students)

    var moves int

    for i := range seats {
        move := seats[i] - students[i]
        if move < 0 {
            move *= -1
        }

        moves += move
    }

    return moves 
}
  • Counting bucket. Get the difference between the current position and the desired position.
func minMovesToSeat(seats []int, students []int) int {
    // Counting bucket.
    // 1. Find max within the two arrays.
    var largestSeat int
    for i := range seats {
        if seats[i] > largestSeat {
            largestSeat = seats[i]
        }
    }

    for i := range students {
        if students[i] > largestSeat {
            largestSeat = students[i]
        }
    }

    // 2. Create a table indicating where the seat is located and which student (at where) is inneed of a seat. 
    seatsDifference := make([]int, largestSeat)

    // Provide seat.
    for i := range seats {
        seatsDifference[seats[i] - 1]++
    }

    // Sit on the seat.
    for i := range students {
        seatsDifference[students[i] - 1]--
    }

    // Walk through the seat difference table and make sure that all negatives (students who needs a seat) moves to a location that can cancel out the positive seat (vacancy).
    var moves int
    var unmatched int
    for i := range seatsDifference {
        // Abslute number of unmatched is also the number of students moving.
        moves += abs(unmatched)

        // Substrackt students who found their seat.
        unmatched += seatsDifference[i]
    }

    return moves
}

func abs(num int) int {
    if num < 0 {
        return num * -1
    }

    return num
}
148
Q

@1004. Max Consecutive Ones

Given a binary array nums and an integer k, return the maximum number of consecutive 1’s in the array if you can flip at most k 0’s.

Example 1:
Input: nums = [1,1,1,0,0,0,1,1,1,1,0], k = 2
Output: 6
Explanation: [1,1,1,0,0,1,1,1,1,1,1]
Bolded numbers were flipped from 0 to 1. The longest subarray is underlined.

Example 2:
Input: nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], k = 3
Output: 10
Explanation: [0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
Bolded numbers were flipped from 0 to 1. The longest subarray is underlined.

  • 1 <= nums.length <= 10^5
  • nums[i] is either 0 or 1.
  • 0 <= k <= nums.length
A

Sliding Window. Keep track of the available k’s to flip. If the k is still valid and encounter 1, expand. If k is valid but encounter 0, subtract k by 1. If k isn’t valid, shrink the window until a zero leaves the window.

func longestOnes(nums []int, k int) int {
	var longest int

	remains := k

	var i, j int
	for j < len(nums) {
		if nums[j] == 0 {
			remains--
			for remains < 0 {
                // Add to remains when a zero exits.
				if nums[i] == 0 {
					remains++
				}
                // Shrink the window.
				i++
			}
		}
        // Check the window length.
		longest = max(longest, j-i+1)
        // Expand the window.
		j++
	}

	return longest
}
149
Q

@1207. Unique Number of occurrences

Given an array of integers arr, return true if the number of occurrences of each value in the array is unique or false otherwise.

Example 1:
Input: arr = [1,2,2,1,1,3]
Output: true
Explanation: The value 1 has 3 occurrences, 2 has 2 and 3 has 1. No two values have the same number of occurrences.

Example 2:
Input: arr = [1,2]
Output: false

Example 3:
Input: arr = [-3,0,1,-3,1,1,1,-3,10,0]
Output: true

  • 1 <= arr.length <= 1000
  • -1000 <= arr[i] <= 1000
A

Hashmap.

func uniqueOccurrences(arr []int) bool {
    count := make(map[int]int)
    for i := range arr {
        count[arr[i]]++
    }

    occurrences := make(map[int]struct{})
    for _, v := range count {
        if _, ok := occurrences[v]; ok {
            return false
        }
        occurrences[v] = struct{}{}
    }

    return true
}
150
Q

@945. Minimum Increment to Make Array Unique

You are given an integer array nums. In one move, you can pick an index i where 0 <= i < nums.length and increment nums[i] by 1.

Return the minimum number of moves to make every value in nums unique.

The test cases are generated so that the answer fits in a 32-bit integer.

Example 1:
Input: nums = [1,2,2]
Output: 1
Explanation: After 1 move, the array could be [1, 2, 3].

Example 2:
Input: nums = [3,2,1,2,1,7]
Output: 6
Explanation: After 6 moves, the array could be [3, 4, 1, 2, 5, 7].
It can be shown with 5 or less moves that it is impossible for the array to have all unique values.

  • 1 <= nums.length <= 10^5
  • 0 <= nums[i] <= 10^5
A

Create a difference bucket and add the carry to moves each loop

// 0, 1, 2, 3
// [0, 1, 2]
// [0, 1, 1]
// [0, -1, 1]

// 0, 1, 2, 3, 4, 5, 6, 7
// [0, 2, 2, 1, 0, 0, 0, 1]
// [0, 1, 1, 1, 0, 0, 0, 1]
// [0, 1, 1, -1, 0, 0, 0, 1]

At index 0, moves = 0, carry = 0
At index 1, moves = 0, carry = 1
At index 2, moves += carry == 1 , then carry += currDiff == 2
At index 3, occupied, moves += carry = 3
At index 4, moves += carry = 5, carry -= 1== 1
At index 5, moves += carry = 6, carry -= 1 == 0

func minIncrementForUnique(nums []int) int {
    var arrMax int
    for i := range nums {
        if nums[i] > arrMax {
            arrMax = nums[i]
        }
    }

    bucket := make([]int, arrMax + 1)
    suppose := make([]int, arrMax + 1)

    for _, num := range nums {
        bucket[num]++
        suppose[num] = 1
    }

    diff := make([]int, arrMax + 1)
    for i := range bucket {
        if bucket[i] == 1 && bucket[i] == suppose[i] {
            diff[i] = -1 // occupied
        } else {
            diff[i] = bucket[i] - suppose[i]
        }
    }    

    var moves int
    var carry int
    for i, num := range diff {
        // Add all carry to moves => all non-unique number must move once to this position.
        if carry > 0 {
            moves += carry
        }
        // Difference is 1, there's another non-unique number.
        if num >= 1 {
            carry += num
        }

        // No difference, put 1 non-unique number here.
        if num == 0 && carry > 0 {
            carry--
            diff[i] = -1
        }
    }

    // Deal with the left non-unique numbers.    
    // If carry is 3, then we need to move 3, then 2, then 1
    for i := carry; i > 0; i-- {
        moves += i
    } 

    return moves
}
151
Q

@216. Combination Sum lll

Find all valid combinations of k numbers that sum up to n such that the following conditions are true:

Only numbers 1 through 9 are used.
Each number is used at most once.
Return a list of all possible valid combinations. The list must not contain the same combination twice, and the combinations may be returned in any order.

such that the following conditions are true:

Only numbers 1 through 9 are used.
Each number is used at most once.
Return a list of all possible valid combinations. The list must not contain the same combination twice, and the combinations may be returned in any order.

Example 1:
Input: k = 3, n = 7
Output: [[1,2,4]]
Explanation:
1 + 2 + 4 = 7
There are no other valid combinations.

Example 2:
Input: k = 3, n = 9
Output: [[1,2,6],[1,3,5],[2,3,4]]
Explanation:
1 + 2 + 6 = 9
1 + 3 + 5 = 9
2 + 3 + 4 = 9
There are no other valid combinations.

Example 3:
Input: k = 4, n = 1
Output: []
Explanation: There are no valid combinations.
Using 4 different numbers in the range [1,9], the smallest sum we can get is 1+2+3+4 = 10 and since 10 > 1, there are no valid combination.

  • 2 <= k <= 9
  • 1 <= n <= 60
A

Backtracking.

func combinationSum3(k int, n int) [][]int {
    combinations := make([][]int, 0) 
    
    var backtracking func(lastNum, localSum ,currk int, currCombination []int)
    backtracking = func(lastNum, localSum, currk int, currCombination []int){
        if currk == 0 {
            if localSum == n {
                combinations = append(combinations, currCombination)
            }
            return
        }

        for i := lastNum + 1; i <= 9; i++ {
            nextCombination := make([]int, len(currCombination))
            copy(nextCombination, currCombination)
            nextCombination = append(nextCombination, i)

            backtracking(i, localSum + i, currk - 1, nextCombination)
        }
    }

    for i := 1; i <= 9; i++ {
        backtracking(i, i, k - 1, []int{i})
    }

    return combinations
}
152
Q

[HARD] @501. IPO

Suppose LeetCode will start its IPO soon. In order to sell a good price of its shares to Venture Capital, LeetCode would like to work on some projects to increase its capital before the IPO. Since it has limited resources, it can only finish at most k distinct projects before the IPO. Help LeetCode design the best way to maximize its total capital after finishing at most k distinct projects.

You are given n projects where the ith project has a pure profit profits[i] and a minimum capital of capital[i] is needed to start it.

Initially, you have w capital. When you finish a project, you will obtain its pure profit and the profit will be added to your total capital.

Pick a list of at most k distinct projects from given projects to maximize your final capital, and return the final maximized capital.

The answer is guaranteed to fit in a 32-bit signed integer.

Example 1:
Input: k = 2, w = 0, profits = [1,2,3], capital = [0,1,1]
Output: 4
Explanation: Since your initial capital is 0, you can only start the project indexed 0.
After finishing it you will obtain profit 1 and your capital becomes 1.
With capital 1, you can either start the project indexed 1 or the project indexed 2.
Since you can choose at most 2 projects, you need to finish the project indexed 2 to get the maximum capital.
Therefore, output the final maximized capital, which is 0 + 1 + 3 = 4.

Example 2:
Input: k = 3, w = 0, profits = [1,2,3], capital = [0,1,2]
Output: 6

  • 1 <= k <= 10^5
  • 0 <= w <= 10^9
  • n == profits.length
  • n == capital.length
  • 1 <= n <= 10^5
  • 0 <= profits[i] <= 10^4
  • 0 <= capital[i] <= 10^9
A

Max Heap.

Sort Projects by capital, ensuring we look at the cheapest project first. Loop through the projects every round, pushing all projects whose capital is smaller or equal to the current capital to the MaxHeap (where the MaxHeap properity is determined by the profit).

This way we have a quick access to the project with the highest available profit for the current round. Loop up to k rounds: Pop the highest project from the MaxHeap, add the profit to the capital ( w ), break if there is no more available project in the heap ( no more projects can be pushed to the heap, either empty projects or the projects left are too expensive).

Max Heap

type Project struct {
    Capital int
    Profit int
}

// Inorder to use the heap package in Go, we have to fit the interface 
// If we were to use a max heap property, the less in the sort should be in descending order.

// type Interface interface {
// 	sort.Interface
// 	Push(x any) // add x as element Len()
// 	Pop() any   // remove and return element Len() - 1.
// }

type PriorityQueue []Project

func (pq PriorityQueue) Len() int {return len(pq)}
func (pq PriorityQueue) Less(i, j int) bool {return pq[i].Profit > pq[j].Profit} // Descending order.
func (pq PriorityQueue) Swap(i, j int) {pq[i], pq[j] = pq[j], pq[i]}

// Push pushes project to the tail of the Priority Queue.
func (pq *PriorityQueue) Push(x interface{}) {
    item := x.(Project)
    *pq = append(*pq, item)
}

// Pop removes the tail from the Pririty Queue.
func (pq *PriorityQueue) Pop() interface{} {
    old := *pq
    n := len(old)
    item := old[n-1]
    *pq = old[:n-1]
    return item
}

func findMaximizedCapital(k int, w int, profits []int, capital []int) int {
    // Create the priority queue first.
    projects := make([]Project, len(profits))
    
    for i := 0; i < len(profits); i++ {
        projects[i] = Project{
            Capital: capital[i],
            Profit: profits[i],
        }
    }

    // projects is now sorted in ascending order determined by capital.
    // This allows us to iterate through the projects array in a linear fashion, 
    // this way we won't have to go through the entire list every time looking for capitals that are smaller then the current capital(w).
    sort.Slice(projects, func(i, j int) bool {
        return projects[i].Capital < projects[j].Capital
    })

    // Create a max heap. pq now fits the interface heap in Go.
    pq := make(PriorityQueue, 0)
    i := 0

    for k > 0 {
        // Push all projects whose capital is smaller or equal to the current w (capital) to the MaxHeap.
        for i < len(projects) && projects[i].Capital <= w {
            heap.Push(&pq, projects[i])
            i++
        }

        // Break when there's no more available item in the priority queue.
        // 1. All projects are exhausted.
        // 2. We can't afford the projects that are left.
        if len(pq) == 0 {
            break
        }

        // Pick the head from the MaxHeap, that will be the profit for the current round.
        currProject := heap.Pop(&pq).(Project)
        w += currProject.Profit
        
        // Decrease k after successfully getting profit for the current round.
        k--
    }

    return w
}
153
Q

[HARD] @330. Patching Array

Given a sorted integer array nums and an integer n, add/patch elements to the array such that any number in the range [1, n] inclusive can be formed by the sum of some elements in the array.

Return the minimum number of patches required.

Example 1:
Input: nums = [1,3], n = 6
Output: 1
Explanation:
Combinations of nums are [1], [3], [1,3], which form possible sums of: 1, 3, 4.
Now if we add/patch 2 to nums, the combinations are: [1], [2], [3], [1,3], [2,3], [1,2,3].
Possible sums are 1, 2, 3, 4, 5, 6, which now covers the range [1, 6].
So we only need 1 patch.

Example 2:
Input: nums = [1,5,10], n = 20
Output: 2
Explanation: The two patches can be [2, 4].
Example 3:

Input: nums = [1,2,2], n = 5
Output: 0

  • 1 <= nums.length <= 1000
  • 1 <= nums[i] <= 10^4
  • nums is sorted in ascending order.
  • 1 <= n <= 2^31 - 1
A

Find the pattern when added missing number or add existing number from current array.

For array [1], we can form sum within [0, 2)
For array [1, 2], we can form sum within [0, 4)
For array [1, 2, 4], we can form sum within [0, 8)

If our array have (or smaller than )the next missing number, we add it to the missing number, then we can form sum within [0, miss + nums[i])

If our array doesn’t have the next missing number, add the missing number to array, then we can form sum within [0, miss + miss)

Find pattern

Using the given numbers 1, 2 and 4, we can already build all sums from 0 to 7, i.e., the range [0,8). But we can't build the sum 8, and | the next given number (13) is too large. So we insert 8 into the array. Then we can build all sums in [0,16).
Do we need to insert 16 into the array? No! We can already build the sum 3, and adding the given 13 gives us sum 16. We can also add the 13 to the other sums, extending our range to [0,29).
And so on. The given 43 is too large to help with sum 29, so we must insert 29 into our array. This extends our range to [0,58). But then the 43 becomes useful and expands our range to [0,101). At which point we're done.
func minPatches(nums []int, n int) int {
    var patches int

    // miss means that we can have a series of sum in range [0, miss)
    // We start from 1 (You need a 1 to form a 1).
    miss := 1

    var i int
    // The loop breaks when the missing number is greater than n.
    // Means that at the breaking point, our array can form a series of [0, miss), where miss >= n.
    for miss <= n {
        // Loop in nums.
        if i < len(nums) && nums[i] <= miss {
            // if the current nums[i] is smaller than or equal to miss, ex: [1, 2, 4, 8, 13], miss = 16 (meaning that the miss is formed from our previous added number)
            // we add the next number 13 directly to the miss, 16 + 13 = 29, expanding range of sum our array can form. 
            miss += nums[i]
            i++
        } else {
            // Using the numbers 1, 2 and 4, we can already build all sums from 0 to 7, i.e., the range [0,8). 
            // But we can't build the sum 8, and if the next given number is greater than 8, then there's no way we can build 8.
            // Thus we add the missing 8 to the array. Now the range of sum our array can cover is [0, 16), and our next missing number is 16.
            miss += miss
            patches++
        }
    }

    return patches
}

Example: Let’s say the input is nums = [1, 2, 4, 13, 43] and n = 100. We need to ensure that all sums in the range [1,100] are possible.