一些有意思的逻辑算法 --- (不定时更新)

前言

PS: 2018/04/30 新增多个数组玩法
PS: 2018/05/07 新增四, 应用函数系列, 防抖函数,节流函数
PS: 2019/03/04 新增CSS3实现进度条

一,逻辑系列

1、有36辆自动赛车和6条跑道,没有计时器的前提下,最少用几次比赛可以筛选出最快的三辆赛车?(来自腾讯面试题记腾讯一次糟糕的笔试面试经历)

第一步最基本的:分成6组ABCDEF分别比赛决出名次;(6次了)
这一下可以干掉每组后三名,一下刷掉一半参赛赛车了36/2=18

第二部顺势的:各组头名比赛决出名次(7次了)
这一下把后三名所在组干掉18-3*3=9,
假设按组别名次命名,可知A1>B1>C1,所以毫无悬念的排除掉第一的A1跟不可能前三的C2,C3,9-3=6,
其实还有B3也不可能的,不过反正不超过六位,只要加多一次就够了(8次)

2、一面墙,单独工作时,A花18小时砌好,B花24小时,C花30小时,现A, B, C的顺序轮流砌,每人工作1小时换班,完工时,B总共干了多少小时?(来自腾讯面试题记腾讯一次糟糕的笔试面试经历)

第一步:计算每人工作效率,a = 1/18,b = 1/24, c = 1/30;
第二步:模拟整数值,假设工作量n = 360, abc每小时工作效率分别为20,15,12;
第三部:写个遍历

var n = 360,
  a = 20,
  b = 15,
  c = 12;

for (var i = 0; i < n; i++) {
  if (n - (a + b + c) * i < 0) {
    console.log(i);
    break;
  }
}

所以每人7个小时之后还剩360-47*7=31.根据效率可以知道(31-20)/15 = 0.733...

(当时我就走到这步,然后开始有点偏了,根据题主的答案说A, B, C的顺序轮流砌,但没规定谁第一个.....o(≧口≦)o!我就蒙了,还玩阅读理解了????)
如果按这逻辑的话:
a先上:结果就上面说的那样0.733...,
b先上:满8个小时,
c先上:轮不到b了,7个小时

二,算法系列

1、不借助临时变量,进行两个整数的交换

这个真的有点蒙,绕得我晕,直接上答案

function swap(a, b) {
  b = b - a;
  a = a + b;
  b = a - b;
  console.log(a, b);
}
swap(10, 20);

不懂就笨方法列出来呗
b = b - a,
a = a + b - a,
b = a + b - a - b + a.
这么一看就清晰了,膜拜这答案.

极致浓缩写法:

function swap(a, b) {
  a = [b, (b = a)][0];
  console.log(a, b);
}
swap(10, 20);

2、判断一个单词是否是回文?(回文是指把相同的词汇或句子,在下文中调换位置或颠倒过来,产生首尾回环的情趣,叫做回文,也叫回环。)

其实一般的算法都是考察你对字符串,数组等方法使用技巧跟思路.例如这里我就先想到数组的reverse()倒序,需要通过类型转换作比较;

function checkPalindrom(str) {
    console.log(str == str.split('').reverse().join(''))
}
checkPalindrom('德韦恩韦德');
checkPalindrom('德维恩韦德');

3、去掉一组整型数组重复的值,统计一个字符串出现最多的字母,统计一组整型数组最大分差,排序算法等;

这些思路都大同小异,详情可以参考我之前写的文章js实现数组去重方法及效率对比
基本功能都实现了,例如查询分差那些无非就多加个math.max()方法而已

后面看到统计字符串有个更加高逼格的写法,附上

function statistics(str) {
  var obj = str
    .split('')
    .reduce(
      (previousValue, currentValue) => (
        previousValue[currentValue]++ || (previousValue[currentValue] = 1),
        previousValue
      ),
      {}
    );

  console.log(obj);
}
statistics('abcdaabc164984616464646464AAWEGAWGAG');

最短的代码实现数组去重,Es6的东西

[...new Set([1, "1", 2, 1, 1, 3])]

4、随机生成指定长度的字符串

先把0-9[a-z]全部列出来;然后通过Math.random()随机选择范围.遍历入参数次就成了

function randomString(n) {
  var str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
    tmp = '',
    i = 0,
    l = str.length;

  for (; i < n; i++) {
    tmp += str.charAt(Math.floor(Math.random() * l));
  }
  console.log(tmp);
}
randomString(20);

后来发现有更牛逼的写法如下:

console.log(Math.random().toString(16).substring(2))//14位
console.log(Math.random().toString(36).substring(2))//11位

实际就是返回以指定进制表示的字符串

5、单行写一个评级组件

特殊字符自己想办法搞吧,我是用输出法表情弄出来的,至于数量自行调整

function evaluate(n) {
  console.log('★★★★★☆☆☆☆☆'.slice(5 - n, 10 - n));
}
evaluate(3);

