[关闭]
@thousfeet 2020-11-13T22:58:48.000000Z 字数 45548 阅读 609

来刷题啊 Top100 Liked Problems

LeetCode


617. Merge Two Binary Trees

Given two binary trees and imagine that when you put one of them to cover the other, some nodes of the two trees are overlapped while the others are not.
You need to merge them into a new binary tree. The merge rule is that if two nodes overlap, then sum node values up as the new value of the merged node. Otherwise, the NOT null node will be used as the node of new tree.

Example 1:

Input:
Tree 1 Tree 2
1 2
/ \ / \
3 2 1 3
/ \ \
5 4 7
Output:
Merged tree:
3
/ \
4 5
/ \ \
5 4 7

Note: The merging process must start from the root nodes of both trees.

【题意】
二叉树合并,把相同位置的val加和

【思路】
根节点按要求加和,左右节点扔进递归

【代码】

  1. # Definition for a binary tree node.
  2. # class TreeNode:
  3. # def __init__(self, val=0, left=None, right=None):
  4. # self.val = val
  5. # self.left = left
  6. # self.right = right
  7. class Solution:
  8. def mergeTrees(self, t1: TreeNode, t2: TreeNode) -> TreeNode:
  9. if t1 or t2:
  10. new_root = TreeNode()
  11. else:
  12. return
  13. if t1:
  14. new_root.val += t1.val
  15. if t2:
  16. new_root.val += t2.val
  17. if t1 and t2:
  18. new_root.left = self.mergeTrees(t1.left, t2.left)
  19. new_root.right = self.mergeTrees(t1.right, t2.right)
  20. elif t1:
  21. new_root.left = self.mergeTrees(t1.left, None)
  22. new_root.right = self.mergeTrees(t1.right, None)
  23. elif t2:
  24. new_root.left = self.mergeTrees(None, t2.left)
  25. new_root.right = self.mergeTrees(None, t2.right)
  26. return new_root

【discussion】
简洁写法 啊呜呜呜突然觉得自己写的也太丑了

  1. def mergeTrees(self, t1, t2):
  2. if t1 and t2:
  3. root = TreeNode(t1.val + t2.val)
  4. root.left = self.mergeTrees(t1.left, t2.left)
  5. root.right = self.mergeTrees(t1.right, t2.right)
  6. return root
  7. else:
  8. return t1 or t2

104. Maximum Depth of Binary Tree

Given a binary tree, find its maximum depth.
The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.
Note: A leaf is a node with no children.
Example:
Given binary tree [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
return its depth = 3.

【题意】
求二叉树的树深

【代码】

  1. class Solution:
  2. def maxDepth(self, root: TreeNode) -> int:
  3. if root==None:
  4. return 0
  5. cnt = 0
  6. que = [root]
  7. while len(que):
  8. cnt += 1
  9. new_que = []
  10. for x in que:
  11. if x.left:
  12. new_que.append(x.left)
  13. if x.right:
  14. new_que.append(x.right)
  15. que = new_que[::]
  16. return cnt

【discussion】
One line solution

  1. def maxDepth(self, root):
  2. return 1 + max(self.maxDepth(root.left), self.maxDepth(root.right)) if root else 0

136. Single Number

Given a non-empty array of integers nums, every element appears twice except for one. Find that single one.
Follow up: Could you implement a solution with a linear runtime complexity and without using extra memory?

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

Constraints:
1 <= nums.length <= 3 * 104
-3 * 104 <= nums[i] <= 3 * 104
Each element in the array appears twice except for one element which appears only once.

【题意】
只有一个数出现了一次 其他都出现了两次 找这个数

【代码】

  1. class Solution:
  2. def singleNumber(self, nums: List[int]) -> int:
  3. ans = nums[0]
  4. for x in nums[1:]:
  5. ans = ans^x
  6. return ans

【discussion】
其实还有多种做法

  1. def singleNumber1(self, nums):
  2. dic = {}
  3. for num in nums:
  4. dic[num] = dic.get(num, 0)+1
  5. for key, val in dic.items():
  6. if val == 1:
  7. return key
  8. def singleNumber2(self, nums):
  9. res = 0
  10. for num in nums:
  11. res ^= num
  12. return res
  13. def singleNumber3(self, nums):
  14. return 2*sum(set(nums))-sum(nums)
  15. def singleNumber4(self, nums):
  16. return reduce(lambda x, y: x ^ y, nums)
  17. def singleNumber(self, nums):
  18. return reduce(operator.xor, nums)

226. Invert Binary Tree

Invert a binary tree.
Example:
Input:
4
/ \
2 7
/ \ / \
1 3 6 9
Output:
4
/ \
7 2
/ \ / \
9 6 3 1

【代码】

  1. class Solution:
  2. def invertTree(self, root: TreeNode) -> TreeNode:
  3. if root==None:
  4. return
  5. self.invertTree(root.left)
  6. self.invertTree(root.right)
  7. tmp = root.left
  8. root.left = root.right
  9. root.right = tmp
  10. return root

【discussion】
更Pythonic的写法

  1. def invertTree(self, root):
  2. if root:
  3. root.left, root.right = self.invertTree(root.right), self.invertTree(root.left)
  4. return root

206. Reverse Linked List

Reverse a singly linked list.
Example:
Input: 1->2->3->4->5->NULL
Output: 5->4->3->2->1->NULL

【思路】
遍历每个节点,插到第一个的前面

【代码】

  1. # Definition for singly-linked list.
  2. # class ListNode:
  3. # def __init__(self, val=0, next=None):
  4. # self.val = val
  5. # self.next = next
  6. class Solution:
  7. def reverseList(self, head: ListNode) -> ListNode:
  8. pre_head = ListNode(next=head)
  9. while head and head.next:
  10. now = head.next
  11. head.next, now.next, pre_head.next = now.next, pre_head.next, now
  12. return pre_head.next

【discussion】
递归的写法

  1. class Solution(object):
  2. def reverseList(self, head, prev=None):
  3. if not head:
  4. return prev
  5. curr, head.next = head.next, prev
  6. return self.reverseList(curr, head)

169. Majority Element

Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.
You may assume that the array is non-empty and the majority element always exist in the array.
Example 1:
Input: [3,2,3]
Output: 3
Example 2:
Input: [2,2,1,1,1,2,2]
Output: 2

【代码】
(1)

  1. class Solution:
  2. def majorityElement(self, nums: List[int]) -> int:
  3. nums.sort()
  4. n = len(nums)
  5. return nums[int(n/2)]

(2)

  1. class Solution:
  2. def majorityElement(self, nums: List[int]) -> int:
  3. num, cnt = 0, 0
  4. for x in nums:
  5. if cnt==0:
  6. num = x
  7. cnt += 1
  8. elif num==x:
  9. cnt += 1
  10. elif num!=x:
  11. cnt -= 1
  12. return num

283. Move Zeroes

Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements.
Example:
Input: [0,1,0,3,12]
Output: [1,3,12,0,0]
Note:
You must do this in-place without making a copy of the array.
Minimize the total number of operations.

【题意】
把数组中的0挪到最后面 要求是in-place操作

【思路】
先想到把0的pop掉然后在加上少掉的0,更好的是用双指针的做法把0和非0的直接交换(没前者好写就没写了orz)

【代码】

  1. class Solution:
  2. def moveZeroes(self, nums: List[int]) -> None:
  3. """
  4. Do not return anything, modify nums in-place instead.
  5. """
  6. length = len(nums)
  7. now = 0
  8. while now<len(nums):
  9. if nums[now]==0:
  10. nums.pop(now)
  11. else:
  12. now+=1
  13. zero_num = length-len(nums)
  14. nums += [0]*zero_num

【discussion】
比双指针做法更简单,因为其实不要想着是和0交换,而是直接按序排下去就好了,第一个非0的要放在数组第一个位置,第二个要放第二个位置,所以当不为0的时候idx++就是正确的位置,最后0都是会被交换到末尾的

  1. def moveZeroes(self, nums):
  2. idx = 0
  3. for i in xrange(len(nums)):
  4. if nums[i] != 0:
  5. nums[i], nums[idx] = nums[idx], nums[i]
  6. zero += 1

448. Find All Numbers Disappeared in an Array

Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements of [1, n] inclusive that do not appear in this array.
Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.
Example:
Input:
[4,3,2,7,8,2,3,1]
Output:
[5,6]

【题意】
找到1~n中没有出现在数组里的数 n=len(nums)

【代码】
没想出来 还是用了额外空间OTL

  1. class Solution:
  2. def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
  3. all_nums = [0]*len(nums)
  4. for x in nums:
  5. all_nums[x-1]=1
  6. ans = []
  7. for i in range(len(nums)):
  8. if all_nums[i]==0:
  9. ans.append(i+1)
  10. return ans

【discussion】
超级机智!!
对nums中的每个数 如果这个数k出现了 就把index=k位置的置为负数,然后遍历一遍找到还是正数的,那这些位置的index就是答案

  1. def findDisappearedNumbers(self, nums):
  2. for num in nums:
  3. index = abs(num) - 1
  4. nums[index] = -abs(nums[index])
  5. return [i + 1 for i, num in enumerate(nums) if num > 0]

21. Merge Two Sorted Lists

Merge two sorted linked lists and return it as a new sorted list. The new list should be made by splicing together the nodes of the first two lists.
Example 1:
Input: l1 = [1,2,4], l2 = [1,3,4]
Output: [1,1,2,3,4,4]
Example 2:
Input: l1 = [], l2 = []
Output: []
Example 3:
Input: l1 = [], l2 = [0]
Output: [0]
Constraints:
The number of nodes in both lists is in the range [0, 50].
-100 <= Node.val <= 100
Both l1 and l2 are sorted in non-decreasing order.

【题意】
合并两个递增的list

【思路】
先建个头,然后两个list的头看下取哪个就拿过来

【代码】

  1. # Definition for singly-linked list.
  2. # class ListNode:
  3. # def __init__(self, val=0, next=None):
  4. # self.val = val
  5. # self.next = next
  6. class Solution:
  7. def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
  8. ans = ListNode()
  9. now = ans
  10. while l1 or l2:
  11. if l1 and l2:
  12. if l1.val < l2.val:
  13. now.next, l1 = l1, l1.next
  14. else:
  15. now.next, l2 = l2, l2.next
  16. else:
  17. now.next = l1 or l2
  18. l1, l2 = l1.next if l1 else l1, l2.next if l2 else l2
  19. now = now.next
  20. return ans.next

【discussion】
递归的写法

  1. def mergeTwoLists2(self, l1, l2):
  2. if not l1 or not l2:
  3. return l1 or l2
  4. if l1.val < l2.val:
  5. l1.next = self.mergeTwoLists(l1.next, l2)
  6. return l1
  7. else:
  8. l2.next = self.mergeTwoLists(l1, l2.next)
  9. return l2

121. Best Time to Buy and Sell Stock

Say you have an array for which the ith element is the price of a given stock on day i.
If you were only permitted to complete at most one transaction (i.e., buy one and sell one share of the stock), design an algorithm to find the maximum profit.
Note that you cannot sell a stock before you buy one.
Example 1:
Input: [7,1,5,3,6,4]
Output: 5
Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
Not 7-1 = 6, as selling price needs to be larger than buying price.
Example 2:
Input: [7,6,4,3,1]
Output: 0
Explanation: In this case, no transaction is done, i.e. max profit = 0.

【题意】
给一list代表了每天的股价,问买一次卖一次最多能赚多少钱

【思路】
先算出每日价格的差 就相当于是最大连续子串和的问题了

【代码】

  1. class Solution:
  2. def maxProfit(self, prices: List[int]) -> int:
  3. days = len(prices)
  4. if days<=1:
  5. return 0
  6. diff = [prices[i]-prices[i-1] for i in range(1,days)]
  7. ans, now = 0, 0
  8. for x in diff:
  9. now+=x
  10. if now<0:
  11. now=0
  12. ans = max(ans, now)
  13. return ans

【discussion】
只遍历一遍 在每个位置更新下当前见过的min_price,然后在这个点卖出的收益就是当前price-min_price

  1. def maxProfit(prices):
  2. ans, min_price = 0, float('inf')
  3. for price in prices:
  4. min_price = min(min_price, price)
  5. profit = price - min_price
  6. ans = max(ans, profit)
  7. return ans

543. Diameter of Binary Tree

Given a binary tree, you need to compute the length of the diameter of the tree. The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root.
Example:
Given a binary tree
1
/ \
2 3
/ \
4 5
Return 3, which is the length of the path [4,2,1,3] or [5,2,1,3].
Note: The length of path between two nodes is represented by the number of edges between them.

【题意】
求二叉树的直径(一节点到另一节点的最长路径)

【思路】
如果知道直径的根是哪个点,那直径就等于以这个点为根的左边最长+右边最长,所以要遍历到每个点上求一下;因为递归求树高的时候就会遍历到所有点,所以直接在求树高的时候顺带更新一下ans

【代码】

  1. class Solution:
  2. def __init__(self):
  3. self.ans = 0
  4. def diameterOfBinaryTree(self, root: TreeNode) -> int:
  5. if not root:
  6. return 0
  7. def length(root):
  8. if not root:
  9. return 0
  10. l, r = length(root.left), length(root.right)
  11. self.ans = max(self.ans, l+r)
  12. return max(l, r)+1
  13. length(root)
  14. return self.ans

(顺带发现 写成内嵌函数会比写成类函数更快)

70. Climbing Stairs

You are climbing a stair case. It takes n steps to reach to the top.
Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
Example 1:
Input: 2
Output: 2
Explanation: There are two ways to climb to the top.
1. 1 step + 1 step
2. 2 steps
Example 2:
Input: 3
Output: 3
Explanation: There are three ways to climb to the top.
1. 1 step + 1 step + 1 step
2. 1 step + 2 steps
3. 2 steps + 1 step
Constraints:
1 <= n <= 45

【题意】
一次可以跨一级台阶或两级台阶,问要上n级台阶有几种走法

【思路】
经典DP,原问题P(N) = P(N-1)+P(N-2),但因为觉得简单写的太随意还错了3次 555。错的点:一定要开数组存memory不然会T,提前判n小于3就返回是因为后面dp[0],1,2的赋值需要保证n>3

  1. class Solution:
  2. def climbStairs(self, n: int) -> int:
  3. if n<3:
  4. return n
  5. dp = [-1]*(n+1)
  6. dp[0], dp[1], dp[2] = 0, 1, 2
  7. def dfs(n):
  8. if dp[n]!=-1:
  9. return dp[n]
  10. else:
  11. dp[n] = dfs(n-1)+dfs(n-2)
  12. return dp[n]
  13. return dfs(n)

【discussion】
非递归的写法

  1. # Bottom up, O(n) space
  2. def climbStairs2(self, n):
  3. if n == 1:
  4. return 1
  5. res = [0 for i in xrange(n)]
  6. res[0], res[1] = 1, 2
  7. for i in xrange(2, n):
  8. res[i] = res[i-1] + res[i-2]
  9. return res[-1]

101. Symmetric Tree

Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).
For example, this binary tree [1,2,2,3,4,4,3] is symmetric:
1
/ \
2 2
/ \ / \
3 4 4 3
But the following [1,2,2,null,3,null,3] is not:
1
/ \
2 2
\ \
3 3

