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)的代码了。
不过这个代码跟力扣官方题解方法三的思路其实是一样的。
我是个编程爱好者,小白级别的,如果你跟我一样希望通过力扣刷题,学习各种奇妙的算法,可以关注我,大家一起学习。
夜雨聆风