Leetcode 2021-11-23

201. Bitwise AND of Numbers Range (Medium)

Given two integers left and right that represent the range [left, right], return the bitwise AND of all numbers in this range, inclusive.

class Solution:
    def rangeBitwiseAnd(self, left: int, right: int) -> int:
        if left==right: return left
        res = 0
        for pos in range(32):
            res |= 1 << pos
            for n in range(left,right+1):
                if (n & 1<<pos) >> pos ==0:
                    res ^= 1 << pos
                    break
        return res

#answer way of writing
class Solution:
    def rangeBitwiseAnd(self, m: int, n: int) -> int:
        shift = 0   
        # find the common 1-bits
        while m < n:
            m = m >> 1
            n = n >> 1
            shift += 1
        return m << shift
#
class Solution:
    def rangeBitwiseAnd(self, m: int, n: int) -> int:
        while m < n:
            # turn off rightmost 1-bit
            n = n & (n - 1)
        return m & n

初次尝试,time limit exceeded, 32位过一次,一旦发现在pos位上为0,就break。 还是速度慢, after the AND operation on all the numbers, the remaining part of bit strings is the common prefix of all these bit strings.As a result, we then can reformulate the problem as "given two integer numbers, we are asked to find the common prefix of their binary strings." 思路: shift 直到m n相等,然后再 shift back。 这样就找到了common prefix。另一解法,思路:关闭右侧最后是1的位,然后和左侧求&。

When we do AND bit operation between number and number-1, the rightmost bit of one in the original number would be turned off (from one to zero).

202. Happy Number (Easy)

Write an algorithm to determine if a number n is happy.
Input: n = 19
Output: true
Explanation:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1

class Solution:
    def isHappy(self, n: int) -> bool:
        visited =set()
        
        while n!=1:
            if n in visited: return False
            visited.add(n)
            new_n =0
            while n:
                lastdig = n%10
                new_n += lastdig*lastdig
                n //= 10
            n=new_n
        
        return True
#MY ANSWER
class Solution:
    def isHappy(self, n: int) -> bool:
        s =set()
        def helper(n):
            if n==1: return True
            res = 0
            while n:
                lastdig = n%10
                n = n//10
                res+=lastdig**2
            if res in s:return False
            s.add(res)
            return helper(res)
        return helper(n)

203. Remove Linked List Elements (Easy)

Given the head of a linked list and an integer val, remove all the nodes of the linked list that has Node.val == val, and return the new head.

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
        if not head: return head
        dummyhead = ListNode(val='NULL',next=head)
        cur=dummyhead
        while cur and cur.next:
            while cur.next and cur.next.val==val:
                cur.next=cur.next.next
            cur=cur.next
        return dummyhead.next

204. Count Primes (Medium)

class Solution:
    def countPrimes(self, n: int) -> int:
 
        if n <=2:
            return 0
        primes = [True] * n
        primes[0] = primes[1] = False
        for i in range(2, int(n ** 0.5) + 1):
            if primes[i]:
                primes[i * i: n: i] = [False] * len(primes[i * i: n: i])
        #如果i是pime 比如i=2  那么 i的倍数肯定不是prime 从i**2 开始。 
        return sum(primes)