【题意】
判断二叉树是否左右对称

【思路】
递归

【代码】

  1. class Solution:
  2. def isSymmetric(self, root: TreeNode) -> bool:
  3. def issym(left, right):
  4. if left==None and right==None:
  5. return True
  6. elif left==None or right==None:
  7. return False
  8. elif left.val==right.val and issym(left.left, right.right) and issym(left.right, right.left):
  9. return True
  10. else:
  11. return False
  12. if root==None:
  13. return True
  14. return issym(root.left, root.right)

53. Maximum Subarray

Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
Follow up: If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
Example 1:
Input: nums = [-2,1,-3,4,-1,2,1,-5,4]
Output: 6
Explanation: [4,-1,2,1] has the largest sum = 6.
Example 2:
Input: nums = 1
Output: 1
Example 3:
Input: nums = [0]
Output: 0
Example 4:
Input: nums = [-1]
Output: -1

【题意】
求最大连续子序列的最大值(子序列至少要有一个数)

【思路】
最大连续子序列常规操作闭眼写,但那个是默认全为负就取0个数,所以特判一下如果全为负就直接返回最大

【代码】

  1. class Solution:
  2. def maxSubArray(self, nums: List[int]) -> int:
  3. ans, now = 0, 0
  4. flag = False
  5. for x in nums:
  6. if x>0:
  7. flag = True
  8. now += x
  9. if now < 0:
  10. now = 0
  11. ans = max(ans, now)
  12. if flag == False:
  13. return max(nums)
  14. else:
  15. return ans

【discussion】
超级简单的写法,直观的解释就是,num存的是从头开始到我这的最大连续子序列。那么对于每个位置,如果前面的大于0,就对我这有利可以加过来,如果小于0,就放弃掉。
本质是和常规操作一样的想法,但就可以存下每个位置为结尾且至少有一个数的最大连续子序列,然后取max。

  1. for i in range(1, len(nums)):
  2. if nums[i-1] > 0:
  3. nums[i] += nums[i-1]
  4. return max(nums)

1. Two Sum

Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
You can return the answer in any order.
Example 1:
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Output: Because nums[0] + nums1 == 9, we return [0, 1].
Example 2:
Input: nums = [3,2,4], target = 6
Output: [1,2]
Example 3:
Input: nums = [3,3], target = 6
Output: [0,1]
Constraints:
2 <= nums.length <= 105
-109 <= nums[i] <= 109
-109 <= target <= 109
Only one valid answer exists.

【题意】
返回数组中的两个不同的数位置,使得它们的和是target