6、多维数组转一维数组

缺点就是储存的值变成字符串形式了

var ary = [[1, 5], [11, 17], [21, 22, 27, 29, 30]];

function changeAry(ary) {
  return ary.join(',').split(',');
}

console.log(changeAry(ary));

7、找出一串数组中的最大最小值,包括多维数组

第一步先确保转换成一维数组
第二步再找出其中最大最小值

function findMinAndMax(items) {
  items.join(',').split(',');
  return {
    min: Math.min.apply(null, items),
    max: Math.max.apply(null, items),
  };
}
console.log(findMinAndMax([995, 350, 796, 297, 686, 900, 10, 795, 53, 359]));

8、一次过十万个包含重复特殊字符的数据(个人遇到的面试题)

1, 惯例最糟糕的遍历字符串生成插入;
2, 我当时想到的ES6新方法fill(),一种写法两种思路,注意的是第一种写法是连接字符串,生成的字符串数量是数组长度-1;

console.log(new Array(10).fill().join('<=>'))
console.log(new Array(10).fill('<=>').join(''))

3, 后面找到的一种方法,其实也是一个思路,但是兼容性好

console.log(new Array(10).join('<=>'))

9、实现一个替换字符串内的变量的模板

var str = 'Hello ${name},you are so ${praise}',
  obj = {
    name: '高圆圆',
    praise: 'goodly',
  };

console.log(
  str.replace(/\$\{([^{}]+)\}/g, function(match, key) {
    return obj[key];
  })
);

10、数组内随机抽取?范围抽取?

var ary = [123, 512, 515, 125, 123, 124, 125, 151];
console.log(ary[Math.floor(Math.random() * ary.length)]);
// 随机公式
console.log(ary[Math.floor(Math.random() * (max - min +1)) + min]);

11、数组乱序排列?

var ary = [123, 512, 515, 125, 123, 124, 125, 151];
console.log(ary.sort(() => Math.random() - 0.5));

12、正则实现trim()效果?

console.log(' fwf 124 14fq fq f '.replace(/^\s+|\s+$/g,''));

12、一步清空数组(不能替换)?

var ary = [123, 512, 515, 125, 123, 124, 125, 151];
ary.length = 0;
console.log(ary);

也可以用这方法来截取数组.

13、删除数组对象成员?

如果是删除数组成员,delete只是把该位置成员设置成undefined,想彻底删除应该使用splice();
如果是对象会彻底删除该属性;

var ary = [123, 512, 515, 125, 123, 124, 125, 151];
obj = {
  a: 1,
};
delete ary[0];
ary.splice(1, 1);
delete obj.a;
console.log(ary, obj);

14、123.321保留两位小数加上1.2345结果?

console.log(123.321.toFixed(2) +1.2345);
console.log(Math.floor(+123.321.toFixed(2) +1.2345));

关键点几个:

  1. toFixed()返回的是字符串;
  2. 简单点说,计算机是用二进制计算,有时候因浮点数小数位的限制而截断的二进制数字再转换成十进制会出现精度误差;

三,新奇系列

1、类迷宫图形




  
    
    无标题文档
    
  

  
  

这个看起来复杂,实际代码量很少很简单,然后你写起来发现还是好些坑的.

  • 图形不能使用键盘里的''和'/',因为转义,输出不了,就算加多个反斜杠,因为角度问题,拼合起来的图形不好看.所以我还是通过输入法的符号使用
  • 各浏览器解析不同,字符串的行距不同

所以我不知道你们看到怎样子,起码我现在看起来长这样子

四, 应用函数系列

1、不使用数组方法的情况下实现该效果(个人遇到的面试题)

function List() {
  this.length = 0;
}

var list = new List();
list.push(1);
console.log(list[0]); //1

当时想法就是内部用一个对象模拟数组方法

function List() {
  this.length = 0;
  this._obj = {};
}
List.prototype.push = function(val) {
  this._obj[this.length] = val;
  this.length++;
};

var list = new List();
list.push(1);
console.log(list);

但是不行,因为中间还隔着一层_obj属性,不过思路应该可以的,再进一步就不要对象直接保存在this上.

function List() {
  this.length = 0;
}
List.prototype.push = function(val) {
  this[this.length] = val;
  this.length++;
};

var list = new List();
list.push(1);
console.log(list[0]); //1

效果达到了,不过如果有更好的写法欢迎说出来.

2、数字格式化(三位数加逗号)

var num = 0123456789.32;
/**
 * [利用slice切割数字组合]
 * @param  {[type]} param [字符串数字或数字]
 * @return {[type]}       [格式字符串]
 */
