KK's blog

每天积累多一些

0%

LeetCode



Given two strings s and p, return an array of all the start indices of p‘s anagrams in s. You may 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: s = “cbaebabacd”, p = “abc”
Output: [0,6]
Explanation:
The substring with start index = 0 is “cba”, which is an anagram of “abc”.
The substring with start index = 6 is “bac”, which is an anagram of “abc”.


Example 2:

Input: s = “abab”, p = “ab”
Output: [0,1,2]
Explanation:
The substring with start index = 0 is “ab”, which is an anagram of “ab”.
The substring with start index = 1 is “ba”, which is an anagram of “ab”.
The substring with start index = 2 is “ab”, which is an anagram of “ab”.


Constraints:

`1 <= s.length, p.length <= 3 104*sandp` consist of lowercase English letters.

题目大意:

求字符串s中含p的anagram的所有初始下标

解题思路:

求某子串的频率统计,第一时间想到滑动窗口。此题较特殊,属于固定大小窗口的滑动窗口,因为p的大小是固定的,窗口大小必须和p长度一样。

解题步骤:

N/A

注意事项:

  1. Python代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    def findAnagrams(self, s: str, p: str) -> List[int]:
    char_to_count_p = collections.Counter(p)
    substr_win = collections.defaultdict(int)
    res = []
    for i, char in enumerate(s):
    substr_win[s[i]] += 1
    # window: [i - len(p) + 1, i]
    if i >= len(p):
    substr_win[s[i - len(p)]] -= 1
    if substr_win[s[i - len(p)]] == 0:
    substr_win.pop(s[i - len(p)])
    if substr_win == char_to_count_p:
    res.append(i - len(p) + 1)
    return res

算法分析:

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

A change for two N-children tree contains:

  1. key is different
  2. value is different
  3. delete a node
  4. add a node

Problem: how many changes to convert tree A to tree B

题目大意:

DD的面经题,多少个改动可以使得existingTree变成newTree

解题思路:

DFS, 比较children,三种情况。若其中一方没有节点,就是计算节点数

解题步骤:

N/A

注意事项:

  1. 比较children,三种情况。若其中一方没有节点,就是计算节点数

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
def changeNodes(self, existingTree, newTree) -> int:
if not existingTree and not newTree:
return 0
if not existingTree or not newTree:
return self.count(existingTree) + self.count(newTree)
res = 0 if existingTree.key == newTree.key and existingTree.val == newTree.val else 1
existing_children_dict = self.get_children_dict(existingTree.children)
new_tree_children_dict = self.get_children_dict(newTree.children)
for key in existing_children_dict.keys() & new_tree_children_dict.keys(): # in both
res += self.changeNodes(existing_children_dict[key], new_tree_children_dict[key])
for key in existing_children_dict.keys() - new_tree_children_dict.keys(): # in existing tree not in new tree
res += self.count(existing_children_dict[key])
for key in new_tree_children_dict.keys() - existing_children_dict.keys(): # in new tree not in existing tree
res += self.count(new_tree_children_dict[key])
return res

def count(self, root):
if not root:
return 0
res = 0
for child in root.children:
res += self.count(child)
return 1 + res

def get_children_dict(self, children):
key_to_node = {}
for child in children:
key_to_node[child.key] = child
return key_to_node

算法分析:

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

LeetCode



You are asked to design a file system that allows you to create new paths and associate them with different values.

The format of a path is one or more concatenated strings of the form: / followed by one or more lowercase English letters. For example, “/leetcode" and “/leetcode/problems" are valid paths while an empty string "" and "/" are not.

Implement the FileSystem class:

bool createPath(string path, int value) Creates a new path and associates a value to it if possible and returns true. Returns false if the path already exists or its parent path doesn’t exist. int get(string path) Returns the value associated with path or returns -1 if the path doesn’t exist.

Example 1:

Input:
[“FileSystem”,”createPath”,”get”]
[[],[“/a”,1],[“/a”]]
Output:
[null,true,1]
Explanation:
FileSystem fileSystem = new FileSystem();

fileSystem.createPath(“/a”, 1); // return true
fileSystem.get(“/a”); // return 1


Example 2:

Input:
[“FileSystem”,”createPath”,”createPath”,”get”,”createPath”,”get”]
[[],[“/leet”,1],[“/leet/code”,2],[“/leet/code”],[“/c/d”,1],[“/c”]]
Output:
[null,true,true,2,false,-1]
Explanation:
FileSystem fileSystem = new FileSystem();

fileSystem.createPath(“/leet”, 1); // return true
fileSystem.createPath(“/leet/code”, 2); // return true
fileSystem.get(“/leet/code”); // return 2
fileSystem.createPath(“/c/d”, 1); // return false because the parent path “/c” doesn’t exist.
fileSystem.get(“/c”); // return -1 because this path doesn’t exist.


Constraints:

The number of calls to the two functions is less than or equal to 10<sup>4</sup> in total. 2 <= path.length <= 100
* 1 <= value <= 10<sup>9</sup>

题目大意:

设计文件系统,支持创建路径,路径含key, value

Trie解题思路:

用Trie, is_end变成key, value

解题步骤:

N/A

