LeetCode 每日一题 2021/6/21-2021/6/27

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




6/21 401. Binary Watch 二进制手表

遍历所有存在的时间可能性
查看时间内亮的灯是否是需要的灯数

def readBinaryWatch(turnedOn):
    """
    :type turnedOn: int
    :rtype: List[str]
    """
    ret = []
    for i in range(12):
        for j in range(60):
            if bin(i).count('1')+bin(j).count('1')==turnedOn:
                ret.append(f'{i}:{j:02d}')
    return ret

6/22 剑指 Offer 38. 字符串的排列

排序防止重复

def permutation(s):
    """
    :type s: str
    :rtype: List[str]
    """
    l = list(s)
    l.sort()
    ret = []
    def func(l,tmp):
        if not l:
            ret.append(tmp)
            return
        n = len(l)
        i =0
        while i<n:
            c = l[i]
            tmp+=c
            func(l[:i]+l[i+1:],tmp)
            tmp=tmp[:-1]
            i+=1
            while i<n and l[i]==l[i-1]:
                i+=1
    func(l,'')
    print(ret)
    return ret

6/23 剑指 Offer 15. 二进制中1的个数

1.和1与 判断最后一位
往右挪一位 循环判断
2.每次n&(n-1) 去除n最后一位1

def hammingWeight(n):
    """
    :type n: int
    :rtype: int
    """
    res = 0
    while n > 0:
        res += n &1
        n >>= 1
    return res

def hammingWeight2(n):
    """
    :type n: int
    :rtype: int
    """
    ans = 0
    while n>0:
        ans +=1
        n &=(n-1)
    return ans

6/24 149. Max Points on a Line 直线上最多的点数

y=kx+b
根据x轴从小到大排序
记录x相同的直线有多少点
当ans大于一半的总数目时 必定是能够连接到的最多点数
find(k,b,loc):
寻找loc之后 满足k,b的点 小数误差|diff|<1e10
kb():
计算两点连成线的k,b
双层循环 决定组成直线的最初两点
跳过x相同的点
mem记录k,b 减少重复探查

def maxPoints(points):
    """
    :type points: List[List[int]]
    :rtype: int
    """
    points.sort(key=lambda x:x[0])
    if len(points)<3:
        return len(points)
    n = len(points)
    ans = 2
    pre = 1
    for p in range(1,n):
        if points[p][0]==points[p-1][0]:
            pre +=1
            ans = max(ans,pre)
        else:
            pre = 1
    if ans>n//2:
        return ans
    
    def find(k,b,loc):
        ans = 0
        ck = float('inf')
        for p in points[loc:]:
            x,y = p[0],p[1]
            if ck==x:
                continue
            diff = y-k*x-b
            if abs(diff)<1e-10:
                ans+=1
                ck=x
        return ans
    
    def kb(x1,x2,y1,y2):
        k = (y2-y1)*1.0/(x2-x1)
        b = y1-x1*k
        return k,b
    
    mem = {}
    for i in range(n-2):
        x1,y1=points[i][0],points[i][1]
        for j in range(i+1,n-1):
            x2,y2=points[j][0],points[j][1]
            if x2==x1:
                continue
            k,b = kb(x1,x2,y1,y2)
            if (k,b) in mem:
                continue
            mem[(k,b)]=1
            tmp = 2+find(k,b,j+1)
            ans = max(ans,tmp)
            if ans > n//2:
                return ans
    return ans

6/25 752. Open the Lock 打开转盘锁

  1. 从0000开始 BFS广搜 记录旋转次数
  2. 双向BFS
    从0000 和 target 开始分别向对方靠近
    l1,l2 记录当前两方需要探索字符串
    visited记录已经判断过的字符串
    每次挑选较少的情况来判断 len(l1)<len(l2)
