leetcode刷题笔记-bit & bitmask

本文解析了多个LeetCode算法题目,包括特殊排列、数组拆分、最长二进制子序列等,运用了动态规划、位操作等技术手段,提供了清晰的Python代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2741. Special Permutations

class Solution:
    # https://leetcode.com/problems/special-permutations/solutions/3650420/beginner-friendly-2-methods-similar-questions-bit-mask-visited-array/
    MOD = int(1e9) + 7

    def helper(self, nums, preIdx, curIdx, msk, dp):
        if curIdx == len(nums):
            #  Base case: If we have reached the end of the numbers, there is only one special permutation which is []
            return 1

        if dp[preIdx + 1][msk] != -1:
            return dp[preIdx + 1][msk]

        total = self.MOD
        for ind in range(len(nums)):
            if msk & (1 << ind): # 当前index已经被用过,被标记在mask里面了。 
                continue

            if preIdx == -1 or nums[ind] % nums[preIdx] == 0 or nums[preIdx] % nums[ind] == 0:
                total += self.helper(nums, ind, curIdx + 1, msk | (1 << ind), dp) % self.MOD
                total %= self.MOD

        dp[preIdx + 1][msk] = total
        return total

    def specialPerm(self, nums):
        # 二维数组, [-3] * x 每一纬度。 x = mask可能的最大值
        dp = [[-1] * ((1 << 14) + 7) for _ in range(21)]
        return self.helper(nums, -1, 0, 0, dp) % self.MOD

2871. Split Array Into Maximum Number of Subarrays

class Solution:
    def maxSubarrays(self, nums: List[int]) -> int:
        '''
        Because (x & y) <= x and (x & y) <= y,
        so the score(array) <= score(subarray).

        If the score of A is x,
        then the score of each subarray of A bigger or equal to x.

        If x > 0,
        2x > x,
        so we won't split A,
        return 1.

        If x == 0,
        so we may split A,
        into multiple subarray with score 0.

        So the real problem is,
        split A into as many subarray as possbile,
        with socre 0

        [0,8,0,0,0,23] 23 will & with pre 0
        '''
        re = 0
        total = -1  # all bits are 1
        for n in nums:
            total &= n
            if total == 0:
                re += 1
                total = -1

        return max(1, re)

2311. Longest Binary Subsequence Less Than or Equal to K

class Solution:
    def longestSubsequence(self, s: str, k: int) -> int:
        '''
        dp[i] means the minimum value of the subsequence with length i
        Time O(n^2)
        Space O(n)
        
        dp = [0]
        for v in map(int, s):  # 从头往后拿s的字母,并转为Int
            if dp[-1] * 2 + v <= k:  # 拿后面的数字,前面的进一位
                dp.append(dp[-1] * 2 + v)
            for i in range(len(dp) - 1, 0, -1):
                dp[i] = min(dp[i], dp[i - 1] * 2 + v)  #  不要i的那位,换成当前这个位置的数,即v
        return len(dp) - 1
        ''' 

        '''
        Greedy
        拿所有的0, 然后尽量的从右边拿1
        Time O(n)
        Space O(1)
        '''

        re = 0
        n = len(s)
        bit = 1  # 这一位如果是1代表的值

        for v in map(int, s[::-1]):  # 为了尽量从右边拿1, 这些1和0构成的数要小于k
            if (v == 0 or bit <= k):
                k -= bit * (v - 0)
                re += 1
            bit = bit << 1
        return re

1986. Minimum Number of Work Sessions to Finish the Tasks

class Solution:
    def minSessions(self, tasks: List[int], sessionTime: int) -> int:

        '''
Let dp(mask, remainTime) is the minimum of work sessions needed to finish all the tasks represent by mask (where ith bit = 0 means tasks[i] need to proceed) with the remainTime we have for the current session.
        '''

        '''
        # O(2^n * sessionTime * n)  mask 有2^n种情况, 每个worksession都要考虑2^n,因为DP是二维,每个dp里面要for loop N
        n = len(tasks)  # the number of tasks
        @lru_cache(None)
        def dp(mask, remainTime):
            if mask == (1 << n) - 1:  # all the tasks are marked as 1 (finished)
                return 0
            
            ans = sys.maxsize

            for i in range(n):  # check each task is done or not
                if mask & (1 << i) == 0:  # this task is not done
                    if tasks[i] <= remainTime:
                        ans = min(ans, dp(mask | (1<<i), remainTime-tasks[i]))
                    else:
                        ans = min(ans, 1 + dp(mask | (1<<i), sessionTime - tasks[i]))
            return ans
        return dp(0, 0)  # 第一维度,都是0表示tasks都没被处理, 第二纬0表示当前开的worksession 剩下时间是0,意味着要重新开一个worksession  

        '''

        # 改进 O(2^n * n) dp(mask) return (the minimum of work sessions needed, remainTime) 
        n = len(tasks)
        @lru_cache(None)
        def dp(mask):
            if mask == (1 << n) - 1:  # all the tasks are marked as 1 (finished)
                return 0, 0
            ans = sys.maxsize
            ansRemainTime = 0

            for i in range(n):
                if mask & (1 << i) == 0:
                    newMask = mask | (1<<i)
                    cnt, remainTime = dp(newMask)

                    if tasks[i] <= remainTime:
                        remainTime = remainTime - tasks[i]
                    else:  # neet to create a new session
                        cnt += 1 
                        remainTime = sessionTime - tasks[i]
                    if cnt < ans or cnt == ans and remainTime > ansRemainTime:
                        ans = cnt
                        ansRemainTime = remainTime
            return ans, ansRemainTime
        
        return dp(0)[0]

338. Counting Bits

class Solution(object):
    def countBits(self, num):
        dp = [0] * (num+1)
        for i in xrange(num+1):
            dp[i] = dp[i/2] + i%2
        return dp

260. Single Number III

class Solution(object):
    def singleNumber(self, nums):
        xor = n1 = n2 = 0
        # find n1 xor n2
        for n in nums:
            xor ^= n  
# if a bit in xor is 1, means n1, n2 in this bit is different
# Thus, all the numbers can be partitioned into two groups according to their bits at location i.
# the first group consists of all numbers whose bits at i is 0.
# the second group consists of all numbers whose bits at i is 1.
        bit = 1
        while bit & xor == 0:
            bit = bit << 1 # 位移1bit
        
        for n in nums:
            if n & bit:
                n1 ^= n
            else:
                n2 ^= n
        return [n1, n2]

137. Single Number II

class Solution(object):
    def singleNumber(self, nums):
        ones = twos = 0
        for n in nums:
            ones = ones^n & ~twos
            twos = twos^n & ~ones
        return ones|twos

477. Total Hamming Distance

class Solution(object):
    def totalHammingDistance(self, nums):
        bits = [[0,0] for _ in xrange(32)]
        for n in nums:
            for i in xrange(32):
                bits[i][n%2] += 1
                n /= 2
        return sum(x*y for x,y in bits)

136. Single Number

这题关键是最多的也只重复2次。

class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        res = nums[0]
        for i in xrange(1, len(nums)):
            res ^= nums[i]

        return res

 return sum(set(nums))*2 - sum(nums)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值