LeetCode 每日一题 2024/12/2-2024/12/8

记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步




12/2 52. N 皇后 II

dfs
使用三个set记录已有皇后的位置
列,左到右的斜线,右到左的斜线
y, x+y, x-y
如果当前位置可以放 那么将这三个值放入 并记录当前x层的列位置y
查看下一层x+1
如果已到了最后一层则保存当前其情况
否则将刚才的状态清空 查看下一个位置

def totalNQueens(n):
    """
    :type n: int
    :rtype: int
    """
    col,ltr,rtl =set(),set(),set()
    ans=[]
    pos=[]
    def dfs(y):
        for x in range(n):
            if (x not in col) and ((x+y) not in ltr) and ((x-y) not in rtl):
                col.add(x)
                ltr.add(x+y)
                rtl.add(x-y)
                pos.append(x)
                if y+1==n:
                    tmp=pos[:]
                    ans.append(tmp)
                else:
                    dfs(y+1)
                col.remove(x)
                ltr.remove(x+y)
                rtl.remove(x-y)
                pos.pop()
    dfs(0)
    return(len(ans))



12/3 3274. 检查棋盘方格颜色是否相同

a看作0 相加奇偶性一致颜色一致

def checkTwoChessboards(coordinate1, coordinate2):
    """
    :type coordinate1: str
    :type coordinate2: str
    :rtype: bool
    """
    if (ord(coordinate1[0])+int(coordinate1[1])-ord(coordinate2[0])-int(coordinate2[1]))%2==0:
        return True
        



12/4 2056. 棋盘上有效移动组合的数目

createmoves 生成某个棋子所有可能移动
check检查两个棋子移动是否会重叠
枚举每个合法移动 如果棋子没有重叠则答案+1
如果当前棋子移动和前面棋子冲突则不往下递归

def countCombinations(pieces, positions):
    """
    :type pieces: List[str]
    :type positions: List[List[int]]
    :rtype: int
    """
    def createmoves(x0,y0,dirs):
        moves = [(x0,y0,0,0,0)]
        for dx,dy in dirs:
            x,y=x0+dx,y0+dy
            step = 1
            while 0<x<=8 and 0<y<=8:
                moves.append((x0,y0,dx,dy,step))
                step+=1
                x+=dx
                y+=dy
        return moves
    def check(m1,m2):
        x1,y1,dx1,dy1,step1=m1
        x2,y2,dx2,dy2,step2=m2
        for i in range(max(step1,step2)):
            if i<step1:
                x1+=dx1
                y1+=dy1
            if i<step2:
                x2+=dx2
                y2+=dy2
            if x1==x2 and y1==y2:
                return False
        return True
    rookstep = [(1,0),(0,1),(-1,0),(0,-1)]
    bishopstep = [(1,1),(1,-1),(-1,1),(-1,-1)]
    allsteps={'r':rookstep,'b':bishopstep,'q':rookstep+bishopstep}
    allmoves=[createmoves(x,y,allsteps[p[0]]) for p,(x,y) in zip(pieces,positions)]
    
    n=len(pieces)
    path=[None]*n
    global ans
    ans=0
    def dfs(i):
        global ans
        if i==n:
            ans+=1
            return 
        for m1 in allmoves[i]:
            if all(check(m1, m2) for m2 in path[:i]):
                path[i]=m1
                dfs(i+1)
    dfs(0)
    return ans



12/5 3001. 捕获黑皇后需要的最少移动次数

在没有阻挡的情况下
不管什么位置 车最多用两步捕获皇后
象在斜线上 无阻挡用一步
先判断象和皇后是否在一条斜线上
如果车在他们中间则返回2 否则返回1
在判断车和皇后是否在一条直线上
如果象在中间 则返回2 否则1
其余情况车到皇后需要两步

def minMovesToCaptureTheQueen(a, b, c, d, e, f):
    """
    :type a: int
    :type b: int
    :type c: int
    :type d: int
    :type e: int
    :type f: int
    :rtype: int
    """
    if abs(c-e)==abs(d-f):
        if abs(a-c)==abs(b-d) and min(c,e)<a<max(c,e) and min(d,f)<b<max(d,f):
            return 2
        else:
            return 1
    if a==e:
        if c==a and min(b,f)<d<max(b,f):
            return 2
        else:
            return 1
    if b==f:
        if d==b and min(a,e)<c<max(a,e):
            return 2
        else:
            return 1
    return 2



