头条算法-点亮圆环上所有的灯

707 阅读2分钟

问题描述

给你100盏灯围成一个圆环,灯有两种状态,要么是亮的要么是灭的,灯的初始状态是随机的。每个灯有一个开关,灯的开关具有这样的作用,按一下某个灯的开关,则该灯以及它相邻的两个灯的状态都会发生一次变化,即亮的变成暗的,暗的变成亮的。例如亮–亮--亮,按下中间的开关,则三盏灯全灭,亮–暗--暗,按下中间的开关,变成暗–亮--亮… 问你有没有办法使得100盏灯全亮,如果有,请说明你的算法思路。

算法解决

1 如果一共有99盏灯是全灭的,那么很容易就想到如何全部点亮,那么此时如果有100盏灯是全灭的,怎么全部点亮

可以发现不管是100盏灯还是101盏灯,按照从0开始依次按就可以全部点亮。

2 如果100盏灯中有一盏灯是亮的的,那么就是剩下99盏灯是全灭的,应该很好解决

所以现在的问题就是如果获得全灭的灯,可以先遍历从0到97盏灯,遇到亮的就按灭,那么最后剩下第98和第99盏灯,此时就分几种情况了 2.1 如果第98和第99盏灯全灭的话,那就等于转换为了100栈全灭的灯了 2.2 如果第98和第99盏灯中有一盏灯是亮的话,那么此时就转换为了只有一盏灯是亮的情况了。

3 怎么想到是灯全灭的这种情况呢?

因为输入的状态的灯是随机的,所以处理的时候得需要统一处理一下

代码

function triggle(list, i) {
  if (i < 0 || i > list.length - 1) {
    return;
  }
  list[i] = list[i] === 1 ? 0 : 1;
  if (i === 0) {
    if (list.length > 2) {
      list[list.length - 1] = list[list.length - 1] === 1 ? 0 : 1;
    }
    list[1] = list[1] === 1 ? 0 : 1;
  } else if (i === list.length - 1) {
    if (list.length > 2) {
      list[list.length - 2] = list[list.length - 2] === 1 ? 0 : 1;
    }
    list[0] = list[0] === 1 ? 0 : 1;
  } else {
    list[i + 1] = list[i + 1] === 1 ? 0 : 1;
    list[i - 1] = list[i - 1] === 1 ? 0 : 1;
  }
}
function triggleAllLeds(lists) {
  for (let i = 0; i < lists.length - 2; i++) {
    if (lists[i] === 1) {
      triggle(lists, i + 1);
    }
  }
  if (lists[lists.length - 1] === 0 && lists[lists.length - 2] === 0) {
    for (let i = 0; i < lists.length; i++) {
      triggle(lists, i);
    }
    return lists;
  } else if (lists[lists.length - 1] === 1 && lists[lists.length - 2] === 0) {
    for (let i = 1; i < lists.length - 2; i += 3) {
      triggle(lists, i);
    }
    return lists;
  } else if (lists[lists.length - 1] === 0 && lists[lists.length - 2] === 1) {
    for (let i = 0; i < lists.length - 3; i += 3) {
      triggle(lists, i);
    }
    return lists;
  } else {
    triggle(lists, 98);
    triggle(lists, 99);
    for (let i = 2; i < lists.length - 4; i += 3) {
      triggle(lists, i);
    }
    return lists;
  }
}

export default triggleAllLeds;