KK's blog

每天积累多一些

0%

LeetCode



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

Example 1:

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


Example 2:

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


Constraints:

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

题目大意:

子数组和等于k的个数

解题思路:

子数组和第一时间想到presum,而数组元素之间关系也应该想到two sum

解题步骤:

N/A

注意事项:

  1. 加0到presum中或者加0到sum_to_idx字典中,确保presum本身可以等于k
  2. 数组含负数,也即是presum中可以含有多个相同的值,所以sum_to_idx要转成频数而不是下标。如[-1, 1, -1, 1], k=0结果为4,而不是3, 容易漏整个数组和

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# presum = [0, 1, 2, 3], target = presum[i] - k = presum[j]
# add 0 to presum so that presum[i] = k
# [0, -1, 0, -1, 0]
# [0, 1]
def subarraySum(self, nums: List[int], k: int) -> int:
presum, res = [0], 0 #
for n in nums:
presum.append(presum[-1] + n) # 0, 1, 2, 3
sum_to_idx = collections.defaultdict(int)
for i in range(len(presum)): #
if presum[i] - k in sum_to_idx: # 1-1
res += sum_to_idx[presum[i] - k] #4
sum_to_idx[presum[i]] += 1 # {0:2, -1:2, 2:2}
return res

算法分析:

时间复杂度为O(n),空间复杂度O(n)

LeetCode



Sometimes people repeat letters to represent extra feeling. For example:

"hello" -> "heeellooo" "hi" -> "hiiii"

In these strings like "heeellooo", we have groups of adjacent letters that are all the same: "h", "eee", "ll", "ooo".

You are given a string s and an array of query strings words. A query word is stretchy if it can be made to be equal to s by any number of applications of the following extension operation: choose a group consisting of characters c, and add some number of characters c to the group so that the size of the group is three or more.

For example, starting with "hello", we could do an extension on the group "o" to get "hellooo", but we cannot get "helloo" since the group "oo" has a size less than three. Also, we could do another extension like "ll" -> "lllll" to get "helllllooo". If s = "helllllooo", then the query word "hello" would be stretchy because of these two extension operations: query = "hello" -> "hellooo" -> "helllllooo" = s.

Return the number of query strings that are stretchy.

Example 1:

Input: s = “heeellooo”, words = [“hello”, “hi”, “helo”]
Output: 1
Explanation:
We can extend “e” and “o” in the word “hello” to get “heeellooo”.
We can’t extend “helo” to get “heeellooo” because the group “ll” is not size 3 or more.


Example 2:

Input: s = “zzzzzyyyyy”, words = [“zzyy”,”zy”,”zyy”]
Output: 3


Constraints:
1 <= s.length, words.length <= 100
1 <= words[i].length <= 100 s and words[i] consist of lowercase letters.

题目大意:

Cisco常考题
定义了一种富于表现力的单词,就是说某个字母可以重复三次或以上,叫stretchy
找给定的单词列表中的单词可以成为stretchy单词的个数

解题思路:

统计每个字符的个数,然后比较对应每个字符个数

解题步骤:

N/A

注意事项:

  1. Line 13的条件,若个数不等,word的字符个数大于stretchy的字符个数(word不能删除字符),或者stretchy的个数小于3,就不满足

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
def expressiveWords(self, s: str, words: List[str]) -> int:
res = 0
s_count = self.get_consecutive_count(s)
for word in words:
char_count = self.get_consecutive_count(word)
if len(char_count) != len(s_count):
continue
for i in range(len(s_count)):
char_s, count_s = s_count[i]
char_w, count_w = char_count[i]
if char_w != char_s:
break
if count_s != count_w and (count_w > count_s or count_s < 3): # remember
break
if i == len(s_count) - 1:
res += 1
return res

def get_consecutive_count(self, s):
s += ' '
s_count, count = [], 1
for i in range(1, len(s)):
if s[i] != s[i - 1]:
s_count.append((s[i - 1], count))
count = 0
count += 1
return s_count

算法分析:

时间复杂度为O(n),空间复杂度O(1)

LeetCode



Given an array of n integers nums and an integer target, find the number of index triplets i, j, k with 0 <= i < j < k < n that satisfy the condition nums[i] + nums[j] + nums[k] < target.

Example 1:

Input: nums = [-2,0,1,3], target = 2
Output: 2
Explanation: Because there are two triplets which sums are less than 2:
[-2,0,1]
[-2,0,3]


Example 2:

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


Example 3:

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


Constraints:

n == nums.length 0 <= n <= 3500
-100 <= nums[i] <= 100 -100 <= target <= 100

题目大意:

找三数和小于target的组合个数

解题思路:

类似于三数和等于target,但当小于target时,直接求个数,类似于LeetCode 315 Count of Smaller Numbers After Self。

解题步骤:

N/A

注意事项:

  1. res不是+1而是right - left

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def threeSumSmaller(self, nums: List[int], target: int) -> int:
if len(nums) < 3:
return 0
nums.sort()
res = 0
for i in range(len(nums) - 2):
left, right = i + 1, len(nums) - 1
while left < right:
if nums[i] + nums[left] + nums[right] < target:
res += right - left # remember
left += 1
else:
right -= 1
return res

