c++如何判断是否是可见字符_LeetCode基础算法题第101篇:判断末尾字符是否是1比特字符...

技术提高是一个循序渐进的过程,所以我讲的leetcode算法题从最简单的level开始写的,然后到中级难度,最后到hard难度全部完。

目前我选择C语言,Python和Java作为实现语言,因为这三种语言还是比较典型的。由于篇幅和精力有限,其他语言的实现有兴趣的朋友请自己尝试。

初级难度说的差不多的时候,我打算再加点其他内容,我可能会从操作系统到协议栈,从分布式聊到大数据框架,从大数据聊到人工智能,... ...。

如果有任何问题可以在文章后评论或者私信给我

我会持续分享下去,敬请您的关注。

LeetCode 717. 1比特与2比特字符(1-bit and 2-bit Characters)

问题描述:

有两种特殊字符。第一种字符可以用一比特0来表示。第二种字符可以用两比特(10 或 11)来表示。

现给一个由若干比特组成的字符串。问最后一个字符是否必定为一个一比特字符。给定的字符串总是由0结束。

注:

  1. 1 <= len(bits) <= 1000.
  2. bits[i] 总是0 或 1.

示例:

abd9292553e457f93dfc9cfc5d12ade1.png
4b33a91c037394c61dfe29f25d3c4996.png

C语言实现:

这道题的解法很多,我只列出两个比较简洁的实现方式,性能可能不是最好,但是足够简单。时间复杂度都是O(n)。

第一种方法:

我们看2比特字符的定义,它的起始比特一定是1,而第二个比特是任意的,所以我们很容易得出结论,如果我从数组的起始位置开始遍历:

  1. 如果遇到元素1,那么它后面的一个元素一定会和结合成一个2比特字符,
  2. 如果遇到0,那么它一定被作为一个1比特字符;
  3. 如果遍历结束末尾的0被结合了,那么就应该返回false,否则返回true。

所以我们可以画出如下的步骤图:

9489f0b3e9ebc42613e07a9f79551e1d.png

原理很简单,代码也同样简单。我们判断末尾0是否被结合,是通过遍历后i的结果来判断的。

eb79725ab9067065d7f3e27edecfba55.png

第二种方法:

一般我不会给多个算法的源代码,大部分时候仅仅是提供一些思路,今天我会给出的第二种算法会附带源码,因为这种方法也足够简单,可以满足篇幅的要求。

cf870b5e2f38504e7c871deaaa4cffa1.png

如上图红色标记的0是除去末尾的0元素外,数组的最后一个0元素,这个0元素很关键,我们给它起个名字叫Z,通过观察你会发现:

如果Z前面也是0,那么Z作为一个1比特字符存在;

如果Z前面是1,那么有两种情况:

  1. 和1组成10,变成一个2比特字符;
  2. 如果前面的1和还有1,且结合成了11,那么Z将作为1比特字符存在;

综上所述,无论如何,Z都和它后面的元素无关,也就是说它的左边和结果无关,影响结果的只在右边

此外,因为它是除末尾0元素外的最后一个0元素,也就是说,它后面到末尾0元素间的所有元素都是1,或者不存在任何1元素,所以我们可以得出如图所示的结论:

  1. 当Z到末尾0之间有奇数个1,则,结果返回false,因为最后一个1会和末尾0结合成一个2比特字符。
  2. 当Z到末尾0之间有偶数个1,则,结果返回true,因为最后一个1不会和末尾0结合成一个2比特字符。
cd3cff4cb3dbdbf24665d0a1d8716855.png

这个算法的问题是,在一种极端情况下表现可能会不如第一种算法,这种情况就是,Z到末尾0元素间的连续1元素个数特别多,大于数组长度的一半以上。

两种算法在LeetCode上提交,跑出的结果差不多。

611a7d82ef655d57b7954d7f6f88a661.png

python语言的实现:

python的实现用的是上面说描述的第二种算法。

虽然在LeetCode上提交这两种实现表现差不多,但是经过我的评测,第二种算法效率要比第一种算法好很多,第二种算法的的问题是输入数组长度很大时,它的两次切片操作消耗很大,是唯一的瓶颈。

代码如下:

7db285d99004ea72a3df011dab012634.png
87e77de0d4862ea97cddcf1c23fccfc0.png

Java语言的实现:

Java 的实现用的是上面描述的第一种算法。

代码如下:

4895cb6a2fc702380fbfa1cc679af5a2.png
c4beb172ac93693f62652fe929ae32d5.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值