注意事项:

  1. 遍历用1开始,因为首个/前面是空字符串

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
35
36
37
38
39
class FileSystem(TestCases):

def __init__(self):
self.head = TrieNode('')

def createPath(self, path: str, value: int) -> bool:
segments = path.split('/')

it = self.head
for i in range(1, len(segments)):
segment = segments[i]
if segment not in it.children:
if i == len(segments) - 1: # match all the previous segments
it.children[segment] = TrieNode(segment)
else:
return False
it = it.children[segment]
if it.value != -1: # exists
return False
it.value = value
return True

def get(self, path: str) -> int:
segments = path.split('/')

it = self.head
for i in range(1, len(segments)):
segment = segments[i]
if segment not in it.children:
return -1
it = it.children[segment]
return it.value

class TrieNode:

def __init__(self, name):
self.children = collections.defaultdict(TrieNode) # {}
self.name = name
self.value = -1

算法分析:

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


算法II HashMap解题思路:

用前缀法

Python代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class FileSystem2(TestCases):

def __init__(self):
self.path_to_val = defaultdict()

def createPath(self, path: str, value: int) -> bool:

if path == "/" or len(path) == 0 or path in self.path_to_val:
return False

# search from the right
parent = path[:path.rfind('/')]
if len(parent) > 1 and parent not in self.path_to_val:
return False

self.path_to_val[path] = value
return True

def get(self, path: str) -> int:
return self.path_to_val.get(path, -1)

算法分析:

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

LeetCode



Two strings X and Y are similar if we can swap two letters (in different positions) of X, so that it equals Y. Also two strings X and Y are similar if they are equal.

For example, "tars" and "rats" are similar (swapping at positions 0 and 2), and "rats" and "arts" are similar, but "star" is not similar to "tars", "rats", or "arts".

Together, these form two connected groups by similarity: {"tars", "rats", "arts"} and {"star"}. Notice that "tars" and "arts" are in the same group even though they are not similar. Formally, each group is such that a word is in the group if and only if it is similar to at least one other word in the group.

We are given a list strs of strings where every string in strs is an anagram of every other string in strs. How many groups are there?

Example 1:

Input: strs = [“tars”,”rats”,”arts”,”star”]
Output: 2


Example 2:

Input: strs = [“omv”,”ovm”]
Output: 1


Constraints:

1 <= strs.length <= 300 1 <= strs[i].length <= 300
strs[i] consists of lowercase letters only. All words in strs have the same length and are anagrams of each other.

题目大意:

单词列表中,可以分成多少组,每组里面的单词互相之间至少有一对可以通过交换一个位置变成另一个单词

解题思路:

典型求连通集个数,类似于Num of island,用BFS。难点在于怎么找到neighbor,用遍历每一个单词的方式

解题步骤:

N/A

注意事项:

  1. 难点在于怎么找到neighbor,用遍历每一个单词的方式,判断是否buddyStrings Leetcode 0859

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
def numSimilarGroups(self, strs: List[str]) -> int:
if not strs:
return 0
visited, groups, word_set = set(), 0, set(strs)
for s in strs:
if s in visited:
continue
self.bfs(word_set, s, visited)
groups += 1
return groups

def bfs(self, word_set, start, visited):
queue = collections.deque([start])
visited.add(start)
while queue:
node = queue.popleft()
for s in word_set:
if s in visited:
continue
if node == s or not self.buddyStrings(node, s):
continue
queue.append(s)
visited.add(s)

def buddyStrings(self, s: str, goal: str) -> bool:
if len(s) != len(goal):
return False
if s == goal and len(set(s)) < len(goal): # any dups
return True
diff = [(a, b) for a, b in zip(s, goal) if a != b]
return True if len(diff) == 2 and diff[0] == diff[1][::-1] else False

算法分析:

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

LeetCode



You are given two strings of the same length s and t. In one step you can choose any character of t and replace it with another character.

Return the minimum number of steps to make t an anagram of s.

An Anagram of a string is a string that contains the same characters with a different (or the same) ordering.

Example 1:

Input: s = “bab”, t = “aba”
Output: 1
Explanation: Replace the first ‘a’ in t with b, t = “bba” which is anagram of s.


Example 2:

Input: s = “leetcode”, t = “practice”
Output: 5
Explanation: Replace ‘p’, ‘r’, ‘a’, ‘i’ and ‘c’ from t with proper characters to make t anagram of s.


Example 3:

Input: s = “anagram”, t = “mangaar”
Output: 0
Explanation: “anagram” and “mangaar” are anagrams.


Constraints:

`1 <= s.length <= 5 104*s.length == t.length*sandt` consist of lowercase English letters only.

题目大意:

通过替换字母使得两字符为同位词Anagram

解题思路:

统计某一个词的词频,遍历另一个单词,减去词频,若不够减(小于0),就加步数

解题步骤:

N/A

注意事项:

  1. Python代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    def minSteps(self, s: str, t: str) -> int:
    char_to_count_t = collections.Counter(t)
    steps = 0
    for char in s:
    if char in char_to_count_t and char_to_count_t[char] > 0:
    char_to_count_t[char] -= 1
    else:
    steps += 1
    return steps

算法分析:

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

Free mock interview