1. 岛屿数量问题
他是个色盲,蓝绿不分。连通块,上下左右连接,则认为是一个连通块。
输入grid=[ [“R”, “R”, “G”, “G”, “B”, “B”],
[“R”, “G”, “B”, “G”, “R”, “R”]]
正常人会认为有6个连通块,但是由于他是色盲,会导致他只看到3个连通块,现在求解任何一个矩阵,他会比正常人少看多少个连通块。
分析:
R不会影响差值,结果就是B岛屿数量+G岛屿数量-BG联合形成的岛屿数量
def numIslands(grid,mark) -> int: #grid 为矩阵,mark为印记
dir=[[-1,0],[0,1],[1,0],[0,-1]]
ans=0
def dfs(x,y):
grid[x][y]='0'
for k in range(4):
dx=x+dir[k][0]
dy=y+dir[k][1]
if dx>=0 and dx<len(grid) and dy>=0 and dy<len(grid[0]) and grid[dx][dy]==mark:
dfs(dx,dy)
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j]==mark:
dfs(i,j)
ans+=1
return ans
例子:
arr=[[1,0,0],[1,1,0],[0,0,1]]
numIslands(arr,1) #即数数1的连通块有几个
那么本题的解法
grid=[["R", "R", "G", "G", "B", "B"],["R", "G", "B", "G", "R", "R"]]
#此处使用了列表推倒式,将色盲眼中的颜色进行了替换
grid_semang=[[x if x=="R" else "G" for x in y] for y in grid]
numIslands(grid,'B')+numIslands(grid,'G')-numIslands(grid_semang,'G')
2.将数据排序
// 输入两个数n,m,输出 n * m 的按列递增的矩阵,超出9的部分从0开始
// 例:n=3,m=4
// 0 3 6 9
// 1 4 7 0
// 2 5 8 1
分析:利用模运算即可
n,m=map(int,input().split())
word=list(range(10))
ans=[[0 for _ in range(m)] for _ in range(n)]
cnt=0
for j in range(m):
for i in range(n):
ans[i][j]=word[cnt%10]
cnt+=1
for i in ans:print(i)
结果:
3 4. #输入的m 和 n
[0, 3, 6, 9]
[1, 4, 7, 0]
[2, 5, 8, 1]
3.n皇后问题
首先来看一下皇后们的约束条件:
1.不能同行
2.不能同列
3.不能同斜线
分析:采用回溯的方法,行是深度,列是宽度,注意python的拷贝
from copy import deepcopy
def backtacking(n,row,chessboard):
if row==n:
# print(chessboard)
# tmp=chessboard.copy()
res.append(deepcopy(chessboard))
for col in range(n):
if isValid(row,col,chessboard,n):
chessboard[row][col]='Q'
backtacking(n,row+1,chessboard)
chessboard[row][col]='.'
def isValid(row,col,chessboard,n):
#检查列
for i in range(row):
if chessboard[i][col]=='Q':
return False
#检查45度
i=row-1
j=col-1
while i>=0 and j>=0:
if chessboard[i][j]=='Q':
return False
i-=1
j-=1
#检查135度
i=row-1
j=col+1
while i>=0 and j<n:
if chessboard[i][j]=='Q':
return False
i-=1
j+=1
return True
def solveNQueens(n,res):
chessboard=[['.' for _ in range(n)] for _ in range(n)]
backtacking(n,0,chessboard)
return res
res=[]
solveNQueens(4,res)
运行结果:
[[['.', 'Q', '.', '.'],
['.', '.', '.', 'Q'],
['Q', '.', '.', '.'],
['.', '.', 'Q', '.']],
[['.', '.', 'Q', '.'],
['Q', '.', '.', '.'],
['.', '.', '.', 'Q'],
['.', 'Q', '.', '.']]]
3.1 n 皇后
题目描述
米小游最近在研究 n 皇后问题。 所谓 n 皇后问题,指 n×n 的棋盘中,放置 n 个皇后,满足两两之间不会互相攻击。
每个皇后可以攻击同一行、同一列以及同一 45度角斜线和 135度角斜线上的所有其他皇后。
米小游拿到了一个 n×n 的棋盘,目前已经放置了一些皇后,米小游希望再放置一个皇后, 满足所有的皇后不会互相攻击。
你能帮米小游求出有多少种放置方案吗?
输入描述
第一行输入一个正整数 n ,代表棋盘大小。
接下来的 n 行,每行输入一个仅由 … 和 ∗∗ 组成的字符串,其中 ∗代表放置了一个皇后, .代表未放置皇后。
保证输入的棋盘中没有两个皇后会互相攻击。1≤n≤1000
3
.*.
…
…
输出描述
输出米小游有多少种放置方案。2
分析:对棋盘上没有放置皇后的位置进行遍历,判断是否合理。
def isValid(n,row,col,chessboard):
#查看列
for i in range(n):
if chessboard[i][col] != '.':
return False
#查看行
for j in range(n):
if chessboard[row][j] != '.':
return False
#查看45度
i=row-min(row,col)
j=col-min(row,col)
while i<n and j<n:
if chessboard[i][j] != '.':
return False
i+=1
j+=1
#查看135度
i=0
j=col+row
while j>=0 and i<n :
if j<n and chessboard[i][j] != '.':
return False
j-=1
i+=1
return True
def solvequeen(n,chessboard):
s=0
for i in range(n):
for j in range(n):
if chessboard[i][j]=='.' and isValid(n,i,j,chessboard):
s+=1
return s
chessboard=[['.','*','.'],['.','.','.'],['.','.','.']]
solvequeen(3,chessboard)
解法2:遍历有皇后的位置,将其攻击区域改为#,之后计算没有攻击的位数,便是下一个皇后可以放置的方案数
def attck(n,row,col,chessboard):
#修改列
for i in range(n):
chessboard[i][col] = '#'
#修改行
for j in range(n):
chessboard[row][j] = '#'
#修改45度
i=row-min(row,col)
j=col-min(row,col)
while i<n and j<n:
chessboard[i][j] = '#'
i+=1
j+=1
#修改135度
i=0
j=col+row
while j>=0 and i<n :
if j<n :
chessboard[i][j] = '#'
j-=1
i+=1
def solvequeen_2(n,chessboard):
for i in range(n):
for j in range(n):
if chessboard[i][j]=='*':
attck(n,i,j,chessboard)
s=0
for i in chessboard:
for j in i:
if j=='.':
s+=1
return s
chessboard=[['.','*','.'],['.','.','.'],['.','.','.']]
solvequeen_2(3,chessboard)
4.小明去游乐园
题目描述
游乐场有n个项目,每个项目必须在时间ti前才能玩,玩一个项目需要花一个小时,小明0点进入游乐场
每个项目有对应的积分 玩了能获得积分 没玩要扣除相应的积分 求最多能获得多少分 比如
3
3 1 1
3 6 9
3个项目 分别在3点前 1点前 1点前参加 分别的积分是 3 6 9 算上游玩要花的一个小时 其实是要在 2点 0点 0 点 之前去玩 所以样例最多积分是 9+3-6=6分
思路
该问题类似背包问题,显然最佳策略是尽量的得分,这样扣分也会相对应得减少,总分也会略高。准备一个数组来记录玩的项目的分数,该数组可以存储当前分数的最小值。根据时间进行从低到高的排序,接着进行循环遍历,时间是背包的容量,如果遍历到某个项目比数组中的最小值大,则进行替代。
分析:该题目是加了权重的贪心算法
5.大整数截取
花花有一个很珍贵的数字串,但是它太长了,没有办法保留下来,所以她想截取其中一段保存下来,但是她希望截取下来的这一段数对1000000007取模之后等于Ai,她想知道有多少种截取方案。数字串S中截取一段是指S[L], S[L+1], …, S[R]连起来所形成的十进制数,其中L和R满足1≤L≤R≤|S|。例如S=“1023456789”,S(0,2)=10,S(2,4)=23,S(2,10)=23456789。
输入描述
第一行一个数字串,长度不超过30000。
第二行一个数T,表示询问的数量。(T≤100)
接下来T行,每行一个非负整数Ai,表示询问有多少种截取方案使得其值模1000000007后等于Ai。(0≤Ai<1000000007)
输出描述
共T行,每行一个非负整数,表示方案数。
样例输入
1000000008001
4
8
0
1
10
样例输出
9
39
5
2
def getCountofMod(s,mod,key):
n=len(s)
cnt=0
for i in range(n):
if s[i] != '0':
tmp=int(s[i])
if tmp==key:
print(tmp)
cnt+=1
for j in range(i+1,n):
tmp=((tmp*10)%mod+int(s[j]))%mod
if tmp==key:
print(s[i:j+1])
cnt+=1
return cnt
s='1000000008001'
mod=1000000007
key=10
getCountofMod(s,mod,key)
结果:
10
10000000080
2
6最短子串
题目描述
米小游拿到了一个字符串,她想截取一个连续子串,使得该子串中包含至少k个连续的“mihoyo”。 帮米小游求出最短的子串长度,以及对应的子串位置
输入描述
第一行输入两个正整数n和k,用空格隔开。 第二行输入一个长度为n的、仅由小写字母组成的字符串。
输出描述
如果不存在这样一个连续子串,请输出-1。 否则输出两个正整数l,r,代表选取的子串的左下标和右下标(整个字符串左下标为0,右下标为n-1)。 请务必保证选择的连续子串包含至少k个"mihoyo",且长度是最短的。有多解时输出任意即可。
思路:将mihoyo看作一个整体