2021-06-20:二分查找,69,字典树,208,212,位运算,291,231,238

二分查找:

1.单调递增或者递减

2.存在上下界

3.能够通过索引访问

class Solution:
    def mySqrt(self, x: int) -> int:
        if(x == 0) or (x == 1):
            return x
        l ,r= 1 , x
        while(l <= r):
            m = (l+r) //2
            if( m == x//m):
                return m
            elif (m> x//m):
                r = m-1
            else:
                l = m+1
                res = m
        return res
                    

字典树:

Trie字典树的核心思想是空间换时间,利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的

例题208:

思路:

用字典一层一层存储,模拟多叉树的结构去搜索。

class Trie:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.dict = {}
        self.end_of_word = "True"
        
        

    def insert(self, word: str) -> None:
        """
        Inserts a word into the trie.
        """
        t = self.dict
        for w in word:
            if w not in t:
                t[w] = {}
            t = t[w]
        t['end'] = self.end_of_word

    def search(self, word: str) -> bool:
        """
        Returns if the word is in the trie.
        """
        t = self.dict
        for w in word:
            if w not in t:
                return False
            t= t[w]
        return t['end'] in t
        

    def startsWith(self, prefix: str) -> bool:
        """
        Returns if there is any word in the trie that starts with the given prefix.
        """
        t = self.dict
        for w in prefix:
            if w not in t:
                return False
            t= t[w]
        return True


# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)

错误地方:

1.在insert里面,无论w存不存在于这一层的字母中,都要进入下一层。每一层字典对应第几个字母。

2. 在search里面: return t['end'] in t 错误   

return 'end' in t 正确

在 insert里面,最后一个t = t[w] 最后一个字母w对应了一个空的字典。这个字典里面存了‘end’:'True'这一键值对

所以进入最后一个字母对应的字典以后,只要判断‘end’这个键在不在这个字典里面就行了。如果不在说明只是prefix

212

思路:

1.将单词全部加入字典树

2.从字典树的头部字母对应矩阵里面的字母,再对其上下左右的字母进行dfs遍历。如果吻合到end就append到res里面,如果不吻合就恢复走过的位置。为了不走重复的位置每次遍历要把位置的字母置“#”。为了不遍历重复的单词,我们把遍历打印过的单词end 键值变成 0(什么时候出现重复的情况?矩阵有两个不同的位置都能满足打印出这个单词的条件)

class Solution:
    def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
        self.dict={}
        self.row = len(board)
        self.col = len(board[0])
        self.res = []
        self.board = board
        for word in words:
            t = self.dict
            for w in word:
                if w not in self.dict:
                    t[w] = {}
                t = t[w]
                t["end"] = 1
            for i in range(self.row):
                for j in range(self.col):
                    self.dfs(i,j,self.dict,"")
            return self.res
    def dfs(self,i,j,trie,s):
        c = self.board[i][j]
        if c not in trie:
            return
        trie = trie[c]
        if "end" in trie and trie["end"] == 1:
            self.res.append(s+c)
            trie["end"] = 0
        self.board[i][j] = '#'
        for x,y in [[-1,0],[1,0],[0,1],[0,-1]]:
            temp_x = i + x
            temp_y = j + y
            if 0 <= temp_x <self.row and 0<= temp_y<self.col and self.board[i][j] != "#":
                dfs(temp_x,temp_y,trie,s+c)
        self.board[i][j] = c




问题:

1.在把单词加入字典树的时候; if w not in t. 此时我们已经把self.dict赋给t让t带进循环了

2.t["end"] = 1; 实在每个单词结束的时候,所以应该写在for w in word外面

3.下面用字典树前后左右遍历的时候,注意判断这一位重复了也是此前后左右的空。

4.如果这一层的dfs循环不下去了,记得恢复board上面的这个位置的字母

正确代码:

class Solution:
    def findWords(self, board: List[List[str]], words: List[str]) -> List[str]:
        self.dict={}
        self.row = len(board)
        self.col = len(board[0])
        self.res = []
        self.board = board
        for word in words:
            t = self.dict
            for w in word:
                if w not in t:
                    t[w] = {}
                t = t[w]
            t["end"] = 1
        for i in range(self.row):
            for j in range(self.col):
                self.dfs(i,j,self.dict,"")
        return self.res
    def dfs(self,i,j,trie,s):
        c = self.board[i][j]
        if c not in trie:
            return
        trie = trie[c]
        if "end" in trie and trie["end"] == 1:
            self.res.append(s+c)
            trie["end"] = 0
        self.board[i][j] = "#"
        for x,y in [[-1,0],[1,0],[0,1],[0,-1]]:
            temp_x = i + x
            temp_y = j + y
            if 0 <= temp_x <self.row and 0<= temp_y<self.col and self.board[temp_x][temp_y] != "#":
                self.dfs(temp_x,temp_y,trie,s+c)
        self.board[i][j] = c

位运算:

x&x-1  清零最低位的1 

用法:  求出此树有多少二进制位的1   有多少二进制位的0

如何用:不断用这个操作去清除最低位的1,直到这个数变成全0

-x就是取反加1  所以这个操作是得到最低位的1所在的位置

例题:

291.

class Solution:
    def hammingWeight(self, n: int) -> int:
        ans = 0
        while n != 0:
            n = n& n-1
            ans += 1
        return ans 

231:

class Solution:
    def isPowerOfTwo(self, n: int) -> bool:
        number = 0
        if n<0:
            return False
        while(n != 0):
            n = n&(n-1)
            number += 1
        if number ==1 :
            return True
        else:
            return False

简化之后:

class Solution:
    def isPowerOfTwo(self, n: int) -> bool:
        return n > 0 and n & (n - 1) == 0

n&(n-1)是打掉最后一位的1

应用场景:所有涉及二进制的运算,还有2的幂的题目都可以试试

338.

class Solution:
    def countBits(self, n: int) -> List[int]:
        res = []
        for i in range(n+1):
            num = 0
            while(i != 0):
                i = i & (i-1)
                num += 1 
            res.append(num)
        return res
  • 时间复杂度: O(N * sizeof(int))O(N∗sizeof(int))
  • 空间复杂度:O(1)O(1),返回数组不计入空间复杂度中

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值