【思路】
遍历数组中每个数,查target-nums[i]有没有在nums里,这样是O(N^2)

【代码】

  1. class Solution:
  2. def twoSum(self, nums: List[int], target: int) -> List[int]:
  3. for i, x in enumerate(nums):
  4. if target-x in nums:
  5. idx = nums.index(target-x)
  6. if idx==i:
  7. continue
  8. else:
  9. return([i, idx])

【discussion】
O(N)的做法,一边遍历一边用dict记录这个值出现的位置,不同时存d[m]是因为不允许重复,所以就只记录在遍历到此处之前的数

  1. def twoSum(self, nums, target):
  2. d = {}
  3. for i, n in enumerate(nums):
  4. m = target - n
  5. if m in d:
  6. return [d[m], i]
  7. else:
  8. d[n] = i

155. Min Stack

Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
push(x) -- Push element x onto stack.
pop() -- Removes the element on top of the stack.
top() -- Get the top element.
getMin() -- Retrieve the minimum element in the stack.
Example 1:
Input
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]
Output
[null,null,null,null,-3,null,0,-2]
Explanation
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); // return -3
minStack.pop();
minStack.top(); // return 0
minStack.getMin(); // return -2

【题意】
实现一个能getMin的栈

【思路】
除了另外开一个minval数组,专门存从开始到每个位置的最小值,其他就没啥了

【代码】

  1. class MinStack:
  2. def __init__(self):
  3. self.nums = []
  4. self.minval = []
  5. def push(self, x: int) -> None:
  6. self.nums.append(x)
  7. if len(self.minval)==0:
  8. self.minval = [x]
  9. else:
  10. self.minval.append(min(x,self.minval[-1]))
  11. def pop(self) -> None:
  12. self.nums.pop()
  13. self.minval.pop()
  14. def top(self) -> int:
  15. return self.nums[-1]
  16. def getMin(self) -> int:
  17. return self.minval[-1]

