此专栏追求代码的精简和技巧性,默认已看过题目,? 没看过的话点标题可以跳转链接,咱们一起体验炫酷的 Python
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
d = {}
for i, n in enumerate(nums):
if n in d: return [d[n], i]
d[target-n] = i
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode, carry=0) -> ListNode:
if not (l1 or l2): return ListNode(1) if carry else None
l1, l2 = l1 or ListNode(0), l2 or ListNode(0)
val = l1.val + l2.val + carry
l1.val, l1.next = val % 10, self.addTwoNumbers(l1.next, l2.next, val > 9)
return l1
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
b, m, d = 0, 0, {}
for i, l in enumerate(s): b, m, d[l] = max(b, d.get(l, -1) + 1), max(m, i - b), i
return max(m, len(s) - b)
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
a, b, m = *sorted((nums1, nums2), key=len), (len(nums1) + len(nums2) - 1) // 2
self.__class__.__getitem__ = lambda self, i: m-i-1 < 0 or a[i] >= b[m-i-1]
i = bisect.bisect_left(self, True, 0, len(a))
r = sorted(a[i:i+2] + b[m-i:m-i+2])
return (r[0] + r[1 - (len(a) + len(b)) % 2]) / 2
class Solution:
def longestPalindrome(self, s: str) -> str:
r = ''
for i, j in [(i, j) for i in range(len(s)) for j in (0, 1)]:
while i > -1 and i + j < len(s) and s[i] == s[i + j]: i, j = i - 1, j + 2
r = max(r, s[i + 1:i + j], key=len)
return '' if not s else r
class Solution:
def reverse(self, x):
r = x // max(1, abs(x)) * int(str(abs(x))[::-1])
return r if r.bit_length() < 32 or r == -2**31 else 0
class Solution:
def myAtoi(self, s: str) -> int:
return max(min(int(*re.findall('^[\+\-]?\d+', s.lstrip())), 2**31 - 1), -2**31)
^:匹配字符串开头,[\+\-]:代表一个+字符或-字符,?:前面一个字符可有可无,\d:一个数字,+:前面一个字符的一个或多个,\D:一个非数字字符,*:前面一个字符的0个或多个
max(min(数字, 2**31 - 1), -2**31)
用来防止结果越界class Solution:
def isPalindrome(self, x: int) -> bool:
return str(x) == str(x)[::-1]
不使用字符串的进阶解法:
class Solution:
def isPalindrome(self, x: int) -> bool:
r = list(map(lambda i: int(10**-i * x % 10), range(int(math.log10(x)), -1, -1))) if x > 0 else [0, x]
return r == r[::-1]
class Solution:
def maxArea(self, height: List[int]) -> int:
res, l, r = 0, 0, len(height) - 1
while l < r: res, l, r = (max(res, height[l] * (r - l)), l + 1, r) if height[l] < height[r] else (max(res, height[r] * (r - l)), l, r - 1)
return res
class Solution:
def romanToInt(self, s: str) -> int:
d = {'I':1, 'IV':3, 'V':5, 'IX':8, 'X':10, 'XL':30, 'L':50, 'XC':80, 'C':100, 'CD':300, 'D':500, 'CM':800, 'M':1000}
return sum([d.get(s[max(i-1, 0):i+1], d[n]) for i, n in enumerate(s)])
class Solution:
def longestCommonPrefix(self, strs: List[str]) -> str:
r = [len(set(c)) == 1 for c in zip(*strs)] + [0]
return strs[0][:r.index(0)] if strs else ''
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums, r = sorted(nums), set()
for i in [i for i in range(len(nums)-2) if i < 1 or nums[i] > nums[i-1]]:
d = {-nums[i]-n: j for j, n in enumerate(nums[i + 1:])}
r.update([(nums[i], n, -nums[i]-n) for j, n in enumerate(nums[i+1:]) if n in d and d[n] > j])
return list(map(list, r))
第一题 Two Sum
,用字典记录{需要的值:当前索引},如果字典中存在相同的数字,那么将会记录比较大的那个索引,因此可以用d[n] > i
来避免一个元素重复选择(nums[i], n, -nums[i]-n)
保证了列表升序class Solution:
def threeSumClosest(self, nums: List[int], target: int) -> int:
nums, r, end = sorted(nums), float('inf'), len(nums) - 1
for c in range(len(nums) - 2):
i, j = max(c + 1, bisect.bisect_left(nums, target - nums[end] - nums[c], c + 1, end) - 1), end
while r != target and i < j:
s = nums[c] + nums[i] + nums[j]
r, i, j = min(r, s, key=lambda x: abs(x - target)), i + (s < target), j - (s > target)
return r
class Solution:
def isValid(self, s: str) -> bool:
while any(('()' in s, '[]' in s, '{}' in s)): s = s.replace('()', '').replace('[]', '').replace('{}', '')
return not s
不断删除有效括号直到不能删除,思路简单效率低。另外,stack的方法也很简单,而且快多了。
class Solution:
def isValid(self, s: str) -> bool:
stack, d = [], {'{': '}', '[': ']', '(': ')'}
for p in s:
if p in '{[(':
stack += [p];
elif not (stack and d[stack.pop()] == p):
return False
return not stack
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
if l1 and l2:
if l1.val > l2.val: l1, l2 = l2, l1
l1.next = self.mergeTwoLists(l1.next, l2)
return l1 or l2
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
r, n, p = [], lists and lists.pop(), None
while lists or n: r[len(r):], n = ([n], n.next or lists and lists.pop()) if n else ([], lists.pop())
for n in sorted(r, key=lambda x: x.val, reverse=True): n.next, p = p, n
return n if r else []
本题思路:
如何把所有节点放进 r(result link)?
我们首先初始化 r 为空列表,初始化 n(node) 为题目所给的第一个链表的开头节点,并删除lists中的这个节点,接着进入while循环,如果 n 不为空,那么 r += [n],这里使用了切片的技巧(r[len®:]=[n]相当于r=r+[n]),n=n.next,如果n是第一个链表的最后一个节点的话n.next就是None,下一次while的时候如果lists不为空就说明还有别的链表,此时n为None,我们让 r 不变,n=lists.pop(),也就是从lists中再取下一个节点赋值给n,重复以上步骤直到 lists 为空,我们就把所有节点放进 r 了。
怎么对 r 排序?
用了sorted函数,其中key定义了排序时用来比较的是每个元素的val属性,同时设置reverse为True代表降序排序。
如何修改每个节点的指针?
我们初始化 p(previous node) 为None。遍历降序排好的列表 r,r中的第一个元素就是值最大的元素,也就是我们应该返回的链表的结尾,我们设置它指向None,然后让p=这个节点,继续for循环。之后每经过一个节点 n 就把这个节点的next属性设置为上一个节点 p,遍历完成之后的 n,也就是我们遍历经过的最后一个元素,拥有最小的值,自然就是整个新链表的起始节点,我们将其作为输出值,函数返回。
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
for i in range(len(nums)-1, 0, -1):
if nums[i] == nums[i-1]: nums.pop(i)
return len(nums)
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
i = 0
for j in range(1, len(nums)):
if nums[j] != nums[i]:
nums[i + 1] = nums[j]
i += 1
return i + 1 if nums else 0
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
return haystack.find(needle)
不用内置函数也可以
class Solution:
def strStr(self, haystack: 'str', needle: 'str') -> 'int':
for i in range(0, len(haystack) - len(needle) + 1):
if haystack[i:i+len(needle)] == needle:
return i
return -1
class Solution:
def search(self, nums, target):
self.__class__.__getitem__ = lambda self, m: not(target < nums[0] <= nums[m] or nums[0] <= nums[m] < target or nums[m] < target <= nums[-1])
i = bisect.bisect_left(self, True, 0, len(nums))
return i if target in nums[i:i+1] else -1
class Solution:
def search(self, nums, target):
lo, hi, k = 0, len(nums) - 1, -1
while lo <= hi:
m = (lo + hi) // 2
if m == len(nums) - 1 or nums[m] > nums[m+1]:
k = m + 1
break
elif m == 0 or nums[m] < nums[m-1]:
k = m
break
if nums[m] > nums[0]:
lo = m + 1
else:
hi = m - 1
i = (bisect.bisect_left(nums[k:] + nums[:k], target) + k) % max(len(nums), 1)
return i if nums and nums[i] == target else -1
class Solution:
def countAndSay(self, n: int) -> str:
return '1' * (n is 1) or re.sub(r'(.)\1*', lambda m: str(len(m.group())) + m.group(1), self.countAndSay(n - 1))
class Solution:
def multiply(self, num1: str, num2: str) -> str:
d = {}
for i, n1 in enumerate(num1[::-1]):
for j, n2 in enumerate(num2[::-1]): d[i + j] = d.get(i + j, 0) + int(n1) * int(n2)
for k in [*d]: d[k + 1], d[k] = d.get(k + 1, 0) + int(d[k] * 0.1), d[k] % 10
return re.sub('^0*', '', ''.join(map(str, d.values()))[::-1]) or '0'
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
return [[n] + sub for i, n in enumerate(nums) for sub in self.permute(nums[:i] + nums[i+1:])] or [nums]
每次固定第一个数字递归地排列数组剩余部分
python 有内置函数可以直接实现
class Solution:
def permute(self, nums: List[int]) -> List[List[int]]:
from itertools import permutations
return list(permutations(nums))
class Solution:
def maxSubArray(self, nums):
from functools import reduce
return reduce(lambda r, x: (max(r[0], r[1]+x), max(r[1]+x,x)), nums, (max(nums), 0))[0]
reduce 函数详解
r[0]代表以当前位置为结尾的局部最优解
r[1]代表全局最优解
直接DP的解法更好理解一些
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
for i in range(1, len(nums)):
nums[i] = max(nums[i], nums[i] + nums[i-1])
return max(nums)
class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
return matrix and [*matrix.pop(0)] + self.spiralOrder([*zip(*matrix)][::-1])
[*matrix.pop(0)]
而不是matrix.pop(0)
?因为对于后面的递归,传进来的列表中元素是tupleclass Solution:
def lengthOfLastWord(self, s: str) -> int:
return len(s.strip(' ').split(' ')[-1])
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
r, n = [[n**2]], n**2
while n > 1: n, r = n - len(r), [[*range(n - len(r), n)]] + [*zip(*r[::-1])]
return r
|| => |9| => |8| |6 7| |4 5| |1 2 3|
|9| => |9 8| => |9 6| => |8 9 4|
|8 7| |7 6 5|
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def rotateRight(self, head: ListNode, k: int) -> ListNode:
l = []
while head: l[len(l):], head = [head], head.next
if l: l[-1].next, l[-1 - k % len(l)].next = l[0], None
return l[- k % len(l)] if l else None
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
return int(math.factorial(m+n-2)/math.factorial(m-1)/math.factorial(n-1))
class Solution:
def plusOne(self, digits: List[int]) -> List[int]:
return list(map(int, str(int(''.join(map(str, digits))) + 1)))
class Solution:
def mySqrt(self, x: int) -> int:
return int(x ** 0.5)
出题者应该是希望看到下面的答案:
class Solution:
def mySqrt(self, x: int) -> int:
r = x
while r*r > x:
r = (r + x/r) // 2
return int(r)
class Solution:
def climbStairs(self, n: int) -> int:
from functools import reduce
return reduce(lambda r, _: (r[1], sum(r)), range(n), (1, 1))[0]
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
from itertools import combinations
return sum([list(combinations(nums, i)) for i in range(len(nums) + 1)], [])
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
while n > 0: nums1[m+n-1], m, n = (nums1[m-1], m-1, n) if m and nums1[m-1] > nums2[n-1] else (nums2[n-1], m, n-1)
这种题倒着算更容易
上面那行代码其实就相当于:
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
"""
Do not return anything, modify nums1 in-place instead.
"""
while n > 0:
if m and nums1[m-1] > nums2[n-1]:
nums1[m+n-1], m, n = nums1[m-1], m-1, n
else:
nums1[m+n-1], m, n = nums2[n - 1], m, n-1
class Solution:
def grayCode(self, n: int) -> List[int]:
return (lambda r: r + [x | 1<<n-1 for x in r[::-1]])(self.grayCode(n-1)) if n else [0]
[0]
[0 1]
[00 01 11 10]
[000 001 011 010 110 111 101 100]
(011 → 110)
,相当于 3 * 2的1次方class Solution:
def grayCode(self, n: int) -> List[int]:
r = [0]
for i in range(n):
r.extend([x | 1<<i for x in r[::-1]])
return r
class Solution:
def grayCode(self, n: int) -> List[int]:
return [i ^ i >> 1 for i in range(1 << n)]
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
f = self.inorderTraversal
return f(root.left) + [root.val] + f(root.right) if root else []
class Solution:
def inorderTraversal(self, root: TreeNode) -> List[int]:
r, stack = [], []
while True:
while root:
stack.append(root)
root = root.left
if not stack:
return r
node = stack.pop()
r.append(node.val)
root = node.right
return r
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def maxDepth(self, root: TreeNode) -> int:
return max(map(self.maxDepth,(root.left, root.right))) + 1 if root else 0
class Solution:
def maxProfit(self, prices: List[int]) -> int:
from functools import reduce
return reduce(lambda r, p: (max(r[0], p-r[1]), min(r[1], p)), prices, (0, float('inf')))[0]
class Solution:
def maxProfit(self, prices: List[int]) -> int:
r, m = 0, float('inf')
for p in prices:
r, m = max(r, p - m), min(m, p)
return r
class Solution:
def maxProfit(self, prices: List[int]) -> int:
return sum(b - a for a, b in zip(prices, prices[1:]) if b > a)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def maxPathSum(self, root: TreeNode, ok=True) -> int:
if not root: return 0
l, r = self.maxPathSum(root.left, False), self.maxPathSum(root.right, False)
self.max = max(getattr(self, 'max', float('-inf')), l + root.val + r)
return self.max if ok else max(root.val + max(l, r), 0)
max(以当前节点为结尾的最大路径和,0)
。并更新最大值全局最大路径和=max(全局最大路径和,当前节点值+左子树返回结果+右子树返回结果)
class Solution:
def singleNumber(self, nums: List[int]) -> int:
from functools import reduce
return reduce(int.__xor__, nums)
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def hasCycle(self, head):
"""
:type head: ListNode
:rtype: bool
"""
while head and head.val != None: head.val, head = None, head.next
return head != None
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def hasCycle(self, head):
slow = fast = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if slow == fast:
return True
return False
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def detectCycle(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
s = {None}
while head not in s:
s.add(head)
head = head.next
return head
2(H + D) = H + D + nL
,因此可以推出 H = nL - D
,这意味着如果我们让俩个慢指针一个从 head 出发,一个从 X 出发的话,他们一定会在节点 E 相遇 _____
/ \
head___________E \
\ /
X_____/
class Solution(object):
def detectCycle(self, head):
slow = fast = head
while fast and fast.next:
fast = fast.next.next
slow = slow.next
if slow == fast:
break
else:
return None
while head is not slow:
head = head.next
slow = slow.next
return head
class LRUCache(object):
def __init__(self, capacity):
self.od, self.cap = collections.OrderedDict(), capacity
def get(self, key):
if key not in self.od: return -1
self.od.move_to_end(key)
return self.od[key]
def put(self, key, value):
if key in self.od: del self.od[key]
elif len(self.od) == self.cap: self.od.popitem(False)
self.od[key] = value
# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def sortList(self, head: ListNode) -> ListNode:
if not (head and head.next): return head
pre, slow, fast = None, head, head
while fast and fast.next: pre, slow, fast = slow, slow.next, fast.next.next
pre.next = None
return self.mergeTwoLists(*map(self.sortList, (head, slow)))
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
if l1 and l2:
if l1.val > l2.val: l1, l2 = l2, l1
l1.next = self.mergeTwoLists(l1.next, l2)
return l1 or l2
class Solution(object):
def sortList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
def partition(start, end):
node = start.next.next
pivotPrev = start.next
pivotPrev.next = end
pivotPost = pivotPrev
while node != end:
temp = node.next
if node.val > pivotPrev.val:
node.next = pivotPost.next
pivotPost.next = node
elif node.val < pivotPrev.val:
node.next = start.next
start.next = node
else:
node.next = pivotPost.next
pivotPost.next = node
pivotPost = pivotPost.next
node = temp
return [pivotPrev, pivotPost]
def quicksort(start, end):
if start.next != end:
prev, post = partition(start, end)
quicksort(start, prev)
quicksort(post, end)
newHead = ListNode(0)
newHead.next = head
quicksort(newHead, None)
return newHead.next
class MinStack:
def __init__(self):
self.data = [(None, float('inf'))]
def push(self, x: 'int') -> 'None':
self.data.append((x, min(x, self.data[-1][1])))
def pop(self) -> 'None':
if len(self.data) > 1: self.data.pop()
def top(self) -> 'int':
return self.data[-1][0]
def getMin(self) -> 'int':
return self.data[-1][1]
# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(x)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def getIntersectionNode(self, headA, headB):
"""
:type head1, head1: ListNode
:rtype: ListNode
"""
a, b = (headA, headB) if headA and headB else (None, None)
while a != b: a, b = not a and headB or a.next, not b and headA or b.next
return a
class Solution:
def findPeakElement(self, nums: List[int]) -> int:
self.__class__.__getitem__ = lambda self, i: i and nums[i - 1] > nums[i]
return bisect.bisect_left(self, True, 0, len(nums)) - 1
class Solution:
def majorityElement(self, nums: List[int]) -> int:
return sorted(nums)[len(nums) // 2]
class Solution:
def rob(self, nums: List[int]) -> int:
from functools import reduce
return reduce(lambda r, n: (max(r[0], n + r[1]), r[0]), nums, (0, 0))[0]
class Solution:
def rob(self, nums: List[int]) -> int:
last, now = 0, 0
for i in nums:
last, now = now, max(last + i, now)
return now
class Solution(object):
def numIslands(self, grid):
def sink(i, j):
if 0 <= i < len(grid) and 0 <= j < len(grid[i]) and int(grid[i][j]):
grid[i][j] = '0'
for i, j in zip((i, i+1, i, i-1), (j+1, j, j-1, j)): sink(i, j)
return 1
return 0
return sum(sink(i, j) for i in range(len(grid)) for j in range(len(grid[i])))
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseList(self, head: ListNode, tail=None) -> ListNode:
if head: head.next, tail, head = tail, head, head.next
return self.reverseList(head, tail) if head else tail
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
p = None
while head: head.next, p, head = p, head, head.next
return p
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
return sorted(nums)[-k]
class Solution:
def findKthLargest(self, nums: List[int], k: int) -> int:
l = [x for x in nums if x > nums[0]]
m = [x for x in nums if x == nums[0]]
r = [x for x in nums if x < nums[0]]
f = self.findKthLargest
if k <= len(l):
return f(l, k)
elif k <= len(l) + len(m):
return nums[0]
return f(r, k - len(l) - len(m))
class Solution:
def containsDuplicate(self, nums: List[int]) -> bool:
return len(nums) != len(set(nums))
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def kthSmallest(self, root, k):
from itertools import chain, islice
def gen(x): yield from chain(gen(x.left), [x.val], gen(x.right)) if x else ()
return next(islice(gen(root), k - 1, k))
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution(object):
def kthSmallest(self, root, k):
"""
:type root: TreeNode
:type k: int
:rtype: int
"""
res = []
self.visitNode(root, res)
return res[k - 1]
# 中序遍历
def visitNode(self, root, res):
if root is None:
return
self.visitNode(root.left, res)
res.append(root.val)
self.visitNode(root.right, res)
class Solution:
def isPowerOfTwo(self, n: int) -> bool:
"""
:type n: int
:rtype: bool
"""
return n > 0 and n & n - 1 == 0
class Solution(object):
def isPowerOfTwo(self, n):
return n > 0 and 2**int(math.log2(n)) == n
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root, p, q):
while (root.val - p.val) * (root.val - q.val) > 0: root = (root.left, root.right)[p.val > root.val]
return root
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
l, r = map(lambda x: x and self.lowestCommonAncestor(x, p, q), (root.left, root.right))
return (root in (p, q) or l and r) and root or l or r
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def deleteNode(self, node):
"""
:type node: ListNode
:rtype: void Do not return anything, modify node in-place instead.
"""
node.val, node.next = node.next.val, node.next.next
node = node.next
是不行的,因为这里只是改了函数参数引用的对象,而原来传进来的 node 没有任何改变node = node.next
,那么我们只是换了钥匙,变成了打开 A.next 的门的对应的钥匙,因此链表没有被修改, A没有被修改,只是我们手里的钥匙变了。而如果我们直接写node.val, node.next = node.next.val, node.next.next
,就相当于我们先用钥匙找到 A 的门,然后修改了 A 的属性,链表发生变化class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
res, l, r = [1] * len(nums), 1, 1
for i, j in zip(range(len(nums)), reversed(range(len(nums)))):
res[i], l = res[i] * l, l * nums[i]
res[j], r = res[j] * r, r * nums[j]
return res
class Solution:
def searchMatrix(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: bool
"""
return any(target in row for row in matrix)
class Solution:
def searchMatrix(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: bool
"""
j = -1
for row in matrix:
while j > -len(row) and row[j] > target:
j -= 1
if row and row[j] == target:
return True
return False
class Solution:
def missingNumber(self, nums: List[int]) -> int:
return int(len(nums) * (len(nums) + 1) / 2 - sum(nums))
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
nums.sort(key=bool, reverse=True)
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
i = 0
for i, n in enumerate(filter(lambda x: x, nums)):
nums[i] = n
for i in range(i + 1, len(nums)):
nums[i] = 0
class Solution:
def canWinNim(self, n: int) -> bool:
return bool(n % 4)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def oddEvenList(self, head: ListNode) -> ListNode:
if not head or not head.next: return head
r, odd, p, head = head, head, head.next, head.next.next
while head:
odd.next, head.next, p.next = head, odd.next, head.next
p, odd, head = p.next, head, p.next and p.next.next
return r
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
s.reverse()
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
return [k for k, v in collections.Counter(nums).most_common(k)]
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
d = {}
for n in nums:
d[n] = d.get(n, 0) + 1
return sorted(d.keys(), key=d.get)[-k:]
class Solution:
def isPerfectSquare(self, num: int) -> bool:
r = num
while r * r > num:
r = (r + num / r) // 2
return r * r == num
(r + num / r) / 2
>= √num 而 r > num / r 保证每次迭代 r 在不断减小,而//
的存在保证最接近的时候能够逃离循环体class Solution:
def fizzBuzz(self, n):
return ['Fizz' * (not i % 3) + 'Buzz' * (not i % 5) or str(i) for i in range(1, n+1)]
class Solution:
def thirdMax(self, nums: List[int]) -> int:
nums = set(nums)
for _ in range((2, 0)[len(nums) < 3]): nums.remove(max(nums))
return max(nums)
class Solution:
def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
s = set(nums)
return [i for i in range(1, len(nums) + 1) if i not in s]
class Solution:
def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
for n in nums:
nums[abs(n) - 1] = -abs(nums[abs(n) - 1])
return [i + 1 for i, n in enumerate(nums) if n > 0]
8
,2
,-3,-1]class Solution:
def hammingDistance(self, x: int, y: int) -> int:
return bin(x ^ y).count('1')
class Solution:
def reverseWords(self, s: str) -> str:
return ' '.join(s.split(' ')[::-1])[::-1]
class Solution:
def openLock(self, deadends: List[str], target: str) -> int:
if '0000' in deadends: return -1
deadends, q = set(deadends), [('0000', 0)]
while q:
node, step = q.pop(0)
for i, add in zip([*range(4)] * 2, [1] * 4 + [-1] * 4):
cur = node[:i] + str((int(node[i]) + add) % 10) + node[i+1:]
if cur == target: return step + 1
if not cur in deadends:
q.append((cur, step + 1))
deadends.add(cur)
return -1
class Solution:
def numJewelsInStones(self, J: str, S: str) -> int:
return sum(S.count(i) for i in J)
class Solution:
def numJewelsInStones(self, J: str, S: str) -> int:
j = set(J)
return sum(s in j for s in S)
class Solution:
def transpose(self, A: List[List[int]]) -> List[List[int]]:
return [*zip(*A)]
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def rangeSumBST(self, root: TreeNode, L: int, R: int) -> int:
return root and root.val * (L <= root.val <= R) + self.rangeSumBST(root.left, L, R) + self.rangeSumBST(root.right, L, R) or 0
class Solution(object):
def isAlienSorted(self, words, order):
return words == sorted(words, key=lambda w: [order.index(x) for x in w])
充分利用 python 序列比较的特点,sorted 的参数 key 可传入一个函数,sorted 函数会将每个元素作为输入,输入到 key 函数并获得返回值,整个序列将按此值的大小来排序。此处 key 函数为lambda w: [order.index(x) for x in w]
,其为words中每个单词 word 返回一个 list,list 中每个元素为单词中字母 x 在 order 中的索引。比如当 order 为 ‘abcde……’ 时,单词 ‘cab’ 将返回 [3, 2, 1]。关于俩个 list 的大小比较,服从 python 序列比较的特性,请参考官方文档教程 5.8 节内容。
另外一个通用的方法是简单的数学计算,给每个单词赋予一个数字然后排序对比和原来的数组是否一致即可,每个字母的价值按字母表顺序,第几个就代表几,每进一位需要*10^-2
避免冲突,比如字母表是abcde……
,单词 cab 的价值就是 3 * 1 + 1 * 0.01 + 2 * 0.0001
,价值越小的单词位置应该越靠前
class Solution:
def isAlienSorted(self, words: List[str], order: str) -> bool:
d = {c: i + 1 for i, c in enumerate(order)}
return sorted(words, key=lambda x: sum(d[c] * 10**(-2 * i) for i, c in enumerate(x))) == words
class Solution:
def kClosest(self, points: List[List[int]], K: int) -> List[List[int]]:
return sorted(points, key=lambda x: x[0]**2 + x[1]**2)[:K]
以上是一张互联网公司面试中经常考察的问题类型总结的思维导图,此栏目将根据 LeetCode 中文版探索板块给出的路线制作题解,各专栏将尽力覆盖各大知识要点并总结知识点和套路。相比于题库解析部分追求代码的绝对精简,本专题追求以高可读性呈现各大专题的常规思路,为后续的题库解析部分做铺垫。俩部分题目可能重复,但专题部分会有更详细的解析,且可能运用不同解法。
遍历
和 搜索最短路径
class Solution(object):
def BFS(self):
# 1.使用 queue.Queue 初始化队列
# 2.选择合适的根节点压入队列
# 3.使用 wile 进入队列循环,直到搜索完毕
# {
# 4.取出一个节点
# 5.放入这个节点周围的节点
# }
队列:先入先出的数据结构
class MyCircularQueue:
def __init__(self, k: int):
"""
Initialize your data structure here. Set the size of the queue to be k.
"""
self.size = k
self.data = []
def enQueue(self, value: int) -> bool:
"""
Insert an element into the circular queue. Return true if the operation is successful.
"""
if self.isFull():
return False
self.data.append(value)
return True
def deQueue(self) -> bool:
"""
Delete an element from the circular queue. Return true if the operation is successful.
"""
if self.isEmpty():
return False
self.data.pop(0)
return True
def Front(self) -> int:
"""
Get the front item from the queue.
"""
if self.isEmpty():
return -1
return self.data[0]
def Rear(self) -> int:
"""
Get the last item from the queue.
"""
if self.isEmpty():
return -1
return self.data[-1]
def isEmpty(self) -> bool:
"""
Checks whether the circular queue is empty or not.
"""
return not self.data
def isFull(self) -> bool:
"""
Checks whether the circular queue is full or not.
"""
return len(self.data) == self.size
# Your MyCircularQueue object will be instantiated and called as such:
# obj = MyCircularQueue(k)
# param_1 = obj.enQueue(value)
# param_2 = obj.deQueue()
# param_3 = obj.Front()
# param_4 = obj.Rear()
# param_5 = obj.isEmpty()
# param_6 = obj.isFull()
队列和广度优先搜索
from queue import Queue
class Solution(object):
def numIslands(self, grid):
try:
r = 0; m = len(grid); n = len(grid[0])
around = ((0, 1), (1, 0), (0, -1), (-1, 0))
except:
return 0
for i in range(m):
for j in range(n):
if int(grid[i][j]):
r += 1
#---------------------------BFS 开始-----------------------------
# 把根节点投入队列
q = Queue()
q.put((i, j))
# 开始循环
while not q.empty():
# 取出还未沉没的陆地节点并沉没陆地(防止下次遍历到的时候再算一遍)
x, y = q.get()
if int(grid[x][y]):
grid[x][y] = '0'
# 放入周围的陆地节点
for a, b in around:
a += x; b += y;
if 0 <= a < m and 0 <= b < n and int(grid[a][b]):
q.put((a, b))
#----------------------------------------------------------------
return r
from queue import Queue
class Solution:
def openLock(self, deadends: List[str], target: str) -> int:
deadends = set(deadends) # in 操作在set中时间复杂度为O(1)
if '0000' in deadends:
return -1
# -------------------------------BFS 开始----------------------------------
# 初始化根节点
q = Queue()
q.put(('0000', 0)) # (当前节点值,转动步数)
# 开始循环队列
while not q.empty():
# 取出一个节点
node, step = q.get()
# 放入周围节点
for i in range(4):
for add in (1, -1):
cur = node[:i] + str((int(node[i]) + add) % 10) + node[i+1:]
if cur == target:
return step + 1
if not cur in deadends:
q.put((cur, step + 1))
deadends.add(cur) # 避免重复搜索
# -------------------------------------------------------------------------
return -1
注:此处贡献名单仅代表汇总搜集贡献,不代表全部原创,欢迎所有更短的解法?