def openLock(deadends, target):
    """
    :type deadends: List[str]
    :type target: str
    :rtype: int
    """
    dead = set(deadends)
    if "0000" in dead:
        return -1
    l = [("0000",0)]
    mem ={}
    while l:
        s,n = l.pop(0)
        if s==target:
            return n
        if s in mem:
            continue
        mem[s] = 1
        for i in range(4):
            for diff in [1,-1]:
                ls = list(s)
                v = int(ls[i])
                v = (v+diff)%10
                if v<0:
                    v+=10
                ls[i] = str(v)
                tmps = "".join(ls)
                if tmps==target:
                    return n+1
                if tmps in dead:
                    continue
                l.append((tmps,n+1))
    return -1

def openLock2(deadends, target):
    """
    :type deadends: List[str]
    :type target: str
    :rtype: int
    """
    visited=set()
    visited.add("0000")
    l1,l2 = set(),set()
    l1.add("0000")
    l2.add(target)
    step=0
    while l1 and l2:
        tmpset=set() 
        if len(l1)>len(l2):
            l1,l2=l2,l1
        for s in l1:
            if s in deadends:
                continue
            if s in l2:
                return step
            
            visited.add(s)
            for i in range(4):
                tmp=list(s)
                if tmp[i]=='9':
                    tmp[i]='0'
                else:
                    tmp[i]= str((int(tmp[i])+1))
                up = ''.join(tmp)
                if up not in visited:
                    tmpset.add(up)
                tmp=list(s)
                if tmp[i]=='0':
                    tmp[i]='9'
                else:
                    tmp[i]= str((int(tmp[i])-1))
                down = ''.join(tmp)
                if down not in visited:
                    tmpset.add(down)
        step+=1
        l1 = l2
        l2 = tmpset
            
    return -1

6/26 773. Sliding Puzzle 773. 滑动谜题

与752思路一致
BFS广度优先搜索 使用双向BFS节约时间
l1,l2 分别记录从起点,终点开始的移动情况
每次移动 情况少的一方len(l1)<len(l2)
当l1,l2中有相同的状态时 代表相遇 及可从起点走到终点

def slidingPuzzle(board):
    """
    :type board: List[List[int]]
    :rtype: int
    """
    def tag(board):
        t=""
        for i in range(2):
            for j in range(3):
                t += str(board[i][j])
        return t
    
    visited = set()
    visited.add(tag(board))
    l1,l2 = set(),set()
    l1.add(tag(board))
    l2.add("123450")
    step = 0
    move = [[0,1],[0,-1],[1,0],[-1,0]]
    while l1 and l2:
        tmpset = set()
        if len(l1)>len(l2):
            l1,l2=l2,l1
        for bd in l1:
            if bd in l2:
                return step
            visited.add(bd)
            x,y=0,0
            loc = 0
            for i in range(6):
                if bd[i]=="0":
                    loc = i
                    break
            x = loc//3
            y = loc%3
            for xx,yy in move:
                tmpx = x+xx
                tmpy = y+yy
                tmpbd = list(bd)
                if -1<tmpx<2 and -1<tmpy<3:
                    tmploc = 3*tmpx+tmpy
                    tmpbd[loc],tmpbd[tmploc]=tmpbd[tmploc],tmpbd[loc]
                    tmpstr = ''.join(tmpbd)
                    if tmpstr not in visited:
                        tmpset.add(tmpstr)
        step+=1
        l1 = tmpset
    return -1

6/27 909. Snakes and Ladders 蛇梯棋

将二维board拼接成一维
BFS广度优先搜索

def snakesAndLadders(board):
    """
    :type board: List[List[int]]
    :rtype: int
    """
    n = len(board)
    l = [0]
    reverse = False
    for i in range(n-1,-1,-1):
        tmp = board[i]
        if reverse:
            tmp = tmp[::-1]
        reverse = not reverse
        l.extend(tmp)
    
    b = [1]
    mem={}
    step = 0
    print(l)
    while b:
        tmp = []
        step +=1
        for loc in b:
            for i in range(1,7):
                new = loc+i
                if l[new]>-1:
                    new = l[new]
                if new ==n*n:
                    return step
                if new>n*n:
                    continue
                if new in mem:
                    continue
                tmp.append(new)
                mem[new]=step
        b=tmp[:]
    return -1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值