遇到两次的笔试题:求连续区间

开发 前端
最近除了准备华为面试外,也在面其他公司,每一轮面试都会有几道笔试题。这些笔试题里面难免有类型相似的。

[[432661]]

最近除了准备华为面试外,也在面其他公司,每一轮面试都会有几道笔试题。这些笔试题里面难免有类型相似的。

最近我就遇到两道类型相似的题,都是求连续区间的。

虽然不是啥算法题,但还是比较考验逻辑能力的,所以这篇文章来梳理一下。

下面是题目,大家可以看下有啥思路没,就当这是在面试了??。

第一道

输入是 1,2,3,5,7,8,10 输出要求是 1~3 5 7~8 10

第二道

将48位的时间位图格式化成字符串

要求:写一个函数timeBitmapToRanges,将下述规则描述的时间位图转换成一个选中时间区间的数组。

规则描述:

将一天24小时按每半小划分成48段,我们用一个位图表示选中的时间区间,例如110000000000000000000000000000000000000000000000, 表示第一个半小时和第二个半小时被选中了,其余时间段都没有被选中,也就是对应00:00~01:00这个时间区间。一个位图中可能有多个不连续的 时间区间被选中,例如110010000000000000000000000000000000000000000000,表示00:00-1:00和02:00-02:30这两个时间区间被选中了。

示例输入:"110010000000000000000000000000000000000000000000"

示例输出:["00:00~01:00", "02:00~02:30"]

第一道题的题解

输入是 1,2,3,5,7,8,10 输出要求是 1~3 5 7~8 10

这题明显是要求出连续区间来,然后格式化成字符串。

当 arr[i+1] 是 arr[i] + 1 的时候,那就是连续的,需要继续往下找。否则就到了区间的边界,记录下区间的起始位置就行。

