2021-12-30:分裂问题。 一个数n,可以分裂成一个数组[n/2, n%2, n/2], 这个数组中哪个数不是1或者0,就继续分裂下去。 比如 n = 5,一开始分裂成[2, 1, 2], [2

Posted 福大大架构师每日一题

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-12-30:分裂问题。 一个数n,可以分裂成一个数组[n/2, n%2, n/2], 这个数组中哪个数不是1或者0,就继续分裂下去。 比如 n = 5,一开始分裂成[2, 1, 2], [2相关的知识,希望对你有一定的参考价值。

2021-12-30:分裂问题。
一个数n,可以分裂成一个数组[n/2, n%2, n/2],
这个数组中哪个数不是1或者0,就继续分裂下去。
比如 n = 5,一开始分裂成[2, 1, 2],
[2, 1, 2]这个数组中不是1或者0的数,会继续分裂下去,比如两个2就继续分裂,
[2, 1, 2] -> [1, 0, 1, 1, 1, 0, 1],
那么我们说,5最后分裂成[1, 0, 1, 1, 1, 0, 1]。
每一个数都可以这么分裂,在最终分裂的数组中,假设下标从1开始,
给定三个数n、l、r,返回n的最终分裂数组里[l,r]范围上有几个1。
n <= 2 ^ 50,n是long类型,
r - l <= 50000,l和r是int类型。
我们的课加个码:
n是long类型随意多大都行,
l和r也是long类型随意多大都行,但要保证l<=r。
来自腾讯。

答案2021-12-31:

每次裂变都放到map中。
时间复杂度:O(logN)。
空间复杂度:O(logN)。

代码用golang编写。代码如下:

package main

import "fmt"

func main() 
    ret := nums2(5, 4, 7)
    fmt.Println(ret)


func nums2(n, l, r int) int 
    allMap := make(map[int]int)
    return dp(n, l, r, allMap)


func size(n int) int 
    if n == 1 || n == 0 
        return 1
     else 
        half := size(n / 2)
        return (half << 1) + 1
    


func dp(n, l, r int, allMap map[int]int) int 
    if n == 1 || n == 0 
        return twoSelectOne(n == 1, 1, 0)
    
    half := size(n / 2)
    all := (half << 1) + 1
    mid := n & 1
    if l == 1 && r >= all 
        if _, ok := allMap[n]; ok 
            return allMap[n]
         else 
            count := dp(n/2, 1, half, allMap)
            ans := (count << 1) + mid
            allMap[n] = ans
            return ans
        
     else 
        mid = twoSelectOne((l > half+1 || r < half+1), 0, mid)
        left := twoSelectOne(l > half, 0, dp(n/2, l, getMin(half, r), allMap))
        right := twoSelectOne(r > half+1, dp(n/2, getMax(l-half-1, 1), r-half-1, allMap), 0)
        return left + mid + right
    


func twoSelectOne(c bool, a, b int) int 
    if c 
        return a
     else 
        return b
    


func getMax(a, b int) int 
    if a > b 
        return a
     else 
        return b
    


func getMin(a, b int) int 
    if a < b 
        return a
     else 
        return b
    

执行结果如下:


左神java代码

以上是关于2021-12-30:分裂问题。 一个数n,可以分裂成一个数组[n/2, n%2, n/2], 这个数组中哪个数不是1或者0,就继续分裂下去。 比如 n = 5,一开始分裂成[2, 1, 2], [2的主要内容,如果未能解决你的问题,请参考以下文章

[NOIP2009普及组]细胞分裂

bzoj2064: 分裂(集合DP)

CCCC 红色警报

L2-013. 红色警报

史莱姆自爆问题

bzoj2064分裂(dp)