直接用判断是否位质数方法会time limit exceeded。 思路:如果i是pime 比如i=2 那么 i的倍数肯定不是prime 从i**2 开始。

     def isP(num):
            for i in range(2,num//2+1):
                if num%i==0:
                    return False
            return True

205. Isomorphic Strings (Easy)

Given two strings s and t, determine if they are isomorphic.
Two strings s and t are isomorphic if the characters in s can be replaced to get t.

class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        if len(s)!=len(t): return False
        l=len(s)
        dic1 = dict()
        dic2 = dict()
        for i in range(l):
            a = s[i]
            b = t[i]
            if a in dic1:
                if dic1[a]!=b:
                    return False
            if b in dic2:
                if dic2[b]!=a:
                    return False
            dic1[a] = b
            dic2[b] = a
        return True

206. Reverse Linked List (Easy)

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        pre = None
        while head:
            headnext=head.next
            head.next = pre
            pre = head
            head=headnext
        return pre

207. Course Schedule (Medium)

class Solution:
    class Node:
        def __init__(self,val=None):
            self.val = val
            self.nei = []
            self.ind = 0 #indegree
            self.status = -1  # -1 not visited, 0 visiting, 1 visited
    
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        #  DAG 判断
        #
        # 建立graph
        nodes = [self.Node(val=i) for i in range(numCourses)]
        for row in prerequisites:
            a,b =  row
            nodes[b].nei.append(nodes[a])
            nodes[a].ind+=1
        
        #DFS 法    
        def dfs(node):
            # return True 无环 False 有环
            node.status=0
            for nei in node.nei:
                if nei.status==-1:
                    if not dfs(nei):
                        return False
                elif nei.status == 0:
                    return False
            
            node.status=1
            return True
        
        for node in nodes:
            if node.status==-1:
                if not dfs(node):
                    return False
        
        return True

# upper DFS lower BFS
class Solution:
    class Node:
        def __init__(self,val=None):
            self.val = val
            self.nei = []
            self.ind = 0 #indegree
            self.status = -1  # -1 not visited, 0 visiting, 1 visited
    
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        #  DAG 判断
        #
        # 建立graph
        nodes = [self.Node(val=i) for i in range(numCourses)]
        for row in prerequisites:
            a,b =  row
            nodes[b].nei.append(nodes[a])
            nodes[a].ind+=1
        
        #bfs 法
        queue=[]
        cnt=0
        for node in nodes:
            if node.ind==0:
                queue.append(node)
        while queue:
            v=queue.pop(0)
            cnt+=1
            for nei in v.nei:
                nei.ind-=1
                if nei.ind==0:
                    queue.append(nei)
        
        return cnt==numCourses

#MY ANSWER 
class Solution:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        indegree = {i:0 for i in range(numCourses)}
        b2a = collections.defaultdict(set)
        # a<-b
        # c<-d

        #   a<-b
        #   \|  |\
        #    c->d

        for row in prerequisites:
            a,b = row
            b2a[b].add(a)
            indegree[a]+=1
        
        queue = []
        tobedel = set()
        for key in indegree:
            if indegree[key] == 0:
                queue.append(key)
                tobedel.add(key)
        
        for key in tobedel:
            del indegree[key]
        

        while queue:
            for _ in range(len(queue)):
                b = queue.pop(0)
                #need b->a map
                for a in b2a[b]:
                    indegree[a]-=1
                    if indegree[a] == 0:
                        queue.append(a)
                        del indegree[a]
        

        return not indegree


感觉是图的算法,判断是否为DAG。BFS找入度为0的。 DFS时候,如果正在搜索某V,但又回到了V。证明有环路。注意需要3个状态来表示node状态, 【visited,visiting,not visited】
需要补充拓扑排序算法解决变种题。

# TopoSort sudo
queue = []
for 图中每个顶点V:
    if indegree(V)==0:
        queue.append(V)
while queue:
    V=queue.pop(0)
    输出V,记录V的输出序号cnt++
    for V的每个邻居 W:
        indegree(W) -= 1
        if indegree(W)==0:
            queue.append(W)

if cnt!=|V|:
    ERROR(图中有回路)

208. Implement Trie (Prefix Tree)

class Trie:

    def __init__(self):
        self.next= dict()
        self.isword=False
 

    def insert(self, word: str) -> None:
        if word:
            char = word[0]
            rest = word[1:]
            if char not in self.next:
                self.next[char] = Trie()
            self.next[char].insert(rest)
        else:
            self.isword=True
             

    def search(self, word: str) -> bool:
       
        if not word:
            return self.isword
        
        char = word[0]
        rest = word[1:]
        if char in self.next:
            if not self.next[char].search(rest):
                return False
        else:
            return False
        return True
        

    def startsWith(self, prefix: str) -> bool:
        if not prefix:
            return True
        
        char=prefix[0]
        rest=prefix[1:]
        if char in self.next:
            if not self.next[char].startsWith(rest):
                return False
        else:
            return False
        
        return True

#MY ANSWER
class Trie:

    def __init__(self):
        self.data = collections.defaultdict(Trie)
        self.isword = False

    def insert(self, word: str) -> None:
        if not word: 
            self.isword = True
            return
        head=word[0]
        rest = word[1:]
        if head not in self.data:
            self.data[head] = Trie()
        self.data[head].insert(rest)

    def search(self, word: str) -> bool:
        if not word:
            if self.isword: 
                 return True
            else:
                return False
        head = word[0]
        rest = word[1:]
        if head not in self.data: return False
        return self.data[head].search(rest)
        

    def startsWith(self, prefix: str) -> bool:
        if not prefix: return True
        head = prefix[0]
        rest = prefix[1:]
        if head not in self.data: return False
        return self.data[head].startsWith(rest)
        

209. Minimum Size Subarray Sum (Medium)

# answer way of writting
class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        # two pointer
 
        l=len(nums)
        res=float('inf')
        left=0
        sum_=0
        for i,n in enumerate(nums):
            sum_+=n
            while sum_>=target:
                res=min(res,i-left+1)
                sum_-=nums[left]
                left+=1
        
        return res if res!= float('inf') else 0
                

果然是two pointer, 学习answer写法,很清晰。

210. Course Schedule II (Medium)

class Solution:
    class Node:
        def __init__(self,val=None):
            self.val=val
            self.nei = []
            self.indegree = 0
    def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:
        # dag
        
        nodes = [self.Node(val=i) for i in range(numCourses)]
        for a,b in prerequisites:
            nodes[b].nei.append(nodes[a])
            nodes[a].indegree+=1
        
        queue = []
        for node in nodes:
            if node.indegree==0:
                queue.append(node)
                
        res = []
        while queue:
            cur=queue.pop(0)
            res.append(cur.val)
            for w in cur.nei:
                w.indegree-=1
                if w.indegree==0:
                    queue.append(w)
        
        return res if len(res)==numCourses else []

###
class Solution:
    def findOrder(self, numCourses: int, prerequisites: List[List[int]]) -> List[int]:

        indegree = {i:0 for i in range(numCourses)}
        b2a = collections.defaultdict(set)
        queue = deque()

        for row in prerequisites:
            a,b = row
            # a<-b
            indegree[a]+=1
            b2a[b].add(a)
        
        res = []
        
        tobedel= []
        for key in indegree:
            if indegree[key]==0:
                res.append(key)
                tobedel.append(key)
                queue.append(key)
        
        for key in tobedel:
            del indegree[key]


        while queue:

            for _ in range(len(queue)):
                b = queue.popleft()
                for a in b2a[b]:
                    indegree[a]-=1
                    if indegree[a]==0:
                        del indegree[a]
                        queue.append(a)
                        res.append(a)
        
        return res if not indegree else []
        

BFS 拓扑排序,找出indegree==0的node output。