乐于分享
好东西不私藏

TV版app:BBLL一年没更新了,大家可以试试blbl

TV版app:BBLL一年没更新了,大家可以试试blbl

楔子

大家好,我是张桃狮。

BBLL已经停更一年了,我还在用BBLL的修改版。

不过我发现BBLL修改版有几个缺点。

BBLL修改版只能选AVC编码,视频画面有些发白,无法选择画质更好的HEVC。

最近我看了很多B站长视频,比如罗永浩的十字路口,一个视频动辄几个小时。

可是我发现BBLL修改版播放这种长视频,最多一个多小时就会卡住。

这就很让人扫兴了。

另外还有一些其他小毛病,比如看直播的时候弹幕是乱的,其中有些弹幕明显跟视频无关。

为了解决这些问题,我去BBLL的github主页看了下。

结果发现BBLL已经停更一周年了,看来B站的律师函杀伤力还是很大的。

不过在Issues中,我看到有人推荐blbl。

点进去一看,作者是cat3399,这不就是BBLL修改版的作者吗。

https://github.com/cat3399/blbl

目前blbl这个项目的星标已经有1.5k,看来已经很不错了。

Releases里面最新的apk安装包是两个星期前发出来的,我下载下来安装到我的小米盒子4S MAX上面。

打开后,我发现界面几乎跟BBLL一模一样。

我把弹幕字体设置为40,弹幕屏幕范围设置为1/4。

这些都是我习惯的弹幕设置,大家可以按照自己的习惯调整。

视频编码选择HEVC,视频可以正常播放,我可太喜欢了。

至于播放长视频超过一定时间是否会断流,这个需要长时间使用才能发现。

喜欢在电视上看视频的朋友,赶快去试试吧。

为了方便大家下载,我把最新的apk文件保存在网盘里面,地址如下。

链接:https://pan.quark.cn/s/84dd9de730c1

闲话讲完,咱们继续力扣刷题学编程。

力扣338. 比特位计数

给你一个整数 n ,对于 0 <= i <= n 中的每个 i ,计算其二进制表示中 1 的个数 ,返回一个长度为 n + 1 的数组 ans 作为答案。

示例 1:

输入:n = 2

输出:[0,1,1]

解释:

0 –> 0

1 –> 1

2 –> 10

示例 2:

输入:n = 5

输出:[0,1,1,2,1,2]

解释:

0 –> 0

1 –> 1

2 –> 10

3 –> 11

4 –> 100

5 –> 101

提示:

0 <= n <= 

进阶:

很容易就能实现时间复杂度为 O(n log n) 的解决方案,你可以在线性时间复杂度 O(n) 内用一趟扫描解决此问题吗?

你能不使用任何内置函数解决此问题吗?(如,C++ 中的 __builtin_popcount )

我的思路

我只会用最简单的字符串和整数互相转换的方法做这道题。

方法一

class Solution:    def countBits(self, n: int) -> List[int]:        res=list()        for i in range(n+1):            res.append(sum([int(s) for s in bin(i)[2:]]))        return res

力扣提交通过,时间复杂度O(n log n),空间复杂度O(n)。

如果不用bin函数,也可以用求余数的方法做这道题。

方法二

class Solution:    def countBits(self, n: int) -> List[int]:        res=[0]        for i in range(1,n+1):            j=0            while i != 0:                j += i%2                i //= 2            res.append(j)        return res

力扣提交通过,时间复杂度O(n log n),空间复杂度O(n)。

我还是做不到时间复杂度O(1),先看官方题解吧。

力扣官方题解

方法一:Brian Kernighan 算法

class Solution:    def countBits(self, n: int) -> List[int]:        def countOnes(x: int) -> int:            ones = 0            while x > 0:                x &= (x - 1)                ones += 1            return ones        bits = [countOnes(i) for i in range(n + 1)]        return bits

力扣提交通过,时间复杂度O(n log n),空间复杂度O(n)。

x &= (x – 1)可以将x最右侧的1转为0,有多少个1就转多少次。

不过这个代码还是做不到时间复杂度O(n)。

方法二:动态规划——最高有效位

class Solution:    def countBits(self, n: int) -> List[int]:        bits = [0]        highBit = 0        for i in range(1, n + 1):            if i & (i - 1) == 0:                highBit = i            bits.append(bits[i - highBit] + 1)        return bits

力扣提交通过,时间复杂度O(n),空间复杂度O(n)。

i & (i – 1) 如果等于0,就说明i是2的幂。

这个代码相当于将i拆分为两部分的和,分别是2的幂和剩余部分。

比如6的二进制为110,可以把它拆分为4+2。

4的二进制数为100,2的二进制数为10。

100只有1个1,事实上所有2的幂都只有1个1,后面都是0。

所以只需要计算2中的1的个数再+1就可以了。

2=6-4,也就是代码中i – highBit。

i – highBit肯定小于i,1的数量可以再列表bits中查到。

现在只需要将每个数字的highBit用变量记录下来就好了。

方法三:动态规划——最低有效位

class Solution:    def countBits(self, n: int) -> List[int]:        bits = [0]        for i in range(1, n + 1):            bits.append(bits[i >> 1] + (i & 1))        return bits

力扣提交通过,时间复杂度O(n),空间复杂度O(n)。

我有点明白动态规划的意义了,就是将当前需要计算的数字变小并找到它们之间的关系,这样就可以计算出当前数字的结果了。

将i右移会将i的尾数舍弃。

对于二进制数来说,尾数要么是0,要么是1。

i & 1可以判断i的尾数是0还是1。

妙啊。

方法四:动态规划——最低设置位

class Solution:    def countBits(self, n: int) -> List[int]:        bits = [0]        for i in range(1, n + 1):            bits.append(bits[i & (i - 1)] + 1)        return bits

力扣提交通过,时间复杂度O(n),空间复杂度O(n)。

i & (i – 1)会将i最右侧的1转为0,而且这个数肯定小于i,可以在bits中查到。

查到后将这个数+1就是最终的结果了。

我喜欢这种简洁的代码。

尾声

看了这么多位运算,我忍不住也想试一下。

我对自己的方法二做了改造。

class Solution:    def countBits(self, n: int) -> List[int]:        res=[0]        for i in range(1,n+1):            j=0            while i > 0:                j += i & 1                i >>= 1            res.append(j)        return res

力扣提交通过,时间复杂度O(n log n),空间复杂度O(n)。

时间复杂度没什么变化,理论上计算速度会快一点。

我还想到另外一种解法,根据奇偶数来计算。

class Solution:    def countBits(self, n: int) -> List[int]:        res=[0]        for i in range(1,n+1):            if i & 1:                res.append(res[i-1]+1)            else:                res.append(res[i>>1])        return res

如果i是奇数,1的个数为res[i-1]+1;如果i是偶数,尾数必然是0,右移1位后肯定小于i,而且1的数量是相同的。

力扣提交通过,时间复杂度O(n),空间复杂度O(n)。

我终于想出时间复杂度为O(n)的代码了。

不过这个代码跟力扣官方题解方法三的思路其实是一样的。

我是个编程爱好者,小白级别的,如果你跟我一样希望通过力扣刷题,学习各种奇妙的算法,可以关注我,大家一起学习。