function numberFormat(param) {
  //简单过滤无效入参,非字符串数字或数字入参
  if (
    !param ||
    (Array.prototype.toString.call(param) !== '[object String]' &&
      /^\d*$/g.test(param)) ||
    Array.prototype.toString.call(param) !== '[object Number]'
  )
    return param;

  //转成字符串,切割整数小数
  var ary = (param + '').split('.'),
    int = ary[0],
    result = '';

  //每次判断整数长度>3动态添加逗号加入result,同时整数截掉对应数字
  while (int.length > 3) {
    result = ',' + int.slice(-3) + result;
    int = int.slice(0, int.length - 3);
  }
  //这里计算可以避免int以0开头
  return int + result + (ary[1] ? '.' + ary[1] : '');
}
console.log(numberFormat(num));
var num = 0123456789.32;
/**
 * [利用数组切割数字组合再合并]
 * @param  {[type]} param [字符串数字或数字]
 * @return {[type]}       [格式字符串]
 */
function numberFormat(param) {
  //简单过滤无效入参,非字符串数字或数字入参
  if (
    !param ||
    (Array.prototype.toString.call(param) !== '[object String]' &&
      /^\d*$/g.test(param)) ||
    Array.prototype.toString.call(param) !== '[object Number]'
  )
    return param;

  //转成字符串,切割整数小数
  var ary = (param + '').split('.'),
    int = ary[0],
    result = [],
    i = int.length - 1,
    //结果长度
    count = 0;

  //每次判断结果长度整被3整除并且整数长度不等于零情况先加逗号,否则直接添加到头部
  for (; i >= 0; i--) {
    count++;
    result.unshift((count % 3 === 0 && i !== 0 ? ',' : '') + int[i]);
  }
  //这里计算可以避免int以0开头
  return result.join('') + (ary[1] ? '.' + ary[1] : '');
}
console.log(numberFormat(num));
var num = 0123456789.32;
/**
 * [前置补零直接加逗号再替换掉]
 * @param  {[type]} param [字符串数字或数字]
 * @return {[type]}       [格式字符串]
 */
function numberFormat(param) {
  //简单过滤无效入参,非字符串数字或数字入参
  if (
    !param ||
    (Array.prototype.toString.call(param) !== '[object String]' &&
      /^\d*$/g.test(param)) ||
    Array.prototype.toString.call(param) !== '[object Number]'
  )
    return param;

  //转成字符串,切割整数小数
  var ary = (param + '').split('.'),
    //需要补几个零
    len = Math.ceil(ary[0].length / 3) * 3 - ary[0].length + 1,
    //不能被3整除补零
    int = Array(len).join(0) + ary[0],
    //提取出3位一组数据再合并并且替换前置0或逗号
    result = int
      .match(/\d{3}/g)
      .join(',')
      .replace(/^[0,]+/g, '');

  //这里计算可以避免int以0开头
  return result + (ary[1] ? '.' + ary[1] : '');
}
console.log(numberFormat(num));

3, 防抖函数

主要代码参数过程注释都能看到了,只是个人思路写法.

/**
 * 防抖函数就是在一定时间内,再次触发函数就会清除定时器重新设置延迟时间执行,适用于非高频率操作。
 * @param  {Function} fn                [执行函数]
 * @param  {Number}   [interval=1000]       [间隔时间]
 * @param  {Boolean}  [immediate=false] [是否立即执行]
 * @return {[type]}                     [function]
 */
function debounce(fn, interval = 1000, immediate = false) {
  //定时器
  let timer;
  return function() {
    const self = this,
      //保存参数
      args = arguments;
    if (timer) clearTimeout(timer);
    //是否立即执行
    if (immediate) {
      fn.apply(self, args);
      immediate = false;
    }
    timer = setTimeout(() => {
      fn.apply(self, args);
    }, interval);
  };
}

下面是执行实例,要注意的是[color=#ff4753]如果页面初始化的时候滚动条高度不为零(例如滑动之后刷新页面),也会自动触发一次监听事件.




  
    
    
  

  
    
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124

4, 节流函数

/**
 * 节流函数就是只允许一个函数在一定时间内执行一次,适用于高频率事件。
 * @param  {Function} fn                [执行函数]
 * @param  {Number}   [interval=1000]       [间隔时间]
 * @return {[type]}                   [function]
 */
function throttle(fn, interval = 2000) {
  let timer,
    preTime = +new Date();
  return function() {
    const self = this,
      args = arguments,
      curTime = +new Date();
    if (timer) clearTimeout(timer);
    //超过间隔时间执行,并记录当前时间是新的时间点
    if (curTime - preTime >= interval) {
      preTime = curTime;
      fn.apply(self, arguments);
    } else {
      //间隔时间内设置定时器,保证即使停止操作也至少执行一次
      timer = setTimeout(() => {
        fn.apply(self, args);
      }, interval);
    }
  };
}



  
    
    
  

  
    
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124
  • 124124

5, CSS3线性渐变实现进度条



  
    
    
    
    
    
  
  
    

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

11111111111111111111111111111111111111111111111111111111111111111

你可能感兴趣的:(面试,javascript)