There is a new alien language that uses the English alphabet. However, the order among the letters is unknown to you.
You are given a list of strings words from the alien language’s dictionary, where the strings in words are sorted lexicographically by the rules of this new language.
Return a string of the unique letters in the new alien language sorted in lexicographically increasing order by the new language’s rules. If there is no solution, return"". If there are multiple solutions, return any of them.
A string s is lexicographically smaller than a string t if at the first letter where they differ, the letter in s comes before the letter in t in the alien language. If the first min(s.length, t.length) letters are the same, then s is smaller if and only if s.length < t.length.
Example 1:
Input: words = [“wrt”,”wrf”,”er”,”ett”,”rftt”] Output: “wertf”
Example 2:
Input: words = [“z”,”x”] Output: “zx”
Example 3:
Input: words = [“z”,”x”,”z”] Output: “” Explanation: The order is invalid, so return "".
Constraints:
1 <= words.length <= 1001 <= words[i].length <= 100 * words[i] consists of only lowercase English letters.
defalienOrder(self, words: List[str]) -> str: # graph = collections.defaultdict(list) graph = Counter({c: [] for word in words for c in word}) for i in range(1, len(words)): ifnot self.populate_one_order(words[i - 1], words[i], graph): return'' in_degree = collections.defaultdict(int) for c in graph.keys(): in_degree[c] = 0 for key, li in graph.items(): for j in range(len(li)): in_degree[li[j]] += 1 res = '' queue = deque([node for node, in_degree_num in in_degree.items() if in_degree_num == 0]) while queue: node = queue.popleft() res += node for neighbor in graph[node]: in_degree[neighbor] -= 1 if in_degree[neighbor] == 0: queue.append(neighbor) return res if len(graph) == len(res) else''
defpopulate_one_order(self, word, word2, graph): for j in range(min(len(word), len(word2))): if word[j] != word2[j]: graph[word[j]].append(word2[j]) returnTrue returnFalseif len(word) > len(word2) elseTrue
definsert(self, word: str) -> None: it = self.head for i in range(len(word)): # if word[i] not in it.children: #it.children[word[i]] = TrieNode() it = it.children[word[i]] it.is_end = True
defsearch(self, word: str) -> bool: it = self.head for i in range(len(word)): if word[i] notin it.children: returnFalse it = it.children[word[i]] return it.is_end
defstartsWith(self, prefix: str) -> bool: it = self.head for i in range(len(prefix)): if prefix[i] notin it.children: returnFalse it = it.children[prefix[i]] returnTrue
definsert(self, word: str) -> None: ifnot word: return it = self.head for i in range(len(word)): # if word[i] not in it.children: # it.children[word[i]] = TrieNode() it = it.children[word[i]] if i == len(word) - 1: it.is_end = True
defsearch(self, word: str) -> bool: ifnot word: returnFalse it = self.head for i in range(len(word)): if word[i] notin it.children: returnFalse it = it.children[word[i]] if i == len(word) - 1and it.is_end: returnTrue returnFalse
defstartsWith(self, prefix: str) -> bool: ifnot prefix: returnFalse it = self.head for i in range(len(prefix)): if prefix[i] notin it.children: returnFalse it = it.children[prefix[i]] if i == len(prefix) - 1: returnTrue returnFalse
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 ofwords.
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 <= 16words[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
Loop through each word
BFS from each word and get the max distance
Get the max of distance
Notes
max_dis = 1 by default in BFS
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
defbfs(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
defget_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).
dp[i][j] = max{dp[i][m] + nums[i]×nums[m]×nums[j] + dp[m][j]}, i < m < j
多状态型DP(DP有多个终止状态)
1 2 3 4 5
dp = dp if s[i] = '0' = dp + 1 if s[i] = '1' dp2 = min(dp2 + 1, dp + 1) if s[i] = '0' = min(dp2, dp) if s[i] = '1'
解题步骤:
9zhang按照DP四部曲
[初始化]dp数组
[实现]
[答案]
[优化]是否可以用滚动内存优化空间
单序列或匹配型DP模板
实现注意事项(5点):
[多1][初始化]初始化矩阵,dp是原长度加1。因为令边界计算方便. 遍历从多少开始,取决于前状态多少个,若递归式含dp[i-1],从1开始,如果dp[i-2]就从2开始.数值型DP,如硬币个数DP长度是数值amount,不是数组长度。Python用dp = [[0 for _ in range(M)] for _ in range(N)], M为col数,再row数
defprint_path(self, nums, path[:biggest_pos + 1], dp_value = res): pos, res = len(path) - 1, [] for _ in range(dp_value): res.append(nums[pos]) pos = path[pos] return res[::-1]
LCS:
path和dp一样,不用特别数组
从右下到左上,若上或左值一样,向此方向移动,直到左和上少一,此时res -= 1
Python代码:
1 2 3 4 5 6 7 8 9 10 11
longest, res = dp[-1][-1], '' while m >= 0and n >= 0: if dp[m - 1][n] == longest: m -= 1 elif dp[m][n - 1] == longest: n -= 1 else: res += text1[m - 1] longest -= 1 m -= 1 n -= 1
Design a data structure to find the frequency of a given value in a given subarray.
The frequency of a value in a subarray is the number of occurrences of that value in the subarray.
Implement the RangeFreqQuery class:
RangeFreqQuery(int[] arr) Constructs an instance of the class with the given 0-indexed integer array arr.
int query(int left, int right, int value) Returns the frequency of value in the subarray arr[left...right].
A subarray is a contiguous sequence of elements within an array. arr[left...right] denotes the subarray that contains the elements of nums between indices left and right (inclusive).
Example 1:
**Input**
["RangeFreqQuery", "query", "query"]
[[[12, 33, 4, 56, 22, 2, 34, 33, 22, 12, 34, 56]], [1, 2, 4], [0, 11, 33]]
**Output**
[null, 1, 2]
**Explanation**
RangeFreqQuery rangeFreqQuery = new RangeFreqQuery([12, 33, 4, 56, 22, 2, 34, 33, 22, 12, 34, 56]);
rangeFreqQuery.query(1, 2, 4); // return 1\. The value 4 occurs 1 time in the subarray [33, 4]
rangeFreqQuery.query(0, 11, 33); // return 2\. The value 33 occurs 2 times in the whole array.
Constraints:
1 <= arr.length <= 10<sup>5</sup>
1 <= arr[i], value <= 10<sup>4</sup>
0 <= left <= right < arr.length
At most 10<sup>5</sup> calls will be made to query