198. House Robber

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.
Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.
Example 1:
Input: nums = [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.
Example 2:
Input: nums = [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
Total amount you can rob = 2 + 9 + 1 = 12.

【题意】
只能抢劫不相邻位置的房子,问最多能得多少

【思路】
DP

【代码】

  1. class Solution:
  2. def rob(self, nums: List[int]) -> int:
  3. if len(nums)==0:
  4. return 0
  5. dp = nums[::]
  6. for i, x in enumerate(nums):
  7. if i-2>=0:
  8. dp[i] = max(dp[i], dp[i-2]+nums[i])
  9. if i-1>=0:
  10. dp[i] = max(dp[i], dp[i-1])
  11. return dp[-1]

【discussion】
更节省空间的做法

  1. # Approach 2:- Constant space use two variables and compute the max respectively
  2. prev = curr = 0
  3. for num in nums:
  4. temp = prev # This represents the nums[i-2]th value
  5. prev = curr # This represents the nums[i-1]th value
  6. curr = max(num + temp, prev) # Here we just plug into the formula
  7. return curr

160. Intersection of Two Linked Lists

Write a program to find the node at which the intersection of two singly linked lists begins.

【题意】
给两个链表,他们可能会在最后一部分有交叉(两个轨道汇入一个轨道),返回汇入的这个节点的value,如果没有交叉就返回None,要求时间O(N)空间O(1)

【思路】
第一想法就是遍历一遍把前序节点都找出来,然后反着找最后的交汇点,但是这样空间要多占O(N)。然后想着拆成两条链,先遍历一条扔进set,再看第二条时会遇到set中的值,但发现值不是唯一的,只能判断节点是不是相同而不能判断值。
扫了眼discussion,先把两条链的长度算出来,然后就能知道长的那条要从哪里开始能两条同步找,然后用节点判断。

【代码】

  1. # Definition for singly-linked list.
  2. # class ListNode:
  3. # def __init__(self, x):
  4. # self.val = x
  5. # self.next = None
  6. class Solution:
  7. def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
  8. def getLen(head):
  9. cnt = 0
  10. while head:
  11. cnt+=1
  12. head = head.next
  13. return cnt
  14. alen = getLen(headA)
  15. blen = getLen(headB)
  16. if blen>alen:
  17. headA, headB = headB, headA
  18. alen, blen = blen, alen
  19. diff = alen-blen
  20. for _ in range(diff):
  21. headA = headA.next
  22. while headA:
  23. if headA==headB:
  24. return headA
  25. headA, headB = headA.next, headB.next
  26. return None

234. Palindrome Linked List

Given a singly linked list, determine if it is a palindrome.
Example 1:
Input: 1->2
Output: false
Example 2:
Input: 1->2->2->1
Output: true
Follow up:
Could you do it in O(n) time and O(1) space?

【思路】
没想到O(1)空间的解法
思路就是先遍历一遍得到整条链的长度,然后第二遍搜到一半长度的位置,一边存下前一半的values,然后在后一半和前面的对比。这样是时间O(2N)空间O(N/2)。

【代码】

  1. class Solution:
  2. def isPalindrome(self, head: ListNode) -> bool:
  3. lenth = 0
  4. now = head
  5. while now:
  6. lenth += 1
  7. now = now.next
  8. now = head
  9. vals = []
  10. for i in range(lenth//2):
  11. vals.append(now.val)
  12. now = now.next
  13. if lenth%2:
  14. now = now.next
  15. # print(vals, now.val)
  16. for i in range(lenth//2):
  17. if not now.val==vals[-1]:
  18. return False
  19. else:
  20. vals.pop()
  21. now = now.next
  22. return True

【discussion】
用walk和run指针的想法走到一半的位置(一个一次走两步一个一次走一步),然后把后一半reverse,就可以比较两条链了。不用担心奇数个的问题,因为后一半这样做完reverse之后相当于是两个不同head的链交汇到mid节点的位置。

  1. def isPalindrome(self, head):
  2. fast = slow = head
  3. # find the mid node
  4. while fast and fast.next:
  5. fast = fast.next.next
  6. slow = slow.next
  7. # reverse the second half
  8. node = None
  9. while slow:
  10. nxt = slow.next
  11. slow.next = node
  12. node = slow
  13. slow = nxt
  14. # compare the first and second half nodes
  15. while node: # while node and head:
  16. if node.val != head.val:
  17. return False
  18. node = node.next
  19. head = head.next
  20. return True

20. Valid Parentheses

Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
An input string is valid if:
Open brackets must be closed by the same type of brackets.
Open brackets must be closed in the correct order.
Example 1:
Input: s = "()"
Output: true
Example 2:
Input: s = "()[]{}"
Output: true
Example 3:
Input: s = "(]"
Output: false
Example 4:
Input: s = "([)]"
Output: false
Example 5:
Input: s = "{[]}"
Output: true
Constraints:
1 <= s.length <= 104
s consists of parentheses only '()[]{}'.

【思路】
经典栈题
觉得简单写的太草率还wa了两次orz 没有判最后栈非空、没有判遍历时遇到栈是空的情况

【代码】

  1. class Solution:
  2. def isValid(self, s: str) -> bool:
  3. stack = []
  4. dic = {'(':')', '{':'}', '[':']'}
  5. for x in s:
  6. if x in dic:
  7. stack.append(x)
  8. elif len(stack)==0:
  9. return False
  10. elif x==dic[stack[-1]]:
  11. stack.pop()
  12. else:
  13. return False
  14. if len(stack)!=0:
  15. return False
  16. return True

763. Partition Labels

A string S of lowercase English letters is given. We want to partition this string into as many parts as possible so that each
letter appears in at most one part, and return a list of integers
representing the size of these parts.

Example 1:
Input: S = "ababcbacadefegdehijhklij"
Output: [9,7,8]
Explanation: The partition is "ababcbaca", "defegde", "hijhklij". This is a partition so that each letter appears in at most one part. A partition like "ababcbacadefegde", "hijhklij" is incorrect, because it splits S into less parts.

Note:
S will have length in range [1, 500]. S will consist of lowercase
English letters ('a' to 'z') only.

【题意】
给一字符串,要切成尽量多个片段,并使得同个字母只出现在一个片段

【思路】
记录下每个字母第一次出现的位置和最后一次出现的位置,那么他们中间这一段就必然要连在一起了,再进行片段之间的合并

【代码】

  1. class Solution:
  2. def partitionLabels(self, S: str) -> List[int]:
  3. dic = {}
  4. for i in range(len(S)):
  5. x = S[i]
  6. if x not in dic:
  7. dic[x] = [i,i]
  8. else:
  9. dic[x][1] = i
  10. frag = list(dic.values())
  11. frag.sort()
  12. # print(frag)
  13. ans = []
  14. l, r = frag[0][0], frag[0][2]
  15. for x in frag[1:]:
  16. ll, rr = x[0], x[1]
  17. if ll < r:
  18. r = max(r, rr)
  19. else:
  20. ans.append(r-l+1)
  21. l, r = ll, rr
  22. return ans+[len(S)-sum(ans)]

【discussion】

复杂度更低的解法O(N):遍历两遍,第一遍记录每个字母最后出现的位置,第二遍开始,对于每个看到的字母去查它的最后位置,维护right=max(right,rightmost[now]),直到当前遍历到的就是之前扫过的所有字母的最后位置,说明当前这一段结束了,result+=[...]。

  1. def partition_labels(S):
  2. rightmost = {c:i for i, c in enumerate(S)}
  3. left, right = 0, 0
  4. result = []
  5. for i, letter in enumerate(S):
  6. right = max(right,rightmost[letter])
  7. if i == right:
  8. result += [right-left + 1]
  9. left = i+1
  10. return result

338. Counting Bits

Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1's in their binary representation and return them as an array.
Example 1:
Input: 2
Output: [0,1,1]
Example 2:
Input: 5
Output: [0,1,1,2,1,2]
Follow up:
It is very easy to come up with a solution with run time O(n*sizeof(integer)). But can you do it in linear time O(n) /possibly in a single pass?
Space complexity should be O(n).
Can you do it like a boss? Do it without using any builtin function like __builtin_popcount in c++ or in any other language.

【题意】
输出从0到num每个数的二进制表示中1的个数

【思路】
只要这个二进制数去掉一个1,就会得到一个更小的数,而这个更小的数是我们算过的,知道答案,就可以写成 1+ans[更小的数]。还记得 -x&x 可以把x二进制变成只剩最后一个1其他都是0,所以就把这个位置的值去掉,得到 ans[x-(-x&x)]+1。

【代码】

  1. class Solution:
  2. def countBits(self, num: int) -> List[int]:
  3. ans = [0 for _ in range(num+1)]
  4. for x in range(1, num+1):
  5. if x<=2:
  6. ans[x]=1
  7. else:
  8. ans[x] = ans[x-(-x&x)]+1
  9. return ans

【discussion】

x & (x-1) 就是给 x 删去最后一个1,所以其实可以直接写作 ans[i] = ans[x & (x-1)] + 1

还有一个挺有趣的做法,就是直接按照1,2,4,8..这样一段一段增加下去,每一段都相当于在前面得到的所有数加上最高位的1,但这样不好的地方就是最坏会到O(2N)

  1. def countBits(self, num):
  2. iniArr = [0]
  3. if num > 0:
  4. amountToAdd = 1
  5. while len(iniArr) < num + 1:
  6. iniArr.extend([x+1 for x in iniArr])
  7. return iniArr[0:num+1]

406. Queue Reconstruction by Height

Suppose you have a random list of people standing in a queue. Each person is described by a pair of integers (h, k), where h is the height of the person and k is the number of people in front of this person who have a height greater than or equal to h. Write an algorithm to reconstruct the queue.
Note:
The number of people is less than 1,100.
Example
Input:
[[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]
Output:
[[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]

【题意】
在一个队伍中知道每个人的身高和排在他前面的更高或和他一样高的人数,还原出这个队伍

【思路】
按照x[0]降序、x1升序,这样先安排个子高的,然后再排矮的,同样个高的站前面的先安排,此时x1位置的值就是他应该插入的位置

【代码】

  1. class Solution:
  2. def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
  3. people = sorted(people, key=lambda x:x[1])
  4. people = sorted(people, key=lambda x:x[0], reverse=True)
  5. ans = []
  6. for x in people:
  7. idx = x[1]
  8. if len(ans) < idx+1:
  9. ans.append(x)
  10. else:
  11. ans = ans[:idx]+[x]+ans[idx:]
  12. return ans

【discussion】
更简洁的写法

  1. def reconstructQueue(self, people):
  2. people.sort(key=lambda (h, k): (-h, k))
  3. queue = []
  4. for p in people:
  5. queue.insert(p[1], p)
  6. return queue

46. Permutations

Given a collection of distinct integers, return all possible permutations.
Example:
Input: [1,2,3]
Output:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]

【题意】
给一串数组,输出全排列

【思路】
练习dfs

【代码】

  1. class Solution:
  2. def permute(self, nums: List[int]) -> List[List[int]]:
  3. ans = []
  4. length = len(nums)
  5. def dfs(tmp_l, dic):
  6. if len(tmp_l)==length:
  7. ans.append(tmp_l)
  8. return
  9. for i in nums:
  10. if i not in dic:
  11. dic[i]=1
  12. dfs(tmp_l+[i], dic)
  13. dic.pop(i)
  14. dfs([],{})
  15. return ans

【discussion】
不用dfs,对于num中每个元素一个个插:每拿到一个新的元素,就把之前已经排好的拎出来插在所有可以插入的位置

  1. def permute(self, nums):
  2. perms = [[]]
  3. for n in nums:
  4. new_perms = []
  5. for perm in perms:
  6. for i in xrange(len(perm)+1):
  7. new_perms.append(perm[:i] + [n] + perm[i:]) #insert n
  8. perms = new_perms
  9. return perms

94. Binary Tree Inorder Traversal

Given the root of a binary tree, return the inorder traversal of its nodes' values.
Example 1:
Input: root = [1,null,2,3]
Output: [1,3,2]
Example 2:
Input: root = []
Output: []
Example 3:
Input: root = 1
Output: 1
Example 4:
Input: root = [1,2]
Output: [2,1]

【题意】
给一个树 输出中序遍历

【思路】
中序是[左根右] 直接dfs就vans了

【代码】

  1. class Solution:
  2. def inorderTraversal(self, root: TreeNode) -> List[int]:
  3. if root==None:
  4. return []
  5. return self.inorderTraversal(root.left) + [root.val] + self.inorderTraversal(root.right)

【discussion】
非递归的写法 自己压栈

  1. def inorderTraversal(self, root):
  2. res, stack = [], []
  3. while True:
  4. while root:
  5. stack.append(root)
  6. root = root.left
  7. if not stack:
  8. return res
  9. node = stack.pop()
  10. res.append(node.val)
  11. root = node.right

739. Daily Temperatures

Given a list of daily temperatures T, return a list such that, for each day in the input, tells you how many days you would have to wait until a warmer temperature. If there is no future day for which this is possible, put 0 instead.
For example, given the list of temperatures T = [73, 74, 75, 71, 69, 72, 76, 73], your output should be [1, 1, 4, 2, 1, 1, 0, 0].
Note: The length of temperatures will be in the range [1, 30000]. Each temperature will be an integer in the range [30, 100].

【题意】
给一个每日温度的列表 输出对于这个列表中的每一天 要等几天会温度变暖

【思路】
最后一天的日子好算就是0 所以从后往前遍历比较好求
维护一个单调栈 从后往前的压栈 如果遇到栈里的数比它小 就可以直接踹掉 因为对于靠前面的日子来说 是不可能指到一个更小还更靠后的数的(后来这个地方wa了 因为题意是需要小于等于都踹掉)
然后这时候栈首-现在这个idx就是所求值,如果栈空就是0

【代码】

  1. class Solution:
  2. def dailyTemperatures(self, T: List[int]) -> List[int]:
  3. idx = len(T)-1
  4. stack = [(T[-1],idx)]
  5. ans = [0]
  6. for x in T[-2::-1]:
  7. idx -= 1
  8. while len(stack) and x >= stack[-1][0]:
  9. stack.pop()
  10. if len(stack)==0:
  11. ans.append(0)
  12. else:
  13. ans.append(stack[-1][3]-idx)
  14. stack.append((x, idx))
  15. return ans[::-1]

【discussion】
更简洁的写法 而且其实栈里不需要存value只存idx就好了

  1. def dailyTemperatures(self, T):
  2. ans = [0] * len(T)
  3. stack = []
  4. for i, t in enumerate(T):
  5. while stack and T[stack[-1]] < t:
  6. cur = stack.pop()
  7. ans[cur] = i - cur
  8. stack.append(i)
  9. return ans

22. Generate Parentheses

Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
Example 1:
Input: n = 3
Output: ["((()))","(()())","(())()","()(())","()()()"]
Example 2:
Input: n = 1
Output: ["()"]
Constraints:
1 <= n <= 8

【题意】
输出n对括号能组成的所有valid的字符串

【思路】
dfs 记录现在有多少左括号了 如果 > 0 就能放右括号 如果 < n 就还能放左括号 到最后如果left=0说明是合法的 加入ans

【代码】

  1. class Solution:
  2. def generateParenthesis(self, n: int) -> List[str]:
  3. ans = []
  4. def dfs(tmp_s, left):
  5. if len(tmp_s)==2*n:
  6. if left==0:
  7. ans.append(tmp_s)
  8. return
  9. if left>0:
  10. dfs(tmp_s+")", left-1)
  11. if left<n:
  12. dfs(tmp_s+"(", left+1)
  13. dfs("",0)
  14. return ans

【discussion】
这样dfs虽然好写 但会有很多重复计算 比如n=3的时候就会重复算n=1+2和n=2+1 好在n不大就没超时
所以这个DP的思路确实很赞 十分奇妙

To generate all n-pair parentheses, we can do the following:

Generate one pair: ()
Generate 0 pair inside, n - 1 afterward: () (...)...
Generate 1 pair inside, n - 2 afterward: (()) (...)...
...
Generate n - 1 pair inside, 0 afterward: ((...))

I bet you see the overlapping subproblems here. Here is the code:
(you could see in the code that x represents one j-pair solution and y represents one (i - j - 1) pair solution, and we are taking into account all possible of combinations of them)

  1. class Solution(object):
  2. def generateParenthesis(self, n):
  3. dp = [[] for i in range(n + 1)]
  4. dp[0].append('')
  5. for i in range(n + 1):
  6. for j in range(i):
  7. dp[i] += ['(' + x + ')' + y for x in dp[j] for y in dp[i - j - 1]]
  8. return dp[n]

78. Subsets

Given a set of distinct integers, nums, return all possible subsets (the power set).
Note: The solution set must not contain duplicate subsets.
Example:
Input: nums = [1,2,3]
Output:
[
3,
1,
2,
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]

【题意】
给一个列表 输出所有的子集

【思路】
遍历nums 对于每一个元素都把之前得到的所有子集拿出来把它塞进去

【代码】

  1. class Solution:
  2. def subsets(self, nums: List[int]) -> List[List[int]]:
  3. ans = [[]]
  4. for x in nums:
  5. ans += [ a+[x] for a in ans]
  6. return ans

【discussion】
除了dfs外 还看到一个思路 是把取子集当做是Bit Manipulation
给nums的每个位置赋予0/1 0代表不取1代表取 那么比如当n=3的时候 就相当于i从000遍历到111 (1 << len(nums))对于0~len(num)-1的这j个位置上 如果是1就把nums[j] append进来

  1. def subsets(self, nums):
  2. res = []
  3. for i in xrange(1<<len(nums)):
  4. tmp = []
  5. for j in xrange(len(nums)):
  6. if i & 1 << j: # if i >> j & 1:
  7. tmp.append(nums[j])
  8. res.append(tmp)
  9. return res

347. Top K Frequent Elements

Given a non-empty array of integers, return the k most frequent elements.
Example 1:
Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]
Example 2:
Input: nums = 1, k = 1
Output: 1
Note:
You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
It's guaranteed that the answer is unique, in other words the set of the top k frequent elements is unique.
You can return the answer in any order.

【题意】
输出列表中出现最多次的前K个元素

【思路】
先遍历一遍把元素个数记下来 然后按照次数sort一下

【代码】

  1. class Solution:
  2. def topKFrequent(self, nums: List[int], k: int) -> List[int]:
  3. dic = {}
  4. for x in nums:
  5. if x in dic:
  6. dic[x]+=1
  7. else:
  8. dic[x]=1
  9. dic = sorted(dic.items(), key=lambda x: -x[1])
  10. ans = []
  11. for i in range(k):
  12. ans.append(dic[i][0])
  13. return ans

【discussion】

最后一步更好的写法

  1. arr = sorted(dic, key = dic.get,reverse = True)
  2. return([arr[:k])

另一种思路,为避免sort的O(NlogN),可以把dict的key和value换一下,key换成次数后就是有范围的,从nums的长度到1,去找前K个,这样就O(N)了

  1. def topKFrequent(self, nums, k):
  2. frq = defaultdict(list)
  3. for key, cnt in Counter(nums).items():
  4. frq[cnt].append(key)
  5. res = []
  6. for times in reversed(range(len(nums) + 1)):
  7. res.extend(frq[times])
  8. if len(res) >= k: return res[:k]
  9. return res[:k]

230. Kth Smallest Element in a BST

Given a binary search tree, write a function kthSmallest to find the kth smallest element in it.
Example 1:
Input: root = [3,1,4,null,2], k = 1
3
/ \
1 4
\
2
Output: 1
Example 2:
Input: root = [5,3,6,2,4,null,null,1], k = 3
5
/ \
3 6
/ \
2 4
/
1
Output: 3
Follow up:
What if the BST is modified (insert/delete operations) often and you need to find the kth smallest frequently? How would you optimize the kthSmallest routine?

【题意】
找出二叉搜索树上的第K大元素

【思路】
如果知道左子树的节点个数M,root就是第M+1大。如果K < M,就在左子树继续找,否则就在右子树找第K-(M+1)大。

【代码】

  1. class Solution:
  2. def cul(self, root):
  3. if root==None:
  4. return 0
  5. return self.cul(root.left)+self.cul(root.right)+1
  6. def kthSmallest(self, root: TreeNode, k: int) -> int:
  7. left_num = self.cul(root.left)
  8. if left_num == k-1:
  9. return root.val
  10. elif left_num > k-1:
  11. return self.kthSmallest(root.left, k)
  12. else:
  13. return self.kthSmallest(root.right, k-(left_num+1))

【discussion】
上面那种做法最坏复杂度可能到O(N^2)
其实不用那么复杂,BST按照中序遍历得到的就是从小到大的序列,然后返回列表中的第k个就行了,这样是O(N)

  1. class Solution(object):
  2. def kthSmallest(self, root, k):
  3. count = []
  4. self.helper(root, count)
  5. return count[k-1]
  6. def helper(self, node, count):
  7. if not node:
  8. return
  9. self.helper(node.left, count)
  10. count.append(node.val)
  11. self.helper(node.right, count)

或者不用存下来,直接在遍历左子树的时候k-=1,当k为0时就得到ans了

  1. def kthSmallest(self, root, k):
  2. self.k = k
  3. self.res = None
  4. self.helper(root)
  5. return self.res
  6. def helper(self, node):
  7. if not node:
  8. return
  9. self.helper(node.left)
  10. self.k -= 1
  11. if self.k == 0:
  12. self.res = node.val
  13. return
  14. self.helper(node.right)

647. Palindromic Substrings

Given a string, your task is to count how many palindromic substrings in this string.
The substrings with different start indexes or end indexes are counted as different substrings even they consist of same characters.
Example 1:
Input: "abc"
Output: 3
Explanation: Three palindromic strings: "a", "b", "c".
Example 2:
Input: "aaa"
Output: 6
Explanation: Six palindromic strings: "a", "a", "a", "aa", "aa", "aaa".
Note:
The input string length won't exceed 1000.

【题意】
给一字符串 输出所有子串中是回文串的个数

【思路】
遍历,把每个当做中心,然后往周围找,这样是O(N^2),除了这种奇数个的情况,还得再处理一下偶数

【代码】

  1. class Solution:
  2. def countSubstrings(self, s: str) -> int:
  3. ans = len(s)
  4. for i, x in enumerate(s):
  5. k = min(i, len(s)-i-1)
  6. for j in range(1, k+1):
  7. if s[i-j]==s[i+j]:
  8. ans += 1
  9. else:
  10. break
  11. for i, x in enumerate(s):
  12. if i+1<len(s) and s[i]==s[i+1]:
  13. ans += 1
  14. k = min(i, len(s)-i-2)
  15. for j in range(1, k+1):
  16. if s[i-j]==s[i+1+j]:
  17. ans += 1
  18. else:
  19. break
  20. return ans

【discussion】
DP的写法,dp[i][j]代表这一段是回文

  1. def countSubstrings(self, s: str) -> int:
  2. n = len(s)
  3. dp = [[0] * n for _ in range(n)]
  4. res = 0
  5. for i in range(n-1, -1, -1):
  6. for j in range(i, n):
  7. dp[i][j] = s[i] == s[j] and ((j-i+1) < 3 or dp[i+1][j-1])
  8. res += dp[i][j]
  9. return res

有个超级机智的统一奇偶长度的方法,就是在每个字符中间插空加上任意一个符号,对结果没有影响,比如加上“#”,奇偶的情况就是#a#b#a#和#a#b#b#a#,这样统一都变成奇数个了

O(N)的做法,Manacher算法: (知乎的讲解

  1. def ManacherAlgm(self, s):
  2. # Transform S into T.
  3. # For example, S = "abba", T = "^#a#b#b#a#$".
  4. # ^ and $ signs are sentinels appended to each end to avoid bounds checking
  5. T = '#'.join('^{}$'.format(s))
  6. n = len(T)
  7. P = [0] * n
  8. C = R = 0
  9. for i in range (1, n-1):
  10. # (R > i) and min(R - i, P[2*C - i]) considering Case1 and Case2
  11. P[i] = (R > i) and min(R - i, P[2*C - i])
  12. # Attempt to expand palindrome centered at i
  13. while T[i + 1 + P[i]] == T[i - 1 - P[i]]:
  14. P[i] += 1
  15. # If palindrome centered at i expand past R,
  16. # adjust center based on expanded palindrome.
  17. if i + P[i] > R:
  18. C, R = i, i + P[i]
  19. return (sum(P) + len(s)) // 2

238. Product of Array Except Self

Given an array nums of n integers where n > 1, return an array output such that output[i] is equal to the product of all the elements of nums except nums[i].
Example:
Input: [1,2,3,4]
Output: [24,12,8,6]
Constraint: It's guaranteed that the product of the elements of any prefix or suffix of the array (including the whole array) fits in a 32 bit integer.
Note: Please solve it without division and in O(n).
Follow up:
Could you solve it with constant space complexity? (The output array does not count as extra space for the purpose of space complexity analysis.)

【题意】
对于列表中的每个位置,输出整个列表除了该位置的数的乘积,限制是不让用除法

【思路】
算个前缀积和后缀积

【代码】

  1. class Solution:
  2. def productExceptSelf(self, nums: List[int]) -> List[int]:
  3. pre = [1]
  4. suf = [1]
  5. for x in nums:
  6. pre.append(pre[-1]*x)
  7. for x in nums[::-1]:
  8. suf.append(suf[-1]*x)
  9. suf.reverse()
  10. ans = []
  11. for i in range(len(nums)):
  12. ans.append(pre[i]*suf[i+1])
  13. return ans

【discussion】
只用O(1)空间的做法
也是正反两次遍历,维护一个在这个位置需要乘下去的p,比如n=4的时候:
第一遍遍历nums 得到output[-, 0, 01, 012]
第二遍反过来遍历nums 得到output[123, 0 23, 01 3, 012]

  1. def productExceptSelf(self, nums):
  2. p = 1
  3. n = len(nums)
  4. output = []
  5. for i in range(0,n):
  6. output.append(p)
  7. p = p * nums[i]
  8. p = 1
  9. for i in range(n-1,-1,-1):
  10. output[i] = output[i] * p
  11. p = p * nums[i]
  12. return output

48. Rotate Image

You are given an n x n 2D matrix representing an image, rotate the image by 90 degrees (clockwise).
You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation.
Example 1:
Input: matrix = [[1,2,3],[4,5,6],[7,8,9]]
Output: [[7,4,1],[8,5,2],[9,6,3]]
Example 2:
Input: matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
Output: [[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]
Example 3:
Input: matrix = [1]
Output: [1]
Example 4:
Input: matrix = [[1,2],[3,4]]
Output: [[3,1],[4,2]]

Constraints:
matrix.length == n
matrix[i].length == n
1 <= n <= 20
-1000 <= matrix[i][j] <= 1000

【题意】
把二维矩阵顺时针转90度,要求是in-place的操作

【思路】
对着图看了几秒,第一反应是先求个转置(对称交换),观察一下,这样之后再每行反过来就行了

【代码】

  1. class Solution:
  2. def rotate(self, matrix: List[List[int]]) -> None:
  3. n = len(matrix)
  4. for i in range(n):
  5. for j in range(i,n):
  6. matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
  7. for i in range(n):
  8. matrix[i] = matrix[i][::-1]

49. Group Anagrams

Given an array of strings strs, group the anagrams together. You can 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: strs = ["eat","tea","tan","ate","nat","bat"]
Output: [["bat"],["nat","tan"],["ate","eat","tea"]]
Example 2:
Input: strs = [""]
Output: [[""]]
Example 3:
Input: strs = ["a"]
Output: [["a"]]

Constraints:
1 <= strs.length <= 104
0 <= strs[i].length <= 100
strs[i] consists of lower-case English letters.

【题意】
给一堆字符串,输出字符相同的组成的集合

【思路】
开始想的是对于a-z分别判断,把它们分成有a/没a的两堆,再每堆里分成有b/没b,再... (然后才发现同字母可能有多个,卒)
于是先给各个字符串做下sort,然后以sort后的字符串作为key造dict

【代码】

  1. class Solution:
  2. def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
  3. from collections import defaultdict
  4. tmp = []
  5. for x in strs:
  6. chars = "".join(sorted(list(x)))
  7. tmp.append(chars)
  8. dic = defaultdict(list)
  9. for i, x in enumerate(tmp):
  10. dic[x].append(strs[i])
  11. return dic.values()

【discussion】
更简洁的写法

  1. class Solution:
  2. def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
  3. ans = collections.defaultdict(list)
  4. for items in strs:
  5. ans[''.join(sorted(items))].append(items)
  6. return (list(ans.values()))

39. Combination Sum

Given an array of distinct integers candidates and a target integer target, return a list of all unique combinations of candidates where the chosen numbers sum to target. You may return the combinations in any order.
The same number may be chosen from candidates an unlimited number of times. Two combinations are unique if the frequency of at least one of the chosen numbers is different.
It is guaranteed that the number of unique combinations that sum up to target is less than 150 combinations for the given input.
Example 1:
Input: candidates = [2,3,6,7], target = 7
Output: [[2,2,3],7]
Explanation:
2 and 3 are candidates, and 2 + 2 + 3 = 7. Note that 2 can be used multiple times.
7 is a candidate, and 7 = 7.
These are the only two combinations.
Example 2:
Input: candidates = [2,3,5], target = 8
Output: [[2,2,2,2],[2,3,3],[3,5]]
Example 3:
Input: candidates = 2, target = 1
Output: []

Constraints:
1 <= candidates.length <= 30
1 <= candidates[i] <= 200
All elements of candidates are distinct.
1 <= target <= 500

【题意】
从一个list中选取数 使他们的和为target 可以重复选

【思路】
dp的思想,如果知道一个小于这个的数能被怎么组成,就能转移到更大的数。比如要求8,如果知道6能怎么得到,就把得到6的所有答案多加一个2就行了。一个小trick就是先sort一下候选数,遇到比target大就直接break掉

【旧的代码】

  1. class Solution:
  2. def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
  3. candidates.sort()
  4. ans = [[] for _ in range(target+1)]
  5. mark = [0 for _ in range(target+1)]
  6. def dfs(num):
  7. for x in candidates:
  8. if num <= x:
  9. break
  10. if mark[num-x]==0:
  11. dfs(num-x)
  12. if len(ans[num-x])>0:
  13. ans[num] += [tmp+[x] for tmp in ans[num-x]]
  14. mark[num] = 1
  15. ans[num] = remove_dup(ans[num])
  16. def remove_dup(lis):
  17. [x.sort() for x in lis]
  18. key_l = list(set([" ".join(list(map(str, x))) for x in lis]))
  19. lis = [list(map(int, key.split())) for key in key_l]
  20. return lis
  21. for x in candidates:
  22. if x > target:
  23. continue
  24. ans[x]=[[x]]
  25. dfs(target)
  26. return ans[target]

这里有个很烦人的地方在于需要去重,我写了个remove_dup把每个list sort之后再join起来扔进set来去重,但看了discussion才发现,其实不用那么麻烦,因为candidates是sort过的,当转移的时候,从数字更小的ans中取出来的某个答案tmp,如果转移差值x是小于tmp[-1]的,那就不用加了
比如求5的时候,先拿出2,给它加上3;再拿出3,要给它加上2,就重复了

【新的代码】

  1. class Solution:
  2. def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
  3. candidates.sort()
  4. ans = [[] for _ in range(target+1)]
  5. mark = [0 for _ in range(target+1)]
  6. def dfs(num):
  7. for x in candidates:
  8. if num <= x:
  9. break
  10. if mark[num-x]==0:
  11. dfs(num-x)
  12. if len(ans[num-x])>0:
  13. for tmp in ans[num-x]:
  14. if x >= tmp[-1]:
  15. ans[num] += [tmp+[x]]
  16. mark[num] = 1
  17. for x in candidates:
  18. if x > target:
  19. continue
  20. ans[x]=[[x]]
  21. dfs(target)
  22. return ans[target]

【discussion】
不把每个数的ans都存下来,直接dfs(运行时间和内存都差不多)

  1. class Solution(object):
  2. def combinationSum(self, candidates, target):
  3. result = []
  4. candidates = sorted(candidates)
  5. def dfs(remain, stack):
  6. if remain == 0:
  7. result.append(stack)
  8. return
  9. for item in candidates:
  10. if item > remain: break
  11. if stack and item < stack[-1]: continue
  12. else:
  13. dfs(remain - item, stack + [item])
  14. dfs(target, [])
  15. return result

215. Kth Largest Element in an Array

Find the kth largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.
Example 1:
Input: [3,2,1,5,6,4] and k = 2
Output: 5
Example 2:
Input: [3,2,3,1,2,4,5,5,6] and k = 4
Output: 4
Note:
You may assume k is always valid, 1 ≤ k ≤ array's length.

【题意】
找出列表中第K大的元素

【思路】
快排中的partition
要注意的坑是 i要从0开始遍历而不是从1开始,不然会在0和j位置交换的时候有问题,比如nums=[2,1] k=2, i,j都为1,while逻辑没进去,于是[2,1]被交换成[1,2],而正确的时候应该i=1 j=0

【代码】

  1. class Solution:
  2. def findKthLargest(self, nums: List[int], k: int) -> int:
  3. p = nums[0]
  4. i, j = 0, len(nums)-1
  5. while i<j:
  6. while i<len(nums) and nums[i]>=p: i+=1
  7. while j>=0 and nums[j]<p: j-=1
  8. if i<j:
  9. nums[i], nums[j] = nums[j], nums[i]
  10. nums[0], nums[j] = nums[j], nums[0]
  11. if j+1==k:
  12. return p
  13. elif j+1>k:
  14. return self.findKthLargest(nums[:j], k)
  15. else:
  16. return self.findKthLargest(nums[j+1:], k-j-1)

【discussion】
更方便的写法 虽然运行时间和空间都更大

  1. class Solution:
  2. def findKthLargest(self, nums, k):
  3. pivot = nums[0]
  4. left = [l for l in nums if l < pivot]
  5. equal = [e for e in nums if e == pivot]
  6. right = [r for r in nums if r > pivot]
  7. if k <= len(right):
  8. return self.findKthLargest(right, k)
  9. elif (k - len(right)) <= len(equal):
  10. return equal[0]
  11. else:
  12. return self.findKthLargest(left, k - len(right) - len(equal))

287. Find the Duplicate Number

Given an array of integers nums containing n + 1 integers where each integer is in the range [1, n] inclusive.
There is only one duplicate number in nums, return this duplicate number.
Can you solve the problem using only constant, O(1) extra space?

【题意】
一个列表中有n+1个数,数的大小在[1,n]之间,其中有一个数重复出现了多次,找出这个重复的数

【思路】
因为数的大小有限制 所以可以直接开个列表来存个数 然后再遍历一下 这样时间是O(N) 但空间开销做不到O(1)

【代码】

  1. class Solution:
  2. def findDuplicate(self, nums: List[int]) -> int:
  3. cnt = [0 for i in nums]
  4. for x in nums:
  5. cnt[x]+=1
  6. for i,x in enumerate(cnt):
  7. if x>1:
  8. return i

【discussion】
神解法...... [link] 看做是图 找回环的入口点

1)比如[2 3 1 1] 这个路径指向就是 0->2 1->3 2->1 3->1 从0开始进入就是0->2->1->3->1->3->1....
第一个while循环停在了1
第二个while循环 留一个slow在继续3->1->3->1... 再开一个finder 2->1->3->1->3...

2)比如[1,3,4,2,2] 路径是0->1->3->2->4->2->4->2.....
第一个while循环停在了4
第二个while循环 留一个slow在继续2->4->2->4... 再开一个finder 1->3->2->4->2->4...

  1. def findDuplicate(self, nums):
  2. slow = fast = finder = 0
  3. while True:
  4. slow = nums[slow]
  5. fast = nums[nums[fast]]
  6. if slow == fast:
  7. while finder != slow:
  8. finder = nums[finder]
  9. slow = nums[slow]
  10. return finder

102. Binary Tree Level Order Traversal

Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level).
For example:
Given binary tree [3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
return its level order traversal as:
[
3,
[9,20],
[15,7]
]

【题意】
二叉树按行输出

【代码】

  1. class Solution:
  2. def levelOrder(self, root: TreeNode) -> List[List[int]]:
  3. if not root:
  4. return []
  5. ans, tmp_nodes = [], [root]
  6. while len(tmp_nodes):
  7. ans.append([x.val for x in tmp_nodes])
  8. new_nodes = []
  9. for x in tmp_nodes:
  10. if x.left: new_nodes.append(x.left)
  11. if x.right: new_nodes.append(x.right)
  12. tmp_nodes = new_nodes[::]
  13. return ans

64. Minimum Path Sum

Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right, which minimizes the sum of all numbers along its path.
Note: You can only move either down or right at any point in time.
Example 1:
Input: grid = [[1,3,1],[1,5,1],[4,2,1]]
Output: 7
Explanation: Because the path 1 → 3 → 1 → 1 → 1 minimizes the sum.
Example 2:
Input: grid = [[1,2,3],[4,5,6]]
Output: 12

Constraints:
m == grid.length
n == grid[i].length
1 <= m, n <= 200
0 <= grid[i][j] <= 100

【题意】
从网格的左上角走到右下角所经过数字和的最小值

【思路】
DP
这次写了一维的DP 因为每行都是从上一行或从左边转来,而上一行就是前一步得到的dp值,所以只开一个行向量长度的dp数组就够了
初始化dp时 除了第一个位置取0 其他取一个很大的值 这样强制在第一行的位置能全部从左边转移 有个坑点是 这个很大的值我开始就取101(矩阵上元素的最大值)但其实应该取n*101 这样才能保证在加和第一行的之后一直小于这个MAX

【代码】

  1. class Solution:
  2. def minPathSum(self, grid: List[List[int]]) -> int:
  3. m, n = len(grid), len(grid[0])
  4. dp = [0] + [m*n*101 for _ in range(n-1)]
  5. for i in range(m):
  6. for j in range(n):
  7. dp[j] = min(dp[j], dp[j-1])+grid[i][j]
  8. return dp[n-1]

62. Unique Paths

A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).
How many possible unique paths are there?

【题意】
和上面一题几乎是一毛一样的emmm 唯一不同就是从路径和变成了路径条数

【代码】

  1. class Solution:
  2. def uniquePaths(self, m: int, n: int) -> int:
  3. dp = [1 for _ in range(n)]
  4. for i in range(1, m):
  5. for j in range(1,n):
  6. dp[j] = dp[j] + dp[j-1]
  7. return dp[n-1]

96. Unique Binary Search Trees

Given n, how many structurally unique BST's (binary search trees) that store values 1 ... n?
Example:
Input: 3
Output: 5
Explanation:
Given n = 3, there are a total of 5 unique BST's:
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3

Constraints:
1 <= n <= 19

【题意】
给一个数n 问用1~n组成的二叉搜索树有几种

【思路】
因为是二叉搜索树,所以其实只要确定了树长什么样,上面的节点就是固定的。所以其实相当于从一个完整的满二叉树上挑出一个包含根节点的子树有多少种挑法的问题。
把挑节点想成挑树边会更容易,于是我把问题这样定义(几层是指节点多少层):
1层的树选0条边:1种
2层的树选1条边:2种
3层的树选2条边:5种
...
假设现在要选n条边,对于一棵大树,如果选根左边那条边要、右边不要,就从更小的那棵左子树上选n-1条边,反之,右子树上选n-1条边 ans = select[i-1]*2;如果根左右的两条边都要,那就从两棵更小的子树上选出n-2条(remain条)边就可以,选法可以有0 + remain、1 + remain-1、2 + remain-2 ... remain + 0这么多种 ans += select[sel] * select[remain-sel]

【代码】

  1. class Solution:
  2. def numTrees(self, n: int) -> int:
  3. if n==1: return 1
  4. if n==2: return 2
  5. select = [1, 2]
  6. n = n-1
  7. for i in range(2, n+1):
  8. ans = select[i-1]*2
  9. remain = i-2
  10. for sel in range(0, remain+1):
  11. ans += select[sel] * select[remain-sel]
  12. select.append(ans)
  13. return select[-1]

【discussion】

哎我去 是我sb了 第一层完全不需要单独区分的 就直接是0 + n-1、1 + n-1-1、...、n-1 + 0 的问题 OTL

  1. # DP
  2. def numTrees1(self, n):
  3. res = [0] * (n+1)
  4. res[0] = 1
  5. for i in xrange(1, n+1):
  6. for j in xrange(i):
  7. res[i] += res[j] * res[i-1-j]
  8. return res[n]

啊这居然就是Catalan数 看了下它的wikipidia感觉还蛮有趣的

  1. # Catalan Number (2n)!/((n+1)!*n!)
  2. def numTrees(self, n):
  3. return math.factorial(2*n)/(math.factorial(n)*math.factorial(n+1))

11. Container With Most Water

Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of the line i is at (i, ai) and (i, 0). Find two lines, which, together with the x-axis forms a container, such that the container contains the most water.
Notice that you may not slant the container.
Example 1:
Input: height = [1,8,6,2,5,4,8,3,7]
Output: 49
Explanation: The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49.
Example 2:
Input: height = [1,1]
Output: 1
Example 3:
Input: height = [4,3,2,1,4]
Output: 16

Constraints:
n = height.length
2 <= n <= 3 * 10^4
0 <= height[i] <= 3 * 10^4

【题意】
array代表了若干个隔板 在两个隔板之间倒水最多能倒多满

【思路】
今天这道题有点难
一开始想的就是 每个隔板都有可能成为短板 就以它为左边 去右边找最远的超过它高度的位置 这样O(N^2)不能接受
然后又想 那就不从左往右而是从下往上看 最终的水高一定会是某个板子的高度,所以遍历板子高度存下他们的idx得到一个 高度->idx表 但这样也是O(N^2) 然后就卡住了orz

看了discussion才发现 其实是一次遍历就能解决的:
在优先保证宽度的情况下 左右两个隔板尽量往高的取 如果最左边矮 就抛弃掉最左边的 如果最右边矮 就抛弃右边
这是因为:如果扔掉的是更高的那个 下一个遇到更高的 那么面积是宽度小了但高度不变,总之不可能得到更大的解了;如果遇到了一个更矮的 宽高都小了;如果扔掉矮的,就有可能遇到一个能使水面变高的

【代码】

  1. def maxArea(self, height):
  2. L, R, width, res = 0, len(height) - 1, len(height) - 1, 0
  3. for w in range(width, 0, -1):
  4. if height[L] < height[R]:
  5. res, L = max(res, height[L] * w), L + 1
  6. else:
  7. res, R = max(res, height[R] * w), R - 1
  8. return res

394. Decode String

Given an encoded string, return its decoded string.
The encoding rule is: k[encoded_string], where the encoded_string inside the square brackets is being repeated exactly k times. Note that k is guaranteed to be a positive integer.
You may assume that the input string is always valid; No extra white spaces, square brackets are well-formed, etc.
Furthermore, you may assume that the original data does not contain any digits and that digits are only for those repeat numbers, k. For example, there won't be input like 3a or 24.
Example 1:
Input: s = "3[a]2[bc]"
Output: "aaabcbc"
Example 2:
Input: s = "3[a2[c]]"
Output: "accaccacc"
Example 3:
Input: s = "2[abc]3[cd]ef"
Output: "abcabccdcdcdef"

【题意】
看example即可OTL

【思路】
一看就知道是栈 难的是coding 本来还想着递归 看了下答案写的挺简洁的 就是难想555
栈里存的是之前的str和当前这个[]要重复的次数
遇到 [ 的时候是新的开始 把之前的str压栈 需要重复的次数已经知道了也压栈 然后一个个加字符 遇到 ] 之后当前的str和栈里的num乘上 再前面补上pre_s 就是上一 [ ] 里的cur了

【代码】

  1. class Solution:
  2. def decodeString(self, s: str) -> str:
  3. sta = []
  4. num, cur_s = 0, ""
  5. for x in s:
  6. if x.isdigit():
  7. num = num*10+int(x)
  8. elif x=='[':
  9. sta.append(cur_s)
  10. sta.append(num)
  11. num, cur_s = 0, ""
  12. elif x==']':
  13. cur_num = sta.pop()
  14. pre_s = sta.pop()
  15. cur_s = pre_s + cur_num*cur_s
  16. else:
  17. cur_s += x
  18. return cur_s

337. House Robber III

The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night.
Determine the maximum amount of money the thief can rob tonight without alerting the police.
Example 1:
Input: [3,2,3,null,3,null,1]
3
/ \
2 3
\ \
3 1
Output: 7
Explanation: Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.
Example 2:
Input: [3,4,5,1,3,null,1]
3
/ \
4 5
/ \ \
1 3 1
Output: 9
Explanation: Maximum amount of money the thief can rob = 4 + 5 = 9.

【题意】
又来抢劫了 相邻的节点不能同时抢 问能抢到的最大值

【思路】
一看到树上dp就有点懵了 但其实仔细想想没那么难 唯一的不同是没法用一维dp存 就是怎么记录节点的问题 因为是二叉树 所以我就用满二叉数的idx作为标记了 这样就开个dict来存dp的结果
维护一下“取”或“不取”两种情况 对每个idx都开个长度2的数组 0表示不取1表示取 如果父节点不取,那子节点取不取都行,直接两个max相加;如果父节点取,那么只能子节点都不取 再加上父节点的value

【代码】

  1. class Solution:
  2. def rob(self, root: TreeNode) -> int:
  3. dp = {}
  4. def dfs(root, idx):
  5. if root==None:
  6. return [0, 0]
  7. if idx in dp:
  8. return dp[idx]
  9. l, r = dfs(root.left, idx*2), dfs(root.right, idx*2+1)
  10. dp[idx] = [max(l)+max(r), root.val+l[0]+r[0]]
  11. return dp[idx]
  12. return max(dfs(root, 1))

【discussion】
不记录dp 直接递归
想了想似乎每个结点递归完也就只访问一次 确实不需要233 解法是一毛一样的

  1. class Solution(object):
  2. def rob(self, root):
  3. def superrob(node):
  4. if not node: return (0, 0)
  5. left, right = superrob(node.left), superrob(node.right)
  6. rob = node.val + left[1] + right[1]
  7. no_rob = max(left) + max(right)
  8. return (rob, no_rob)
  9. return max(superrob(root))

621. Task Scheduler

Given a characters array tasks, representing the tasks a CPU needs to do, where each letter represents a different task. Tasks could be done in any order. Each task is done in one unit of time. For each unit of time, the CPU could complete either one task or just be idle.
However, there is a non-negative integer n that represents the cooldown period between two same tasks (the same letter in the array), that is that there must be at least n units of time between any two same tasks.
Return the least number of units of times that the CPU will take to finish all the given tasks.
Example 1:
Input: tasks = ["A","A","A","B","B","B"], n = 2
Output: 8
Explanation:
A -> B -> idle -> A -> B -> idle -> A -> B
There is at least 2 units of time between any two same tasks.
Example 2:
Input: tasks = ["A","A","A","B","B","B"], n = 0
Output: 6
Explanation: On this case any permutation of size 6 would work since n = 0.
["A","A","A","B","B","B"]
["A","B","A","B","A","B"]
["B","B","B","A","A","A"]
...
And so on.
Example 3:
Input: tasks = ["A","A","A","A","A","A","B","C","D","E","F","G"], n = 2
Output: 16
Explanation:
One possible solution is
A -> B -> C -> A -> D -> E -> A -> F -> G -> A -> idle -> idle -> A -> idle -> idle -> A

Constraints:
1 <= task.length <= 104
tasks[i] is upper-case English letter.
The integer n is in the range [0, 100].

【题意】
两个相同任务之间需要间隔至少n时 问排完这些任务所需的最少时间

【思路】
我还记得这道题 两种情况:
1)全塞满 就是len(task)
2)没有塞满 只需要排好次数最多的 中间间隙不用去管一定能塞得下
原因:[link](我还问过建明为什么可以保证塞得下hhh)

【代码】

  1. class Solution:
  2. def leastInterval(self, tasks: List[str], n: int) -> int:
  3. from collections import Counter
  4. cnts = Counter(tasks).values()
  5. cnt_max, max_num = max(cnts), 0
  6. for x in cnts:
  7. if x==cnt_max: max_num+=1
  8. return max((cnt_max-1)*(n+1)+max_num, len(tasks))

【discussion】
统计出现最多次数的有几个字母可以用task_counts.count()

  1. class Solution:
  2. def leastInterval(self, tasks: List[str], n: int) -> int:
  3. tasks_count = list(collections.Counter(tasks).values())
  4. max_count = max(tasks_count)
  5. max_count_tasks = tasks_count.count(max_count)
  6. return max(len(tasks), (max_count-1)*(n+1)+max_count_tasks)

208. Implement Trie (Prefix Tree)

Implement a trie with insert, search, and startsWith methods.
Example:
Trie trie = new Trie();
trie.insert("apple");
trie.search("apple"); // returns true
trie.search("app"); // returns false
trie.startsWith("app"); // returns true
trie.insert("app");
trie.search("app"); // returns true

Note:
You may assume that all inputs are consist of lowercase letters a-z.
All inputs are guaranteed to be non-empty strings.

【思路】
用dict嵌套dict来模拟这个char树,当一个word完成的时候记录一下它是一个end点
有一点就是,我开始觉得每个节点都要有一个end标记,所以value应该是个(dict, bool)这种的,就写的有点繁琐。但其实py不用那么严苛,随便给一个特定的东西作为表征end的key,随时需要加再加就可以了
最终的数据结构是:
key是字母,value是一个dict 代表它的子树;dict里还可能有一个特殊标记‘-1’代表是否是word_end(所以dict里的key可能是一堆字母以及一个-1)

【代码】

  1. class Trie:
  2. def __init__(self):
  3. """
  4. Initialize your data structure here.
  5. """
  6. self.root = {}
  7. self.word_end = -1
  8. def insert(self, word: str) -> None:
  9. """
  10. Inserts a word into the trie.
  11. """
  12. node_now = self.root
  13. for x in word:
  14. if x not in node_now:
  15. node_now[x] = {}
  16. node_now = node_now[x]
  17. node_now[self.word_end] = True
  18. def search(self, word: str) -> bool:
  19. """
  20. Returns if the word is in the trie.
  21. """
  22. node_now = self.root
  23. for x in word:
  24. if x not in node_now:
  25. return False
  26. node_now = node_now[x]
  27. if self.word_end in node_now:
  28. return True
  29. else:
  30. return False
  31. def startsWith(self, prefix: str) -> bool:
  32. """
  33. Returns if there is any word in the trie that starts with the given prefix.
  34. """
  35. node_now = self.root
  36. for x in prefix:
  37. if x not in node_now:
  38. return False
  39. node_now = node_now[x]
  40. return True
  41. # Your Trie object will be instantiated and called as such:
  42. # obj = Trie()
  43. # obj.insert(word)
  44. # param_2 = obj.search(word)
  45. # param_3 = obj.startsWith(prefix)
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注