12/6 999. 可以被一步捕获的棋子数

找到车的位置 向四个方向搜索是否第一个棋子为卒

def numRookCaptures(board):
    """
    :type board: List[List[str]]
    :rtype: int
    """
    n=8
    x0,y0=0,0
    for i in range(n):
        for j in range(n):
            if board[i][j]=='R':
                x0=i
                y0=j
                break
    ans = 0
    steps=[(1,0),(0,1),(-1,0),(0,-1)]
    for dx,dy  in steps:
        x,y=x0+dx,y0+dy
        while 0<=x<n and 0<=y<n:
            if board[x][y]=='p':
                ans+=1
                break
            if board[x][y]=='B':
                break
            x+=dx
            y+=dy
    return ans



12/7 688. 骑士在棋盘上的概率

dp[step][i][j]标记为从(i,j)出发走step步 仍在棋盘上的概率
如果step为0,(i,j)在棋盘上为1 不在棋盘上为0
每次有八种走法

def knightProbability(n, k, row, column):
    """
    :type n: int
    :type k: int
    :type row: int
    :type column: int
    :rtype: float
    """
    dp = [[[0]*n for _ in range(n)] for _ in range(k+1)]
    for step in range(k+1):
        for i in range(n):
            for j in range(n):
                if step==0:
                    dp[step][i][j]=1
                else:
                    for mi,mj in [(-2, -1), (-2, 1), (2, -1), (2, 1), (-1, -2), (-1, 2), (1, -2), (1, 2)]:
                        ni,nj = i+mi,j+mj
                        if 0<=ni<n and 0<=nj<n:
                            dp[step][i][j] += dp[step-1][ni][nj]*1.0/8
    return dp[k][row][column]



12/8 782. 变为棋盘

第一步 判断可行性
若需要变为棋盘 每一行或者每一列中1和0的个数差不超过1
对于某两行 i,j 行变换不会影响两行的对应位置差值
列变换同样不会影响两行所有位置差值和
例如 i:00110
j:11000
对于这两行 i,j 无论行列怎么变换必定存在某一列为两个0
所以若要变为棋盘 行的状态必定只能存在两种
并且两行内每个位置值相反
列状态也相同
第二部 计算移动次数
对于行来说 进行列移动改变状态
因为只存在两种相反状态的行
所以只需要将一行移动成功 对应的左右行也移动成功
只需考虑第一行移动成功的次数
如果每一行个数n为偶数 则有两种情况 判断成为0101…或者1010…哪一种次数少
如果n为奇数 则起始位置只能为个数多的1或者0一种情况
列的情况与行相同且互不影响
将两种情况相加即可
binvalue用来将数组l内的数组合为一个二进制数
numone用来统计二进制数内1的个数
mask0,mask1分别代表0101…,1010…两种状态结果

def movesToChessboard(board):
    """
    :type board: List[List[int]]
    :rtype: int
    """
    def binvalue(l):
        v = 0
        for i in l:
            v = (v<<1)+i
        return v
    def numone(v):
        ans = 0
        while v>0:
            if v&1==1:
                ans+=1
            v>>=1
        return ans
    
    n= len(board)
    row = sum(board[0])
    col = sum([board[i][0] for i in range(n)])
    if abs(2*row-n)>1 or abs(2*col-n)>1:
        return -1
    
    rowv = binvalue(board[0])
    colv = binvalue([board[i][0] for i in range(n)])       
    for i in range(1,n):
        tmpr = binvalue(board[i])
        if tmpr!=rowv and tmpr^rowv!=2**n-1:
            return -1
        tmpc = binvalue([board[j][i] for j in range(n)])
        if tmpc!=colv and tmpc^colv!=2**n-1:
            return -1
        
    mask0,mask1 = 0,0
    for i in range(n):
        mask0 = (mask0<<1)+(i%2)
        mask1 = (mask1<<1)+((i+1)%2)    
    total = 0
    if n%2==0:
        total += min(numone(rowv^mask0),numone(rowv^mask1))
        total += min(numone(colv^mask0),numone(colv^mask1))
    else:
        if row*2>n:
            total += numone(rowv^mask1)
        else:
            total += numone(rowv^mask0)
        if col*2>n:
            total += numone(colv^mask1)
        else:
            total += numone(colv^mask0)
    return total//2



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值