算法分析:

时间复杂度为O(n2),空间复杂度O(1)

LeetCode



Given an integer array nums, find three numbers whose product is maximum and return the maximum product.

Example 1:

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


Example 2:

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


Example 3:

Input: nums = [-1,-2,-3]
Output: -6


Constraints:

3 <= nums.length <= 10<sup>4</sup> -1000 <= nums[i] <= 1000

题目大意:

求数组任意三个数的最大乘积

排序法解题思路:

数学题,正负数分开,最大只可以是排序后最大的三个数(全正,全负)或最大整数乘以最小两个负数(正负均有)

解题步骤:

N/A

注意事项:

  1. Python代码:

    1
    2
    3
    def maximumProduct(self, nums: List[int]) -> int:
    nums.sort()
    return max(nums[-1] * nums[-2] * nums[-3], nums[-1] * nums[0] * nums[1])

算法分析:

时间复杂度为O(nlogn),空间复杂度O(1)


Heap算法II解题思路:

由上述思路进一步优化,不需要全部排序,只需要知道最大的3个数和最小的两个数即可

Python代码:

1
2
3
4
def maximumProduct2(self, nums: List[int]) -> int:
largest = heapq.nlargest(3, nums)
smallest = heapq.nsmallest(2, nums)
return max(largest[0] * largest[1] * largest[2], largest[0] * smallest[0] * smallest[1])

算法分析:

时间复杂度为O(n),空间复杂度O(1)

LeetCode 1048 Longest String Chain



You are given an array of words where each word consists of lowercase English letters.

word<sub>A</sub> is a predecessor of word<sub>B</sub> if and only if we can insert exactly one letter anywhere in word<sub>A</sub> without changing the order of the other characters to make it equal to word<sub>B</sub>.

For example, "abc" is a predecessor of "ab<u>a</u>c", while "cba" is not a predecessor of "bcad".

A word chainis a sequence of words [word<sub>1</sub>, word<sub>2</sub>, ..., word<sub>k</sub>] with k >= 1, where word<sub>1</sub> is a predecessor of word<sub>2</sub>, word<sub>2</sub> is a predecessor of word<sub>3</sub>, and so on. A single word is trivially a word chain with k == 1.

Return the length of the longest possible word chain with words chosen from the given list of words.

Example 1:

Input: words = [“a”,”b”,”ba”,”bca”,”bda”,”bdca”]
Output: 4
Explanation: One of the longest word chains is [“a”,”ba”,”bda”,”bdca”].


Example 2:

Input: words = [“xbc”,”pcxbcf”,”xb”,”cxbc”,”pcxbc”]
Output: 5
Explanation: All the words can be put in a word chain [“xb”, “xbc“, “cxbc”, “pcxbc”, “pcxbcf“].


Example 3:

Input: words = [“abcd”,”dbqca”]
Output: 1
Explanation: The trivial word chain [“abcd”] is one of the longest word chains.
[“abcd”,”dbqca”] is not a valid word chain because the ordering of the letters is changed.


Constraints:
1 <= words.length <= 1000
1 <= words[i].length <= 16 words[i] only consists of lowercase English letters.

Problem Overview

Get longgest one-character transformation in the given list

Thinking Process

This problem is similar to Word Break (reversed to get neighbors) but it is a multi-source longest path problem.

Steps

  1. Loop through each word
  2. BFS from each word and get the max distance
  3. Get the max of distance

Notes

  1. max_dis = 1 by default in BFS
  2. To improve the complexity, make the distance map global so that the distance of each node will be calculated once.
    To do that, sort the list from longest to shortest and make sure the it is greedy to get the max distance

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def longestStrChain(self, words: List[str]) -> int:
word_dict, distance = set(words), {}
max_dis = 0
words.sort(key=len, reverse=True) # remember
for word in words:
dis = self.bfs(word, word_dict, distance)
max_dis = max(max_dis, dis)
return max_dis

def bfs(self, word, word_dict, distance):
queue = deque([word])
visited = {word}
if word in distance: # remember
return distance[word]
distance[word] = 1
max_dis = 1
while queue:
node = queue.popleft()
for neighbor in self.get_neighbors(node, word_dict):
if neighbor in visited:
continue
queue.append(neighbor)
visited.add(neighbor)
distance[neighbor] = distance[node] + 1
max_dis = max(max_dis, distance[neighbor])
return max_dis

def get_neighbors(self, word, word_dict):
res = []
for i in range(len(word)):
new_word = word[:i] + word[i + 1:]
if new_word in word_dict:
res.append(new_word)
return res

Analysis

Though there is a loop and bfs like n^2, actually it is a traversal in a graph. n * L (n is # of nodes, L is max of path
single-source) is the num of edges. Another L is to get neighbors.
Time complexityO(nlogn + n*L2), Space complexityO(n).

Free mock interview