421. Maximum XOR of Two Numbers in an Array (Medium)
Given an integer array nums, return the maximum result of nums[i] XOR nums[j], where 0 <= i <= j < n.
class Solution:
def findMaximumXOR(self, nums: List[int]) -> int:
res=0
L=len(bin(max(nums)))-2
for i in range(L-1,-1,-1):
res <<=1
cur_xor = res | 1
prefixes = {n >> i for n in nums}
res |= any(cur_xor^p in prefixes for p in prefixes)
return res
class Solution:
def findMaximumXOR(self, nums: List[int]) -> int:
L = len(bin(max(nums))) - 2
max_xor = 0
for i in reversed(range(L)):
max_xor <<= 1
# Set comprehension is used for speed purposes
# List comprehension is what most pythonic users are used too imo
prefixes = {num >> i for num in nums}
curr_xor = max_xor | 1
for p in prefixes:
# if p1 ^ p2 == curr_xor then
# p1 ^ curr_xor == p2 ( p2 is in prefixes)
if p ^ curr_xor in prefixes:
# Set the last bit to 1
max_xor |= 1
return max_xor
没思路,看答案。
422. Valid Word Square (Easy)
Given an array of strings words, return true if it forms a valid word square.
A sequence of strings forms a valid word square if the kth row and column read the same string, where 0 <= k < max(numRows, numColumns).
class Solution:
def validWordSquare(self, words: List[str]) -> bool:
L = max([len(word) for word in words])
words = [w if len(w)==L else w+' '*(L-len(w)) for w in words]
for i,w in enumerate(zip(*words)):
#print(i,''.join(w),words[i])
if ''.join(w)!=words[i]:
return False
return True
public class Solution {
public boolean validWordSquare(List<String> words) {
if(words == null || words.size() == 0){
return true;
}
int n = words.size();
for(int i=0; i<n; i++){
for(int j=0; j<words.get(i).length(); j++){
if(j >= n || words.get(j).length() <= i || words.get(j).charAt(i) != words.get(i).charAt(j))
return false;
}
}
return true;
}
}
有corner case。。。Java 答案更正确
423. Reconstruct Original Digits from English (Medium)
Given a string s containing an out-of-order English representation of digits 0-9, return the digits in ascending order.
class Solution:
def originalDigits(self, s: 'str') -> 'str':
# building hashmap letter -> its frequency
count = collections.Counter(s)
# building hashmap digit -> its frequency
out = {}
# letter "z" is present only in "zero"
out["0"] = count["z"]
# letter "w" is present only in "two"
out["2"] = count["w"]
# letter "u" is present only in "four"
out["4"] = count["u"]
# letter "x" is present only in "six"
out["6"] = count["x"]
# letter "g" is present only in "eight"
out["8"] = count["g"]
# letter "h" is present only in "three" and "eight"
out["3"] = count["h"] - out["8"]
# letter "f" is present only in "five" and "four"
out["5"] = count["f"] - out["4"]
# letter "s" is present only in "seven" and "six"
out["7"] = count["s"] - out["6"]
# letter "i" is present in "nine", "five", "six", and "eight"
out["9"] = count["i"] - out["5"] - out["6"] - out["8"]
# letter "n" is present in "one", "nine", and "seven"
out["1"] = count["n"] - out["7"] - 2 * out["9"]
# building output string
output = [key * out[key] for key in sorted(out.keys())]
return "".join(output)
#MY ANSWER
class Solution:
def originalDigits(self, s: str) -> str:
# zero 00)Z确定0个数
# one
# two 11) w知道 2 个数
# three 5) r - 4中r 0中r 知道 3 个数
# four 4) f - 5中f 确定 4 个数, 知道4中 r个数
# five 3) V- seven 个数 确定 5 个数
# six 33) X 确定6 的个数
# seven 2) S-X 确定 7 个数
# eight 22) g 确定 8 个数
# nine 44) i he 33 确定9
res = {str(i):0 for i in range(10)}
C = Counter(s)
# 0
res['0'] = C['z']
C['z']-=res['0']
C['e']-=res['0']
C['r']-=res['0']
C['o']-=res['0']
# 2
res['2'] = C['w']
C['t']-=res['2']
C['w']-=res['2']
C['o']-=res['2']
# 6
res['6'] = C['x']
C['s']-=res['6']
C['i']-=res['6']
C['x']-=res['6']
# 8
res['8'] = C['g']
C['e'] -= res['8']
C['i'] -= res['8']
C['g'] -= res['8']
C['h'] -= res['8']
C['t'] -= res['8']
# 7
res['7'] = C['s']
C['s']-=res['7']
C['e']-=res['7']
C['v']-=res['7']
C['e']-=res['7']
C['n']-=res['7']
# 3
res['3'] = C['t']
C['t']-=res['3']
C['h']-=res['3']
C['r']-=res['3']
C['e']-=res['3']
C['e']-=res['3']
# 4
res['4'] = C['r']
C['f'] -= res['4']
C['o'] -= res['4']
C['u'] -= res['4']
C['r'] -= res['4']
# 5
res['5'] = C['f']
C['f'] -= res['5']
C['i'] -= res['5']
C['v'] -= res['5']
C['e'] -= res['5']
# 1
res['1'] = C['o']
C['o']-=res['1']
C['n']-=res['1']
C['e']-=res['1']
# 9
res['9'] = C['i']
C['n']-=res['9']
C['i']-=res['9']
C['n']-=res['9']
C['e']-=res['9']
r = ''
for key in sorted(res):
if res[key]!=0:
r+= key*res[key]
return r
直接做会出现是否要再次使用当前数字然后继续,或者直接使用下个数字,当前数字不重复使用的问题。
解决方法。。。醉了
Letter "z" is present only in "zero".
Letter "w" is present only in "two".
Letter "u" is present only in "four".
Letter "x" is present only in "six".
Letter "g" is present only in "eight".
Hence there is a good way to count even numbers.
That is actually the key how to count 3s, 5s and 7s since some letters are present only in one odd and one even number (and all even numbers has already been counted) :
Letter "h" is present only in "three" and "eight".
Letter "f" is present only in "five" and "four".
Letter "s" is present only in "seven" and "six".
Now one needs to count 9s and 1s only, and the logic is basically the same :
Letter "i" is present in "nine", "five", "six", and "eight".
Letter "n" is present in "one", "seven", and "nine".
424. Longest Repeating Character Replacement (Medium)
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.
#BINARY SEARCH + Sliding Window
class Solution:
def characterReplacement(self, s: str, k: int) -> int:
l = 1
r = len(s)-1
def valid_length(m):
start = 0
freq = defaultdict(int)
maxfreq = 0
for end in range(len(s)):
freq[s[end]]+=1
if end -start+ 1>m:
freq[s[start]]-=1
start+=1
maxfreq = max(maxfreq,freq[s[end]])
if m-maxfreq<=k:
return True
return False
while l<=r:
m = (l+r)//2
#print(l,r,m,valid_length(m))
if valid_length(m):
l=m+1
else:
r=m-1
return l if valid_length(l) else l-1
#方法2 For loop + sliding window
class Solution:
def characterReplacement(self, s: str, k: int) -> int:
set_s = set(s)
res = 0
def is_window_valid(start,end,count,k):
return end-start+1-count<=k
for ch in set_s:
start = 0
count = 0
for end in range(len(s)):
if s[end]==ch:
count+=1
while not is_window_valid(start, end, count, k):
if s[start]==ch:
count-=1
start+=1
res = max(res, end-start+1)
return res
#方法三
class Solution:
def characterReplacement(self, s: str, k: int) -> int:
res = 0
start = 0
freq = defaultdict(int)
max_freq = 0
for end in range(len(s)):
#expand window
freq[s[end]]+=1
max_freq = max(max_freq,freq[s[end]])
is_valid = end-start+1-max_freq<=k
if not is_valid:
#shrink
freq[s[start]]-=1
start+=1
res = end-start+1
return res
#。。。。
class Solution:
def characterReplacement(self, s: str, k: int) -> int:
l=len(s)
count = defaultdict(int)
maxcount = 0
res = 0
start = 0
for end in range(l):
#expand
count[s[end]]+=1
maxcount = max(maxcount,count[s[end]])
while end-start+1-maxcount>k:
#srink
count[s[start]]-=1
start+=1
res = max(res, end-start+1)
return res
方法一,binary search+ sliding window, 最小1, 最大len(s)做binary seach 看 m长度是不是一个valid length, valid 是指 m长度的sliding window中,存在能变成同一个字符的substring,找出sliding window中的最freq的频率,m-频率 就是杂char的个数,如果小于等于k说明m长度是valid。
方法二: 对每一个unique char, 做for loop, 判断是不是valid window,如果不是就要缩小窗口,start+1.
方法三:
two pointer, expand更新最大频率,check是不是valid,如果不valid,减去一个必定又valid,所以start+1,更新freq。 然后计算result。
方法四:
expand end 更新最大freq, 然后发现不满足条件就shrink, start更新,然后计算结果。
425. Word Squares (Hard)
Given an array of unique strings words, return all the word squares you can build from words. The same word from words can be used multiple times. You can return the answer in any order.
A sequence of strings forms a valid word square if the kth row and column read the same string, where 0 <= k < max(numRows, numColumns).
For example, the word sequence ["ball","area","lead","lady"] forms a word square because each word reads the same both horizontally and vertically.
class Solution:
def wordSquares(self, words: List[str]) -> List[List[str]]:
# a b c d
# b d e f
# c e g h
# d f h k
# select abcd
# next must select b
# select abcd
# bdef
# next must select ce
# select abcd
# bdef
# cegh
# next must selct dfh
# select abcd
# bdef
# cegh
# dfhk
#
# need a trie tree to find prefix is valid or not
# if valid prefix, for childern path, need to explore all possible combinations using bt
class Trie:
def __init__(self):
self.children=dict()
self.words=set()
def search(self,string):
if not string: return True
if string[0] not in self.children:
return False
return self.children[string[0]].search(string[1:])
def getwords(self,string):
if string is False: return True
if len(string)==1:
return self.children[string].words
return self.children[string[0]].getwords(string[1:])
trie=Trie()
#insert words to trie
for word in words:
cur=trie
for w in word:
if w not in cur.children:
cur.children[w] = Trie()
cur.words.add(word)
cur=cur.children[w]
res=[]
size=len(words[0])
def bt(tmp,words):
#backtracking to generate all possible word squares
if len(tmp)==size:
res.append(tmp[:])
return
if not words: return
for word in words:
tmp.append(word)
level=len(tmp)
searchkey=''.join([e[level] for e in tmp]) if level<size else False
if trie.search(searchkey):
validwords=trie.getwords(searchkey)
bt(tmp,validwords)
tmp.pop()
bt([],set(words))
return res
#ANSWER is faster...
class Solution:
def wordSquares(self, words: 'List[str]') -> 'List[List[str]]':
dic= collections.defaultdict(list)
n=len(words[0])
for word in words:
for i in range(1,n):
key=word[:i]
dic[key].append(word)
res=[]
def build(squre):
#print(len(squre))
if len(squre)==n:
res.append(squre)
return
#print(n,len(squre),squre)
for word in dic[''.join(list(zip(*squre))[len(squre)])]:
new=squre[:]
new.append(word)
build(new)
for word in words:
build([word])
return res
#MY ANSWER
class Solution:
def wordSquares(self, words: List[str]) -> List[List[str]]:
#A B C D
#B E F G
#C F J I
l = len(words[0])
prefix = defaultdict(list)
for i in range(1,l):
for w in words:
prefix[w[:i]].append(w)
res = []
def bt(row_id,tmp):
if row_id==l:
res.append(tmp[:])
return
if row_id ==0:
for w in words:
bt(row_id+1, tmp+[w])
else:
key = ''
for row in tmp:
key+=row[row_id]
if key in prefix:
for w in prefix[key]:
bt(row_id+1,tmp+[w])
bt(0,[])
return res
很明显backtracking问题。。。
426. Convert Binary Search Tree to Sorted Doubly Linked List (Medium)
Convert a Binary Search Tree to a sorted Circular Doubly-Linked List in place.
You can think of the left and right pointers as synonymous to the predecessor and successor pointers in a doubly-linked list. For a circular doubly linked list, the predecessor of the first element is the last element, and the successor of the last element is the first element.
We want to do the transformation in place. After the transformation, the left pointer of the tree node should point to its predecessor, and the right pointer should point to its successor. You should return the pointer to the smallest element of the linked list.
"""
# Definition for a Node.
class Node:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
"""
class Solution:
def treeToDoublyList(self, root: 'Optional[Node]') -> 'Optional[Node]':
#inorder
# pre > <cur
if not root: return root
head = None
stack = []
pre =None
while stack or root:
while root:
stack.append(root)
root=root.left
root = stack.pop()
if not head: head = root
if pre:
pre.right = root
root.left = pre
pre = root
root = root.right
pre.right = head
head.left = pre
return head
#ANSER RECURSION METHOD
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
def helper(node):
"""
Performs standard inorder traversal:
left -> node -> right
and links all nodes into DLL
"""
nonlocal last, first
if node:
# left
helper(node.left)
# node
if last:
# link the previous node (last)
# with the current one (node)
last.right = node
node.left = last
else:
# keep the smallest node
# to close DLL later on
first = node
last = node
# right
helper(node.right)
if not root:
return None
# the smallest (first) and the largest (last) nodes
first, last = None, None
helper(root)
# close DLL
last.right = first
first.left = last
return first
corner case 要想清楚。。 而且node要call right left时候node必须存在。
427. Construct Quad Tree (Medium)
Given a n * n matrix grid of 0's and 1's only. We want to represent the grid with a Quad-Tree.
Return the root of the Quad-Tree representing the grid.
"""
# Definition for a QuadTree node.
class Node:
def __init__(self, val, isLeaf, topLeft, topRight, bottomLeft, bottomRight):
self.val = val
self.isLeaf = isLeaf
self.topLeft = topLeft
self.topRight = topRight
self.bottomLeft = bottomLeft
self.bottomRight = bottomRight
"""
class Solution:
def construct(self, grid: List[List[int]]) -> 'Node':
size=len(grid)
if len({e for row in grid for e in row})==1:
val=grid[0][0]==1
isLeaf=True
topLeft=None
topRight=None
bottomLeft=None
bottomRight=None
return Node(val,isLeaf,topLeft,topRight,bottomLeft,bottomRight)
else:
isLeaf=False
val=True
topLeft=self.construct([row[:size//2] for row in grid[:size//2]])
topRight=self.construct([row[size//2:] for row in grid[:size//2]])
bottomLeft=self.construct([row[:size//2] for row in grid[size//2:]])
bottomRight=self.construct([row[size//2:] for row in grid[size//2:]])
return Node(val,isLeaf,topLeft,topRight,bottomLeft,bottomRight)
428. Serialize and Deserialize N-ary Tree (Hard)
Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.
Design an algorithm to serialize and deserialize an N-ary tree. An N-ary tree is a rooted tree in which each node has no more than N children. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that an N-ary tree can be serialized to a string and this string can be deserialized to the original tree structure.
"""
# Definition for a Node.
class Node(object):
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
"""
# Definition for a Node.
class Node(object):
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
class Codec:
def serialize(self, root):
"""Encodes a tree to a single string.
:type root: Node
:rtype: str
"""
r=[]
if not root: return r
q=[root]
while q:
node=q.pop(0)
if node !=',':
r.append(str(node.val))
for child in node.children:
q.append(child)
q.append(',')
else:
r.append(',')
return '#'.join(r)
def deserialize(self, data):
"""Decodes your encoded data to tree.
:type data: str
:rtype: Node
"""
if not data: return None
pieces=data.split('#')
root = Node(int(pieces[0]), [])
idx = 1
q=[root]
while q:
node=q.pop(0)
while pieces[idx] != ',':
child=Node(int(pieces[idx]), [])
node.children.append(child)
q.append(child)
idx += 1
idx += 1
return root
# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.deserialize(codec.serialize(root))
#BFS MY ANSWER
class Codec:
def serialize(self, root: 'Node') -> str:
"""Encodes a tree to a single string.
:type root: Node
:rtype: str
"""
if not root: return ''
code=lambda node: str(node.val)+'+'+str(len(node.children))
res = []
q = [root]
while q:
for _ in range(len(q)):
cur = q.pop(0)
res.append(code(cur))
for node in cur.children:
q.append(node)
return ','.join(res)
def deserialize(self, data: str) -> 'Node':
"""Decodes your encoded data to tree.
:type data: str
:rtype: Node
"""
#print(data)
if not data: return None
dic = dict()
data = data.split(',')
root = None
q = []
c = 0
while data:
#print(data)
val,n = data.pop(0).split('+')
val = int(val)
n = int(n)
node = Node(val)
dic[node] = n
if not root: root = node
if q :
#print('me',q[0].val,'nc',dic[q[0]],'child',node.val)
q[0].children.append(node)
dic[q[0]]-=1
if dic[q[0]]==0:
q.pop(0)
if n:
q.append(node)
return root
第一种 答案写的更简洁
429. N-ary Tree Level Order Traversal (Medium)
Given an n-ary tree, return the level order traversal of its nodes' values.
Nary-Tree input serialization is represented in their level order traversal, each group of children is separated by the null value (See examples).
"""
# Definition for a Node.
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
class Solution:
def levelOrder(self, root: 'Node') -> List[List[int]]:
if not root: return []
q=[root]
res=[]
while q:
l=len(q)
level=[]
for _ in range(l):
cur=q.pop(0)
level.append(cur.val)
for child in cur.children:
q.append(child)
res.append(level)
return res
#RECURSION ANSWER
class Solution:
def levelOrder(self, root: 'Node') -> List[List[int]]:
def traverse_node(node, level):
if len(result) == level:
result.append([])
result[level].append(node.val)
for child in node.children:
traverse_node(child, level + 1)
result = []
if root is not None:
traverse_node(root, 0)
return result
BFS
430. Flatten a Multilevel Doubly Linked List (Medium)
You are given a doubly linked list, which contains nodes that have a next pointer, a previous pointer, and an additional child pointer. This child pointer may or may not point to a separate doubly linked list, also containing these special nodes. These child lists may have one or more children of their own, and so on, to produce a multilevel data structure as shown in the example below.
Given the head of the first level of the list, flatten the list so that all the nodes appear in a single-level, doubly linked list. Let curr be a node with a child list. The nodes in the child list should appear after curr and before curr.next in the flattened list.
Return the head of the flattened list. The nodes in the list must have all of their child pointers set to null.
"""
# Definition for a Node.
class Node:
def __init__(self, val, prev, next, child):
self.val = val
self.prev = prev
self.next = next
self.child = child
"""
class Solution:
def flatten(self, head: 'Optional[Node]') -> 'Optional[Node]':
stack=[]
cur=head
pre=None
while cur or stack:
if not cur:
cur=stack.pop()
cur.prev=pre
pre.next=cur
while cur.child:
if cur.next:
stack.append(cur.next)
curnext=cur.child
curchild=cur.child
cur.child=None
curchild.prev=cur
cur.next=curnext
cur=curnext
if not cur.child:
pre=cur
cur=cur.next
return head
#
class Solution:
def flatten(self, head: 'Node') -> 'Node':
#DFS...
curr=head
tempStack = []
while curr:
if curr.child:
if curr.next:
tempStack.append(curr.next);
curr.next, curr.child.prev, curr.child = curr.child, curr, None;
if not curr.next and len(tempStack):
temp = tempStack.pop();
temp.prev, curr.next = curr, temp
curr = curr.next
return head
#ANSWER PREORDER child is left tree next is right tree
"""
# Definition for a Node.
class Node(object):
def __init__(self, val, prev, next, child):
self.val = val
self.prev = prev
self.next = next
self.child = child
"""
class Solution(object):
def flatten(self, head):
if not head:
return head
# pseudo head to ensure the `prev` pointer is never none
pseudoHead = Node(None, None, head, None)
self.flatten_dfs(pseudoHead, head)
# detach the pseudo head from the real head
pseudoHead.next.prev = None
return pseudoHead.next
def flatten_dfs(self, prev, curr):
""" return the tail of the flatten list """
if not curr:
return prev
curr.prev = prev
prev.next = curr
# the curr.next would be tempered in the recursive function
tempNext = curr.next
tail = self.flatten_dfs(curr, curr.child)
curr.child = None
return self.flatten_dfs(tail, tempNext)
#preorder interative
class Solution(object):
def flatten(self, head):
if not head:
return
pseudoHead = Node(0,None,head,None)
prev = pseudoHead
stack = []
stack.append(head)
while stack:
curr = stack.pop()
prev.next = curr
curr.prev = prev
if curr.next:
stack.append(curr.next)
if curr.child:
stack.append(curr.child)
# don't forget to remove all child pointers.
curr.child = None
prev = curr
# detach the pseudo head node from the result.
pseudoHead.next.prev = None
return pseudoHead.next
###USING STACK
class Solution:
def flatten(self, head: 'Optional[Node]') -> 'Optional[Node]':
if not head: return head
res = head
stack = []
pre = None
while head:
if head.child:
next = head.child
stack.append(head.next)
if head.next:
head.next.prev = None
head.next = head.child
head.child.prev = head
head.child = None
else:
next = head.next
pre = head
head = next
cur = pre
while stack:
cur.next = stack.pop()
if cur.next:
cur.next.prev =cur
while cur.next:
cur = cur.next
#cur = res
#while cur:
# print(cur.val,cur.prev.val if cur.prev else ',', cur.next.val if cur.next else ',')
# cur = cur.next
return res