我们循环一遍数组,把区间 push 到数组里

  1. function calcContinuousRanges(arr) { 
  2.     let continuousRanges = []; 
  3.     let index = 0; 
  4.     while(index < arr.length) { 
  5.         const range = { 
  6.             start: arr[index], 
  7.             end: arr[index
  8.         }; 
  9.         continuousRanges.push(range); 
  10.         index++; 
  11.     } 

但是,如果中间有连续的数字,那区间的 end 要做一下调整:

  1. function calcContinuousRanges(arr) { 
  2.     let continuousRanges = []; 
  3.     let index = 0; 
  4.     while( index < arr.length) { 
  5.         const range = { 
  6.             start: arr[index], 
  7.             end: arr[index
  8.         }; 
  9.         while (index < arr.length && arr[index + 1] === arr[index] + 1) { 
  10.             range.end = arr[index + 1]; 
  11.             index++; 
  12.         } 
  13.         continuousRanges.push(range); 
  14.         index++; 
  15.     } 
  16.     console.log(JSON.stringify(continuousRanges)); 

我们先打印一下 continuousRanges:

  1. calcContinuousRanges([1,2,3,5,7,8,10]); 

连续区间是对的:

之后做下格式化就行

  1. const formatted = continuousRanges.map(({start, end}) => { 
  2.     return start === end ? start : `${start}~${end}`; 
  3. }).join(' '); 

完整代码如下:

  1. function calcContinuousRanges(arr) { 
  2.     let continuousRanges = []; 
  3.     let index = 0; 
  4.     while( index < arr.length) { 
  5.         const range = { 
  6.             start: arr[index], 
  7.             end: arr[index
  8.         }; 
  9.         while (index < arr.length && arr[index + 1] === arr[index] + 1) { 
  10.             range.end = arr[index + 1]; 
  11.             index++; 
  12.         } 
  13.         continuousRanges.push(range); 
  14.         index++; 
  15.     } 
  16.     // console.log(JSON.stringify(continuousRanges)); 
  17.     const formatted = continuousRanges.map(({start, end}) => { 
  18.         return start === end ? start : `${start}~${end}`; 
  19.     }).join(' '); 
  20.     console.log(formatted); 
  21.  
  22. calcContinuousRanges([1,2,3,5,7,8,10]); 

小结

这道题的思路就是先求出连续区间,然后格式化输出。连续区间就是判断 arr[i+1] 和 arr[i] 的关系,如果连续就 index++ 继续往下找,直到找到区间的结束

第二道题的题解

将48位的时间位图格式化成字符串

要求:写一个函数timeBitmapToRanges,将下述规则描述的时间位图转换成一个选中时间区间的数组。

规则描述:

将一天24小时按每半小划分成48段,我们用一个位图表示选中的时间区间,例如110000000000000000000000000000000000000000000000, 表示第一个半小时和第二个半小时被选中了,其余时间段都没有被选中,也就是对应00:00~01:00这个时间区间。一个位图中可能有多个不连续的 时间区间被选中,例如110010000000000000000000000000000000000000000000,表示00:00-1:00和02:00-02:30这两个时间区间被选中了。

示例输入:"110010000000000000000000000000000000000000000000"

示例输出:["00:00~01:00", "02:00~02:30"]

这道题也是连续区间的题。先遍历一遍时间位图,找到所有的连续时间段的区间,然后格式化成时间的格式输出就行。

连续区间的话,如果当前位是 1 就记录下区间的开始,一直 index++ 找区间的结束,直到不为 1,就记录下一个连续区间。这样遍历完一遍就求出了所有连续区间。

格式化成时间的字符串找规律就行。

我们来写下代码。

先找连续区间,如果是 0 就 continue,如果是 1 就记录下区间的开始,然后找区间的结束,之后记录下连续区间:

  1. function timeBitmapToRanges(timeBitmap) { 
  2.     let index = 0; 
  3.     let ranges = []; 
  4.     while(index < timeBitmap.length) { 
  5.         if (timeBitmap[index] === '0') { 
  6.             index++; 
  7.             continue
  8.         } 
  9.         let curRange = { start: indexendindex}; 
  10.         while (timeBitmap[index] === '1') { 
  11.             curRange.end = index
  12.             index++; 
  13.         } 
  14.         ranges.push(curRange); 
  15.     } 

测试一下,连续区间是对的:

格式化部分找规律即可。

半小时为单位,所以要乘以 0.5,然后区间的结束要多加个 0.5

  1. ranges.map(range => { 
  2.     let str = 0; 
  3.     return format(range.start * 0.5) + '~' + format(range.end * 0.5 + 0.5); 
  4. }); 

然后格式化的实现分为小时和分钟两部分:

小时就是整数部分,个位数要补 0;

分钟是小数部分,只有 30 和 0 两种情况。

  1. function format(num) { 
  2.     const left = Math.floor(num); 
  3.     const leftStr =   left < 10 ? '0' + left : left
  4.     const right = num % 1 === 0.5 ? 30 : 0; 
  5.     const rightStr =   right < 10 ? '0' + right : right
  6.     return leftStr + ':' + rightStr; 

经测试,结果是对的:

完整代码如下:

  1. function timeBitmapToRanges(timeBitmap) { 
  2.     let index = 0; 
  3.     let ranges = []; 
  4.     while(index < timeBitmap.length) { 
  5.         if (timeBitmap[index] === '0') { 
  6.             index++; 
  7.             continue
  8.         } 
  9.         let curRange = { start: indexendindex}; 
  10.         while (timeBitmap[index] === '1') { 
  11.             curRange.end = index
  12.             index++; 
  13.         } 
  14.         ranges.push(curRange); 
  15.     } 
  16.  
  17.     return ranges.map(range => { 
  18.         let str = 0; 
  19.         return format(range.start * 0.5) + '~' + format(range.end * 0.5 + 0.5); 
  20.     }); 
  21.  
  22. function format(num) { 
  23.     const left = Math.floor(num); 
  24.     const leftStr =   left < 10 ? '0' + left : left
  25.     const right = num % 1 === 0.5 ? 30 : 0; 
  26.     const rightStr =   right < 10 ? '0' + right : right
  27.     return leftStr + ':' + rightStr; 
  28.  
  29. console.log(timeBitmapToRanges('110010000000000000000000000000000000000000000000')) 

小结

这道题也是求连续区间再格式化输出的思路,只是连续区间是通过当前位是否为 1 来判断的,而且格式化的方式也复杂一些。

总结

 

连续区间的题是我最近遇到两次的笔试题,虽然变形比较多,连续区间的判断和格式化的方式都不同,但思路是一致的,都是先求出连续区间,然后格式化输出。

 

责任编辑:武晓燕 来源: 神光的编程秘籍
相关推荐

2009-05-05 10:03:37

主考官求职笔试题

2021-10-21 11:29:06

勒索软件攻击数据泄露

2013-12-18 09:36:33

Fedora 20

2015-11-03 11:39:18

清华大学OpenStackEasyStack

2013-05-21 11:22:15

Google+UI设计

2023-02-08 15:32:16

云服务中断微软

2021-10-08 11:05:00

Go 切片内存

2020-07-21 10:22:28

网络安全黑客技术

2021-07-26 08:08:56

TCPIP网络协议

2021-04-30 13:32:17

TCP三次握手网络协议

2011-04-19 17:57:58

笔试题C++

2018-08-13 16:19:35

2021-05-13 16:34:20

TCP客户端

2018-07-04 13:36:53

程序员项目数据库

2010-09-25 15:42:26

数据库集群Facebook

2012-12-06 10:00:48

InnoDBMySQL

2012-07-04 15:33:11

亚马逊断网云计算

2018-06-20 22:13:30

IBM人工智能系统Project Deb

2019-12-03 14:55:52

摩根大通苹果iPhone
点赞
收藏

51CTO技术栈公众号