快速幂+贪心思想
- p=x+y
- min(xy)
R(x,y)=xy+v(p-x-y)
易知(v,v)是R的最大值,而向x,y距离越远,xy值越小,多变量亦具有该性质
给你一个正整数 p 。你有一个下标从 1 开始的数组 nums ,这个数组包含范围 [1, 2p - 1] 内所有整数的二进制形式(两端都 包含)。你可以进行以下操作 任意 次:
从 nums 中选择两个元素 x 和 y 。
选择 x 中的一位与 y 对应位置的位交换。对应位置指的是两个整数 相同位置 的二进制位。
比方说,如果 x = 1101 且 y = 0011 ,交换右边数起第 2 位后,我们得到 x = 1111 和 y = 0001 。
请你算出进行以上操作 任意次 以后,nums 能得到的 最小非零 乘积。将乘积对 109 + 7 取余 后返回。
注意:答案应为取余 之前 的最小值。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-non-zero-product-of-the-array-elements
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
mod = 1000000007
class Solution:
def minNonZeroProduct(self, p: int) -> int:
if p==1:
return 1
hi=(1<>1,mod)*hi%mod
快速幂算法:
int qpow(int a, int n){
int ans = 1;
while(n){
if(n&1) //如果n的当前末位为1
ans *= a; //ans乘上当前的a
a *= a; //a自乘
n >>= 1; //n往右移一位
}
return ans;
}
解码方法
一条包含字母 A-Z 的消息通过以下映射进行了 编码 :
'A' -> 1
'B' -> 2
...
'Z' -> 26
要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,"11106" 可以映射为:
"AAJF" ,将消息分组为 (1 1 10 6)
"KJF" ,将消息分组为 (11 10 6)
注意,消息不能分组为 (1 11 06) ,因为 "06" 不能映射为 "F" ,这是由于 "6" 和 "06" 在映射中并不等价。
给你一个只含数字的 非空 字符串 s ,请计算并返回 解码 方法的 总数 。
题目数据保证答案肯定是一个 32 位 的整数。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/decode-ways
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution:
def numDecodings(self, s: str) -> int:
hash_set=set()
for i in range(1,27):
hash_set.add(str(i))
dp=[0]*(len(s)+1)
#dp[0]=-1
if len(s)==1:
if s in hash_set:
return 1
cnt=0
for i in range(len(s)):
if s[i]=='0' and cnt==0:
cnt+=1
if dp[i]==0 or i>0 and int(s[i-1])>2 :
return 0
else:
dp[i+1]=dp[i-1]
elif cnt>0:
cnt=0
#print('cnt!=0')
#print(s[i])
if s[i]=='0':
#print('here')
return 0
else:
dp[i+1]=dp[i]
#print('hi')
elif cnt==0:
dp[0]=1
dp[i+1]=dp[i]
if s[i-1:i+1] in hash_set:
#print('he')
dp[i+1]+=dp[i-1]
#print(dp)
return dp[len(s)]
其中关键点有二:
- 前导零问题
- 二位数是否在编码范围之内
故改进代码如下
class Solution:
def numDecodings(self, s: str) -> int:
hash_set=set()
for i in range(1,27):
hash_set.add(str(i))
dp=[0]*(len(s)+1)
dp[0]=1
for i in range(len(s)):
if s[i]=='0':
if i==0 or i>0 and s[i-1] not in ['1','2']:
return 0
else:
dp[i+1]=dp[i-1]
else:
if i>0:
'''
if s[i-1]!='0':
if s[i-1:i+1] in hash_set:
dp[i+1]=dp[i]+dp[i-1]
else:
dp[i+1]=dp[i]
else:
dp[i+1]=dp[i]
'''
dp[i+1]=dp[i]#长度为1转移一定可以实现
if s[i-1]!='0' and s[i-1:i+1] in hash_set:#唯一的长度为2转移条件
dp[i+1]+=dp[i-1]
else:
dp[i+1]=1
return dp[-1]
关于DNA的模式识别,利用其只有ACGT
给定一个二维矩阵 matrix,以下类型的多个请求:
计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2) 。
实现 NumMatrix 类:
NumMatrix(int[][] matrix) 给定整数矩阵 matrix 进行初始化
int sumRegion(int row1, int col1, int row2, int col2) 返回左上角 (row1, col1) 、右下角 (row2, col2) 的子矩阵的元素总和。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/range-sum-query-2d-immutable
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class NumMatrix:
def __init__(self, matrix: List[List[int]]):
self.n=len(matrix[0])
self.m=len(matrix)
self.matrix =[[matrix[i][j] for j in range(self.n)] for i in range(self.m)]
self.dp=[[0]*self.n for _ in range(self.m)]
for i in range(self.m):
for j in range(self.n):
self.dp[i][j]=self.matrix[i][j]
if i>=1:
self.dp[i][j]+=self.dp[i-1][j]
if j>=1:
self.dp[i][j]+=self.dp[i][j-1]
if i>=1 and j>=1:
self.dp[i][j]-=self.dp[i-1][j-1]
def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int:
#前缀和矩阵[]
ans=self.dp[row2][col2]
if col1>0:
ans-=self.dp[row2][col1-1]
if row1>0:
ans-=self.dp[row1-1][col2]
if col1>0 and row1>0:
ans+=self.dp[row1-1][col1-1]
return ans
- 前缀和+容斥原理
- 容斥原理:为了不重不漏,使用AUB=A+B-A^B,即把所用包含的集合相加,再相减其重叠部分
给你一个下标从 1 开始的二进制矩阵,其中 0 表示陆地,1 表示水域。同时给你 row 和 col 分别表示矩阵中行和列的数目。
一开始在第 0 天,整个 矩阵都是 陆地 。但每一天都会有一块新陆地被 水 淹没变成水域。给你一个下标从 1 开始的二维数组 cells ,其中 cells[i] = [ri, ci] 表示在第 i 天,第 ri 行 ci 列(下标都是从 1 开始)的陆地会变成 水域 (也就是 0 变成 1 )。
你想知道从矩阵最 上面 一行走到最 下面 一行,且只经过陆地格子的 最后一天 是哪一天。你可以从最上面一行的 任意 格子出发,到达最下面一行的 任意 格子。你只能沿着 四个 基本方向移动(也就是上下左右)。
请返回只经过陆地格子能从最 上面 一行走到最 下面 一行的 最后一天 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/last-day-where-you-can-still-cross
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二分答案+多源DFS
特别注意check函数的书写
- 一条性质,此时是找到mid满足后依然记录,试图找到mid满足的最小值
- mid满足即mid天可以从第一行走到最后一行
class Solution:
def latestDayToCross(self, row: int, col: int, cells: List[List[int]]) -> int:
#直接一次过
def check(day):
grid=[[0]*col for _ in range(row)]
for i,j in cells[:day]:
grid[i-1][j-1]=1
for i in range(col):
if dfs(0,i,row,col,grid):
return True
return False
def dfs(x,y,row,col,grid):
if 0<=x>1
if check(mid):
res=max(res,mid)
l=mid
else:
r=mid-1
return res
给定一个未排序的整数数组,找到最长递增子序列的个数。
示例 1:
输入: [1,3,5,4,7]
输出: 2
解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, 3, 5, 7]。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-longest-increasing-subsequence
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
想到一个O(N^3)的方法,被卡住过不去
二维数组dp_s[i][j]是到位置i元素,长度为j的不同排列个数
class Solution:
def findNumberOfLIS(self, nums: List[int]) -> int:
#算法正确性是有的,但是不具备高效性
dict_,n={},len(nums)
#dp=[1]*n
dp_s=[[0]*n for _ in range(n)]
for i in range(n):
dp_s[i][0]=1
for i in range(n):
for j in range(i):
for jj in range(j+1):
if nums[i]>nums[j]:
#print('here')
dp_s[i][jj+1]+=dp_s[j][jj]
#dict_[dp[i]]=dict_.get(dp[i],0)+1
#print(dp_s)
max_=0
for i in range(n-1,-1,-1):
for j in range(n):
if dp_s[j][i]==0:
continue
else:
max_=max(max_,dp_s[j][i])
if max_!=0:
ans=0
for j in range(n):
ans+=dp_s[j][i]
return ans
#print(dict_)
#return dict_[max(dp)]
return 0
标解一,使用空间(其实并不是多占了内存,而是多个独立的变量相比二维数组功能更强大)换取时间。
class Solution:
def findNumberOfLIS(self, nums: List[int]) -> int:
n=len(nums)
length=[0]*n
count=[1]*n
for i in range(n):
for j in range(i):
if nums[i]>nums[j]:
if length[j]>=length[i]:#记录最大值的专业个数,以及长度,以及使用长度作为判断条件
length[i]=length[j]+1
count[i]=count[j]
elif length[j]==length[i]-1:
count[i]+=count[j]
max_=max(length)
return sum([c for i,c in enumerate(count) if length[i]==max_])
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
输入:head = [1,2,3,4]
输出:[2,1,4,3]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/swap-nodes-in-pairs
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
本想省内存,结果在时间复杂度上更突出
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def swapPairs(self, head: ListNode) -> ListNode:
#省内存的方式
if not head or not head.next:
return head
head_new=head.next
tail=head
tail.next=head_new.next
head_new.next=tail
while tail.next and tail.next.next:
mery=tail.next.next
tail.next.next=mery.next
mery.next=tail.next
tail.next=mery
tail=tail.next.next
return head_new