# class Solution: # def twoSum(self, nums: List[int], target: int) -> List[int]: # #for num in nums: # # other = target - num # for i in range(len(nums)): # other = target - nums[i] # for j in range(i+1, len(nums)): # if nums[j] == other: # return [i, j] # return None classSolution: deftwoSum(self, nums: List[int], target: int) -> List[int]: tmp = dict() for index, val inenumerate(nums): other = target-val if other in tmp: return tmp[other], index tmp[val] = index returnNone
无重复最长字串
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
# 滑动窗口法 classSolution: deflengthOfLongestSubstring(self, s: str) -> int: l = r = 0 tmp = set() max_num = 0 for i inrange(len(s)): # 重复后要去除重复元素以及重复元素之前的,同时l + 1 if i!=0: tmp.remove(s[i-1]) l += 1 while r< len(s) and s[r] notin tmp: # 不重复加入 tmp.add(s[r]) r+=1 print(tmp) max_num = max(r-l, max_num) return max_num
z字形变换
将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:
P A H N A P L S I I G Y I R 之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:”PAHNAPLSIIGYIR”。
n, r = len(s), numRows if r <2: return s t = 2* r-2 # 根据周期求列数 ,每个周期内的列数为r-1列 c = (r-1) * int((n +t -1)/t)
# 初始化数组 dp = [[""]*c for _ inrange(r)]
x, y = 0, 0 for index_, ss inenumerate(s): dp[x][y] = ss if index_%t < r-1: x+=1 else: x -= 1 y += 1 return"".join([ch for list1 in dp for ch in list1 if ch !=""])
数字反转
给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution: defreverse(self, x: int) -> int: """ 除10每次取证,直到被除数<10为止 """ # if x< -(2<<31) or x >(2<<31 - 1): # return 0
y, res = abs(x), 0
while y !=0 : if res < -(2<<30)/10or res> (2<<30)/10: return0 res = res*10 + y%10 y //=10 return res if x>=0else0-res
整数转罗马数组
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。
字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
first_ch = strs[0] j = 0 res = "" while j < len(first_ch): ch = first_ch[j] tag = True for s in strs: iflen(s)<= j or ch != s[j]: tag = False if tag: res += ch else: break j +=1 return res
三数之和
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
classSolution: defthreeSum(self, nums: List[int]) -> List[List[int]]: # 排序, 防止重复 nums.sort() n = len(nums) tmp = list() for i inrange(n): first = nums[i] if i >0and nums[i] == nums[i-1]: continue target = -first # 前后双指针 left = i +1 right = n-1
while left < right: # 如果有重复的则忽略 second = nums[left] third = nums[right] if second + third == target: tmp.append([first, second, third]) #判断是否有相同的元素, while left < right and nums[left] == nums[left +1]: left +=1 while left < right and nums[right] == nums[right -1]: right -= 1 if second +third > target: right -= 1 continue if second + third < target: left += 1 continue left += 1 right -= 1 return tmp
while left <= right: mid = (left + right) //2 print(mid, "mid") if nums[mid] == target: right = right -1 elif nums[mid] > target: right = mid-1 else: left = mid +1 if nums[left] == target: return left else: return -1
defsearch_right(nums, target): left, right = 0, len(nums)-1
while left <= right: mid = (left +right) // 2 if nums[mid] == target: left = mid +1 elif nums[mid] >target: right = mid -1 else: left = mid +1
if nums[right] == target: return right else: return -1 ifnot nums or nums[0] > target or nums[-1] < target: return [-1, -1] l = search_left(nums, target) r = search_right(nums, target) ifall([l != -1, r != -1]): return [l, r]
from collections import defaultdict classSolution: defisValidSudoku(self, board: List[List[str]]) -> bool: row, col , sqrt = defaultdict(set), defaultdict(set), defaultdict(set) for i inrange(0, 9):# 行 for j inrange(0, 9): # 列 if board[i][j] == ".": continue if board[i][j] in row[i]: returnFalse if board[i][j] in col[j]: returnFalse ## 推导i, j 是在哪个盒子 if board[i][j] in sqrt[i//3, j//3]: returnFalse row[i].add(board[i][j]) col[j].add(board[i][j]) sqrt[i//3,j//3].add(board[i][j]) returnTrue
m, n = len(num1), len(num2) temp = [0]* (m + n) for i inrange(0, m): for j inrange(0, n): num = (ord(num1[i]) - ord("0")) * ((ord(num2[j]) - ord("0"))) temp[i + j +1] = temp[i+j+1] + num falg_num = 0 for n inrange(-1, -len(temp) +1, -1): this_num = (temp[n]) % 10 falg_num = temp[n]// 10 temp[n] = this_num temp[n-1] += falg_num index = 1if temp[0] == 0else0 ans = "".join([str(i) for i in temp[index:]]) return ans
classSolution: """ x ** 89 89//2 +1 x ** 88 88/2 """ defmyPow(self, x: float, n: int) -> float: defquick_mul(N): if N == 0: return1.0 y = quick_mul(N//2) return y *y if N %2 ==0else y*y *x return quick_mul(n) if n>=0else1/quick_mul(-n)
字母异味词分组-leetcode 49
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。
字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次。
1 2 3 4 5 6 7 8 9 10
import collections
classSolution: defgroupAnagrams(self, strs: List[str]) -> List[List[str]]: dict1 = collections.defaultdict(list) for i inrange(len(strs)):
defspiralOrder(self, matrix: List[List[int]]) -> List[int]: iflen(matrix)==0: return [] ret = list() top, bottom, left, right = 0, len(matrix)-1, 0, len(matrix[0]) -1 while left <= right and top <= bottom: for column inrange(left, right +1): ret.append(matrix[top][column]) for row inrange(top+1, bottom+1): ret.append(matrix[row][right])
if left < right and top < bottom: for column inrange(right-1, left, -1): ret.append(matrix[bottom][column]) for row inrange(bottom, top, -1): ret.append(matrix[row][left]) top +=1 bottom -= 1 left += 1 right -= 1
# s = s.rstrip(" ") # num = 0 # if len(s) == 1: # return 1 # for i in range(-1, -len(s)-1, -1): # if s[i] == " ": # break # num += 1 # return num # 用内置方法 returnlen(s.rstrip(" ").split(" ")[-1].lstrip(" "))
螺旋矩阵II -leetcode
给你一个正整数 n ,生成一个包含 1 到 n**2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
# Definition for singly-linked list. # class ListNode: # def __init__(self, val=0, next=None): # self.val = val # self.next = next classSolution: """ 1. 计算链表的长度 2. 找出倒数第k+1 个节点 (len(head) - k) % len(head) 3. 转为循环链表 4. 在第k+1 个节点处断开 """ defrotateRight(self, head: ListNode, k: int): if k == 0ornot head ornot head.next: return head
n = 1
cur = head while cur.next: cur = cur.next# 最后一个节点 n += 1 # 寻找新链表的结尾位置 end = (n - k) %n # 余数即为倒数第k+1个位置 cur.next = head # 使链表收尾相连 if end == n: return end()
n = max(len(a), len(b)) a = "0" + (n - len(a)) * "0" + a b = "0" + (n - len(b)) * "0" + b flag = 0 ret = [0] * len(a) for i inrange(-1, -len(ret)-1, -1): num = ord(a[i]) - ord("0") + ord(b[i]) - ord("0") + flag cur = num %2 flag = num//2 ret[i] = str(cur) iflen(ret) == 1: return"".join(ret) ret = ret[1:] if ret[0] == "0"else ret return"".join(ret)
defpartition(data, left, right): tmp = data[left] while left < right: while left < right and data[right] >= tmp: right -= 1 data[left] = data[right] while left < right and data[left] <= tmp: left += 1 data[right] = data[left]
# 如果board[i][j] = word[k]: visited.add((i, j)) result = False for di, dj in directions: newi, newj = i+di, j + dj
if0<=newi<len(board) and0<=newj<len(board[0]): if (newi, newj) notin visited: if backtracing(newi, newj, k +1): result = True break visited.remove((i, j))
return result
visited = set()
for i inrange(len(board)): for j inrange(len(board[0])): if backtracing(i, j, 0): returnTrue
classSolution: defremoveDuplicates(self, nums: List[int]) -> int: start, end = 0, 0 while end <len(nums): while nums[start] == nums[end] and end - start >=2: #if end - start >= 2: del nums[start] end -= 1 #start += 1 # 此时两者之间的距离必小于二, 如果不相同, 则说明有了新元素,需要移动起始指针 if nums[start] != nums[end]: start = end end += 1 # 如果相同, 起始不变,end + 1 else: end += 1
classSolution: defmerge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None: """ Do not return anything, modify nums1 in-place instead. """ l = 0 r = 0 ret = list() while l <m and r < n:
if nums1[l] <= nums2[r]: ret.append(nums1[l]) l += 1 else: ret.append(nums2[r]) r += 1
ret = ret + nums1[l:m] ret = ret + nums2[r:] nums1[:] = ret
子集II -leetcode 90
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
classSolution: defsubsetsWithDup(self, nums: List[int]) -> List[List[int]]: result = list() path = list() nums.sort() defbacktracing(path, start_index): result.append(path[:]) iflen(path) >= len(nums): return for i inrange(start_index, len(nums)): if i > start_index and nums[i] == nums[i-1]: continue path.append(nums[i]) backtracing(path, i +1) path.pop() backtracing(path, 0) return result
# Definition for singly-linked list. # class ListNode: # def __init__(self, val=0, next=None): # self.val = val # self.next = next classSolution: defreverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
defdeverse_node(head): # 原地逆置法反转链表 # bag = head # end = bag.next # while end: # bag.next = end.next # end.next = head # head = end # end = bag.next # print(head, 999) # 头插法 pre = None cur = head
while cur: next = cur.next# 指针指向下一个节点 # 在pre的头部插入cur节点 cur.next = pre pre = cur cur = next # 反转后头节点是right_node, 尾节点是left_node
dummy = ListNode(0) dummy.next = head
pre = dummy
for _ inrange(left -1): # left 的前一个节点 pre = pre.next
right_node = pre
for _ inrange(right - left +1): # 来到right 节点 right_node = right_node.next
例如:”0.1.2.201” 和 “192.168.1.1” 是 有效 IP 地址,但是 “0.011.255.245”、”192.168.1.312” 和 “192.168@1.1“ 是 无效 IP 地址。 给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 ‘.’ 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。
if s[startindx] == "0": path.append("0") backtracing(path, startindx+1) path.pop() for i inrange(startindx, len(s)): end = i +1 temp = int(s[startindx:end]) if0 < temp and temp <= 255: path.append(str(temp)) backtracing(path, end) path.pop() else: break backtracing(path, 0) return result
二叉树的中序遍历 - leetcode 94
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
# Definition for a binary tree node. # class TreeNode: # def __init__(self, val=0, left=None, right=None): # self.val = val # self.left = left # self.right = right classSolution: definorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
defmid_order(root, ret=[]): if root isNone: return []
mid_order(root.left, ret) ret.append(root.val)
mid_order(root.right, ret) return ret return mid_order(root, [])
不同的二叉搜索树 -leetcode 92
给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。
# 初始化行列 # print(dp) for i inrange(1, len(s2)+1): # 第一行 if s2[i-1] == s3[i-1]: dp[0][i] = dp[0][i-1] # print(dp, "初始化第一行") for i inrange(1, len(s1)+1 ): # 第一列 if s1[i-1] == s3[i-1]: dp[i][0] = dp[i-1][0] for i inrange(1, len(s1)+1): for j inrange(1, len(s2)+1): if s1[i-1] == s3[i+j-1]: dp[i][j] = dp[i-1][j] if s2[j-1] == s3[i+j-1]: dp[i][j] = dp[i][j] or dp[i][j-1] return dp[-1][-1]
动态规划问题
dp 数组的定义以及下标的含义dp[i][j]
递推公式
dp数组如何初始化
遍历顺序
打印dp数组
动态规划解决斐波那契数
dp数组下标以及含义dp[i], 第i个斐波那契数,dp[i]表示第i个斐波那契数值
递推公式dp[i] = dp[i-1] + dp[i-1]
初始化:dp[0] = 1 dp[1] = 1
遍历顺序:从前向后
打印dp数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
deffibonc(n): dp = [1, 1] #dp[0], dp[1] = 1, 1 if n ==0or n ==1: return1 i = 2 while i <=n:
dp.append(dp[i-1] + dp[i-2]) i+=1 return dp[i-1]
if __name__ == "__main__": fibonc(n)
动态规划解决上楼梯问题
n阶台阶,一次可以上一阶或者两阶,到达第n阶有几种方法
1阶 1
2阶 2
3阶 3
4阶 5
动归五部曲
dp[i] 表示上到第i阶的所有方法
递推公式: dp[i] = dp[i-1] + dp[i-2]
初始化:dp[0] = 0, dp[1]=1, dp[2] = 2
确定遍历顺序: 从头向后
打印dp数组
1 2 3 4 5 6 7 8 9 10
defsolution(n): dp = [1, 2] if n ==1or n ==2: return1if n==1else2 i = 2 while i <=n: dp.append(dp[i-1] + dp[i-2]) i+=1 return dp[n]
# 判断同一列是否满足 for i inrange(len(board)): if board[i][col] == "Q": returnFalse
# 判断左上角是否满足 i = row -1 j = col -1
while i >=0and j >=0: if board[i][j] == "Q": returnFalse i -= 1 j -= 1
# 判断右上是否满足 i = row -1 j = col +1
while i >=0and j< len(board): if board[i][j] == "Q": returnFalse i -= 1 j += 1 returnTrue
defbacktracing(board, row, n):
if row == n: tmp_res = list() for temp in board: tmp_res.append("".join(temp)) res.append(tmp_res[:]) return for col inrange(n): ifnot isValid(board, row, col): continue
while i < len(intervals)-1: if i == 0: temp.append(intervals[0]) pre_end = temp[-1][1] nex_start=intervals[i+1][0] if nex_start < pre_end: del_num +=1 i + 1 else: temp.append(intervals[i+1]) i += 1 return del_num
跳跃游戏-leetcode 55
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution: defcanJump(self, nums: List[int]) -> bool: """ 由于每层最多可以跳A[i]步,也可以跳0步或1步,因此如果能到达最高层,则说明每一层都可以到达。有了这个条件,说明可以用贪心算法 正向,从0出发,一层一层往上跳,看到最后能不能超过最高层,能超过则说明能到达,否则不能到达 """ """ 0 1 2 3 4 [ 2, 3, 1, 1, 4] """ # 维护最远下标 last_index = 0 for i inrange(len(nums)): if i <= last_index: last_index = max(last_index, i + nums[i]) if last_index >= len(nums) -1: returnTrue returnFalse
classSolution: defmaxProfit(self, prices: List[int]) -> int: """ 找到每一个上坡,相加就是最终的结果 """ ans = 0 for i inrange(len(prices)-1): if prices[i+1] >prices[i]: ans += prices[i+1] - prices[i] return ans