力扣小记
平方数之和:给定一个非负整数 c
,你要判断是否存在两个整数 a
和 b
,使得 $a^2$ + $b^2$ = c。
费马定理:
1、任何形为$4n+1$的素数都能表示为两个平方数之和。
2、如果两个整数都能表示为两个平方数之和,则它们的积也能表示为两个平方数之和。
斐波那契恒等式:$(a^2+b^2)+(p^2+q^2) = (ap+bq)^2+(aq-bp)^2$
数字根:给定一个非负整数 num
,反复将各个位上的数字相加,直到结果为一位数。
原数: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
数根: 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3
解法:对九取余即可
最低票价:
在一个火车旅行很受欢迎的国度,你提前一年计划了一些火车旅行。在接下来的一年里,你要旅行的日子将以一个名为 days 的数组给出。每一项是一个从 1 到 365 的整数。
火车票有三种不同的销售方式:
一张为期一天的通行证售价为 costs[0] 美元;
一张为期七天的通行证售价为 costs[1] 美元;
一张为期三十天的通行证售价为 costs[2] 美元。
通行证允许数天无限制的旅行。 例如,如果我们在第 2 天获得一张为期 7 天的通行证,那么我们可以连着旅行 7 天:第 2 天、第 3 天、第 4 天、第 5 天、第 6 天、第 7 天和第 8 天。
返回你想要完成在给定的列表 days 中列出的每一天的旅行所需要的最低消费。
1 <= days.length <= 365
1 <= days[i] <= 365
days 按顺序严格递增
costs.length == 3
1 <= costs[i] <= 1000
解法:动态规划
动态规划的一般做法:
1、建立连续的数组来记录数据,以下标的形式查找,但会消耗内存。
2、递归的方法,找到动态方程。
题目解法:
1、建立空间为365大小的连续数组,记录每天的花费,i表示第i天之前的总花费。
2、没有旅行的第i天则是与第i - 1天相同
3、取i - 1 、i - 7和i - 30的最小值。返回最后旅行的总花费。
1 def mincostTickets(days, costs): 2 3 re = [0] * 365 4 i = 0 5 for index in range(365): 6 if i == len(days): 7 break 8 if index != days[i] - 1: 9 re[index] = re[index - 1] 10 continue 11 12 if days[i] - 1 < 0: 13 tmp1 = costs[0] 14 else: 15 tmp1 = re[days[i] - 2] + costs[0] 16 if days[i] - 7 < 0: 17 tmp2 = costs[1] 18 else: 19 tmp2 = re[days[i] - 8] + costs[1] 20 if days[i] - 30 < 0: 21 tmp3 = costs[2] 22 else: 23 tmp3 = re[days[i] - 31] + costs[2] 24 re[index] = min(tmp1,tmp2,tmp3) 25 i += 1 26 27 return re[days[-1] - 1]
填充书架:
附近的家居城促销,你买回了一直心仪的可调节书架,打算把自己的书都整理到新的书架上。
你把要摆放的书 books 都整理好,叠成一摞:从上往下,第 i 本书的厚度为 books[i][0],高度为 books[i][1]。
按顺序 将这些书摆放到总宽度为 shelf_width 的书架上。
先选几本书放在书架上(它们的厚度之和小于等于书架的宽度 shelf_width),然后再建一层书架。重复这个过程,直到把所有的书都放在书架上。
需要注意的是,在上述过程的每个步骤中,摆放书的顺序与你整理好的顺序相同。 例如,如果这里有 5 本书,那么可能的一种摆放情况是:第一和第二本书放在第一层书架上,第三本书放在第二层书架上,第四和第五本书放在最后一层书架上。
每一层所摆放的书的最大高度就是这一层书架的层高,书架整体的高度为各层高之和。
以这种方式布置书架,返回书架整体可能的最小高度。
1、创建数组来存储每一次放完书的最低高度,创建n + 1长度的数组,第一位为0,没有开始放书。
2、放完第 i 本书后不断往前调整数的位置,逐渐与前一位的书放在同一层书架中,在宽度超出限制或者循环到第一本书则结束。
1 class Solution: 2 def minHeightShelves(self, books: List[List[int]], shelf_width: int) -> int: 3 4 n = len(books) 5 f = [0] * (n + 1) 6 for index in range(n): 7 high = f[index] + books[index][1] # 记录加入书后书架的高度 8 width = books[index][0] # 新加入书的宽度 9 h = books[index][1] # 书的高度 10 for i in range(index - 1,-1,-1): # 调整前面的书 11 width += books[i][0] # 与前面的书放在一起后的宽度 12 if width > shelf_width: # 超过限制则退出 13 break 14 h = max(h,books[i][1]) # 合并书到一起的最大高度 15 high = min(high,f[i] + h) # 取最小的高度 16 f[index + 1] = high 17 return f[-1]
最大正方形:在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积。
解法:
1、d[i][j] 表示矩阵 i ,j 位置的最大面积的边长。
2、动态方程:$d[i][j] = max(d[i - 1][j],d[i -1][j - 1],d[i][j - 1]) + 1$
1 class Solution: 2 def maximalSquare(self, matrix: List[List[str]]) -> int: 3 if not matrix: 4 return 0 5 n,m = len(matrix),len(matrix[0]) 6 re = 0 7 for i in range(n): 8 for j in range(m): 9 if matrix[i][j] == '1': 10 t1 = 0 if i - 1 < 0 else matrix[i - 1][j] 11 t2 = 0 if i - 1 < 0 or j - 1 < 0 else matrix[i - 1][j - 1] 12 t3 = 0 if j - 1 < 0 else matrix[i][j - 1] 13 14 matrix[i][j] = min(t1,t2,t3) + 1 15 re = max(re,matrix[i][j]) 16 else: 17 matrix[i][j] = 0 18 return re * re
power:计算 x 的 n 次幂函数。
快速幂+递归:$x \to x^2 \to x^4 \to x^9 \to x^{19} \to x^{38} \to x^{77}$,在上述的过程中我们只需要知道是否需要多乘一个 x,
1、当我们要计算 $x^n$时,我们可以先递归地计算出 $y = x^{[ n / 2 ]}$,其中 [ n / 2 ]表示对 a 进行下取整;
2、根据递归计算的结果,如果$n$为偶数,那么$x^n = y^2$,如果 n 为奇数,那么$x^n = y^2 * x$。
3、递归的边界为 $n = 0$,任意数的 0 次方均为 1。
class Solution: def myPow(self, x: float, n: int) -> float: def quickMul(N): if N == 0: return 1.0 y = quickMul(N // 2) return y * y if N % 2 == 0 else y * y * x return quickMul(n) if n >= 0 else 1.0 / quickMul(-n)
快速幂+迭代:
class Solution: def myPow(self, x: float, n: int) -> float: def quickMul(N): ans = 1.0 # 贡献的初始值为 x x_contribute = x # 在对 N 进行二进制拆分的同时计算答案 while N > 0: if N % 2 == 1: # 如果 N 二进制表示的最低位为 1,那么需要计入贡献 ans *= x_contribute # 将贡献不断地平方 x_contribute *= x_contribute # 舍弃 N 二进制表示的最低位,这样我们每次只要判断最低位即可 N //= 2 return ans return quickMul(n) if n >= 0 else 1.0 / quickMul(-n)
滑动窗口的最大值:给定一个数组 nums
和滑动窗口的大小 k
,请找出所有滑动窗口里的最大值。
以一个队列来实现窗口的排序,队列的头部是最大值,新元素都会进入队列,但是将要进入的数比尾部的数大则尾部退出队列,不断重复直至保持队列的有序性。
def maxSlidingWindow(nums,k): deque = [];result = [] # deque也可以用collection里的双端队列实现 for i in range(0, len(nums)): while deque and nums[i]>nums[deque[-1]]: # 只存有可能成为最大值的数字的index进deque deque.pop() # 尾部出队列 deque.append(i) while i-deque[0]>k-1: # 如果相距超过窗口k长度则弃掉 deque.pop(0) # 头部出队列 if i >= k-1: # 数组的长度小于k则返回空值 result.append(nums[deque[0]]) # 这过程中始终保持deque[0]为最大值的index return result maxSlidingWindow([1,3,-1,-3,-2,3,6,7],3)
最小栈:
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。
push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。
解法:建一个辅助栈,存储主栈元素对应的最小值。
入栈:入栈元素与辅助栈的栈顶元素相比,选最小的入辅助栈
出栈:辅助栈和主栈元素一起出栈
class MinStack: def __init__(self): """ initialize your data structure here. """ self.re = [] self.min_stack = [] def push(self, x: int) -> None: self.re.append(x) if not self.min_stack: self.min_stack.append(x) else: self.min_stack.append(min(x,self.min_stack[-1])) def pop(self) -> None: self.re.pop() self.min_stack.pop() def top(self) -> int: return self.re[-1] def getMin(self) -> int: return self.min_stack[-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()