对一道【脉脉】上 头条 算法面试题的思考

103

偶然间在脉脉上看到了一道头条的算法面试题

clipboard.png

按照题目的理解,简单的写了一个html网页

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>pool</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
    <div id="vue_det">
        <div @click="SmartChange(0)" style="width:40px;height:40px;background:#fff">开始</div>
        <div class="pool" v-for="(item, index) in list">
            <div @click="change(index)" v-if="item" style="width:40px;height:40px;background:#999;float:left">{{index}}</div>
            <div @click="change(index)" v-if="!item" style="width:40px;height:40px;background:#fff;float:left">{{index}}</div>
        </div>
    </div>
 
    <script src="https://cdn.bootcss.com/vue/2.6.4/vue.js"></script>
    <script>
        var vm = new Vue({
                el: '#vue_det',
                data: {
                    list: [],
                    i: 0
                },
                methods: {
                    details: function () {
                        return this.site + " - 学的不仅是技术,更是梦想!";
                    },
                    change (index) {
                        // console.log(index)
                        if (index === 99) {
                            this.list[0] = !this.list[0]
                            this.list[98] = !this.list[98]
                            this.list[99] = !this.list[99]
                        } else if (index === 0) {
                            this.list[0] = !this.list[0]
                            this.list[1] = !this.list[1]
                            this.list[99] = !this.list[99]
                        } else {
                            // console.log('222')
                            this.list[index] = !this.list[index]
                            this.list[index - 1] = !this.list[index - 1]
                            this.list[index + 1] = !this.list[index + 1]
                        }
                        // console.log(this.list)
                        this.list = JSON.parse(JSON.stringify(this.list))
                    },
                    SmartChange (index) {
                      if (this.i === 99) {
                          return false
                      }
                      if (this.list[this.i] === true) {
                          this.i = this.i + 1
                          setTimeout(() => {
                            this.SmartChange()  
                          }, 10);
                      } else {
                          this.change(this.i + 1)
                          setTimeout(() => {
                              this.SmartChange()
                          }, 10);
                      }
                    //   console.log('222222222',this.i)
                    },
                    go () {
                        for (let index = 1; index < 101; index++) {
                            this.list.push(Math.random() > 0.5 ? true : false)
                        }
                        console.log(this.list)
                        let a = 0, b = 0
                        this.list.map(val => {
                            if (val) {
                                a++
                            } else {
                                b++
                            }
                        })
                        console.log(a, b)
                    }
                },
                created () {
                    this.go()
                }
            })
    </script>
</body>
</html>

得到了如下效果图

clipboard.png

图片描述

得到如题可以进行开关的示例
在最后一个灯特殊处理,链接第一个灯,形成环

经过测试发现
只要从序号0开始,如果打开则跳过,如果是灭灯,则点击i+1
得到如下效果

图片描述

敲黑板

现在得出的部分结论是
只有随机亮灭灯是一定比例的时候才有可能全部点亮

现在可行的比例为
亮-灭 50-50
亮-灭 51-49
亮-灭 47-53
亮-灭 44-56
亮-灭 42-58
亮-灭 53-47
亮-灭 54-46

而且,还决定于最后一个灯和相邻灯的亮灭

大家有什么好想法,可以留下见解讨论下

如果觉得我的文章对你有用,请随意赞赏
已赞赏

你可能感兴趣的

31 条评论
不想发言 · 2月19日

如果是一个环,就不应该有最后一个。

+3 回复

杨永池 · 2月19日

说下我的思路。
先解决这个问题:怎么点亮其中一个灯泡,而保持其他灯泡状态不变?这个问题解决了,然后循环即可。思路如下:
1,比如第1个灯是灭的,剩余99个灯的状态不需要知道,只需要记录99个灯的状态取反的次数,如果是偶数次,则状态没有变化。
2,这个问题等价于第1个一个灯的取反次数是奇数次,剩余99个取反次数是偶数次
3,从第1个灯泡开始依次取反(每次有3个灯泡),一直到第98个,此时每个灯泡取反次数分别为 2 3 3 3 ... ... 3 2 1 1
4,此时可以发现,2里的条件只有第98个灯泡达到了,剩余的都不满足,而剩余的正好是99个,33个3,正好可以全部取反,然后就满足条件2了

+3 回复

joy钰 · 2月19日

做了一半。。。
简单写了个demo
最后出现的情况是可能有0、1、2个灯泡是暗的。
1个灯泡暗和2个灯泡暗本质上是一样的。
关键就是有没有办法转到3个灯泡暗的情况,这样倒是能全亮了。

+2 回复

0

按照我的方法,可以转成99个灯都是暗的,跟3个暗是一样的

杨永池 · 2月19日
0

@杨永池 看到啦~感谢指点

joy钰 · 2月19日
小蜗牛 · 2月19日

提供以下思路:

获取这100个灯的任意初始状态,
1/ 循环检测 当遇到 暗灯(下面以 ✖️ 表示), 按下一个灯,第一个遍循环达到最后的效果是:全亮   /  99个亮1个暗,不存在第二种现象;
            注释:注意是圆环,所以,当有三个不相连的暗灯或者两个不相连的暗灯都可以变为1个暗灯;
       
 2/  这里只需解决1个暗灯现象
            点击这个暗灯前一个灯,让其状态变为  ✖️  ✖️   ✔️
            这里将其100个灯分割一下,
                       1- 97    |    98 -100
                    ✔️ ✔️   ✖️     |  ✖️ ✔️ ✔️

             单 ✖️ 向左 传递,3位一个循环, 循环一次 变为
              1- 94   |      95 -97         |    98 - 100
            ✔️ ✔️   ✖️   |       ✔️ ✔️ ✔️         |   ✖️ ✔️ ✔️

              1- 97 最终循环结果位  

              1- 97     |     98 -100 
               ✖️ ✔️ ✔️    |     ✖️ ✔️ ✔️

              处理一下 98 - 100 

              1- 97     |     98 -100 
               ✖️ ✔️ ✔️    |    ✔️  ✖️ ✖️

            ok  结束

+2 回复

0

实际测试1- 97 最终循环结果位 无法做到如图:

                  1- 97     |     98 -100 
           ✖️ ✔️ ✔️    |     ✖️ ✔️ ✔️
aracta · 2月27日
0

@aracta 吓我一跳,我立马用我手写公式看了一下

1 - 4 | 5 - 97 | 98 - 100

✔️ ✔️ ✔️ ✖️ | ✔️ ✔️ ✔️。。。 | ✖️ ✔️ ✔️

继续点;

1 2 3 4 | 5 - 97 | 98 - 100

✔️ ✖️ ✖️ ✔️ | ✔️ ✔️ ✔️。。。 | ✖️ ✔️ ✔️

再继续

1 2 3 4 | 5 - 97 | 98 - 100

✖️ ✔️✔️ ✔️ | ✔️ ✔️ ✔️。。。 | ✖️ ✔️ ✔️

跟预期的一样

小蜗牛 · 2月27日
莫名小晟 · 2月26日

全亮我做不到,但给我把锤子我可以让灯泡全灭

+2 回复

kumfo · 2月19日

没想法,有想法就懒得看你文章了

+1 回复

0

想不通,想了半天了,智商余额不足

SuperX 作者 · 2月19日
ange · 2月23日

灯数n,当n=4时或者当n>5的时候满足(n-2)%3==0 才能保证任意情况都可以全亮或者全灭。

+1 回复

不想发言 · 2月19日

但是感觉不一定有解

回复

0

一定有解的,如果不能全亮,那么就一定可以全灭的。

觅码君 · 2月19日
神の吻 · 2月19日

此题有解,解法如下:
1、全亮=亮1个+3*33=亮2个相邻的(点击亮的那个边上的)=2+98/3=灭两个相邻的
2、全灭=灭1个+3*33=灭2个相邻的(点击灭的那个边上的)
3、全亮=全灭
4、所有随机状态,通过循环点击灭的灯后面的,可以将前98个状态统一为亮灯状态,剩下的2个,无论是亮一个,还是亮2个,都是可操作的。

回复

0

道理我都懂,但是怎么把亮一个/亮两个操作成全灭呢?

gaoryrt · 2月19日
1

亮一个,剩下的99个,你除以3呀,3个一组,点击中间的就可以啦

神の吻 · 2月19日
0

是随机初始化的,你怎么保证只亮一个

不想发言 · 2月20日
觅码君 · 2月19日

有一种快速判断方法,判断最后是全亮还是全灭的状态:
1、如果亮灯数%3 == 0,那么灭灯数%3 == 1,将所有灯调整为灭灯状态。
2、如果灭灯数%3 == 0,那么亮灯数%3 == 1,将所有灯调整为亮灯状态。
3、亮灯数%3 == 2,灭灯数%3 == 2,则全亮全灭都可实现。

回复

0

全亮=全灭,看我的回复~

神の吻 · 2月19日
0

@神の吻 恩,道理差不多,我只是在操作之前先判断一下要操作成哪种结果,你写的是具体的实现。

觅码君 · 2月19日
0

不太行哦,不太符合您的公式,验证了几个就崩了

SuperX 作者 · 2月19日
auto23_xyc · 2月25日

关于全灭→全亮

全灭状态下依次点击所有的灯,每个灯状态变三次,结果一定是全亮

回复

auto23_xyc · 2月25日

如果99个灯就不一定有解了吧😺

回复

DaemonGW · 2月26日

只保留1 + 99灯基本操作略过,最后可以保证只留一个灯保持一个状态,其余99个灯相反状态,通过3*33几个将99个同一状态的灯全部取反。结论就是如果取全灭就通过基本操作后留一个灯灭,如果取全亮就通过基本操作后留一个灯亮

回复

linux_azhou · 2月28日

全灭状态下依次点击所有的灯,每个灯状态变三次,结果一定是全亮

可以用数学来证明,将灯泡排序,同时 p 代表点击次数,p0 - p1 - ... - p99
对于灯泡 1,如果要亮,需要满足:
(p0 + p1 + p2) % 2 = 1
同样的,对于灯泡 2:
(p1 + p2 + p3) % 2 = 1
...
(p99 + p0 + p1) % 2 = 1

这么一看,p0 = p1 = p2 = p3 = ... = p99 = 1 就满足条件了

回复

SmartCoder · 3月5日

验证了所有情况都可以被全部点亮。可以见我的解法:https://segmentfault.com/a/11...
在线效果:https://codepen.io/FreadChen/...

回复

wuwentao · 3月10日

<!DOCTYPE html>
<html lang="en">
<head>

<meta charset="UTF-8">
<title>bulb1</title>
<style>
    #bulbs span {
        display: inline-block;
        width: 25px;
        height: 25px;
        line-height: 25px;
        text-align: center;
    }
</style>

</head>
<body>

<div id="bulbs"></div>

<script>
function generateBulb(n) {

var bulbs = [];
for (var i = 0; i < n; i++) {
    bulbs.push(Math.round(Math.random()));
}
return bulbs;

}

function allBright(bulbs) {

var count = 0,
    len = bulbs.length;
for (var i = 0; i < len; i++) {
    if (bulbs[i]) count++;
}
return count >= len;

}

function lightOn(bulbs, i) {

var len = bulbs.length,
    last_i = i - 1 < 0 ? len - 1 : i - 1,
    next_i = i + 1 >= len ? 0 : i + 1;

console.log('前==>' + last_i + ':' + i + ':' + next_i, '==>', bulbs[last_i] + ':' + bulbs[i] + ':' + bulbs[next_i]);
bulbs[i] = +!bulbs[i];
bulbs[last_i] = +!bulbs[last_i];
bulbs[next_i] = +!bulbs[next_i];
console.log('后==>' + last_i + ':' + i + ':' + next_i, '==>', bulbs[last_i] + ':' + bulbs[i] + ':' + bulbs[next_i]);

}

function generateElement(bulbs) {

var bulbs_el = document.getElementById('bulbs');
var el = document.createDocumentFragment();

bulbs.forEach(function(bulb) {
    var item = document.createElement('span');
    item.innerHTML = bulb;
    if (bulb) {
        item.style.color = 'white';
        item.style.background = 'blue';
    }
    el.appendChild(item);
});

bulbs_el.innerHTML = '';
bulbs_el.appendChild(el);

}

function exct() {

window.requestAnimationFrame(function() {
    var len = bulbs.length, last_i, next_i, next_i_2, next_i_3, next_i_4;

    var init_index = 0;

    bulbs.every(function(bulb, index) {
        if (!bulb) {
            init_index = index;
            return false;
        }
        return true;
    });
    init_index = ++init_index % len;
    console.log('init_index:', init_index);

    for (var i = init_index; i < len; i = i + 3) {
        last_i = i - 1 < 0 ? len - 1 : i - 1;

        next_i = i + 1 >= len ? 0 : i + 1;
        next_i_2 = next_i + 1 > len ? 0 : next_i;
        next_i_3 = next_i_2 + 1 > len ? 0 : next_i_2;
        next_i_4 = next_i_3 + 1 > len ? 0 : next_i_3;

        // 改变连贯灯泡状态
        if (!bulbs[last_i]) {
            lightOn(bulbs, i);
        }

        // next: 100-011
        if (bulbs[last_i] && !bulbs[i] && !bulbs[next_i] && !bulbs[next_i_2] && bulbs[next_i_3] && bulbs[next_i_4]) {
            lightOn(bulbs, next_i);
        }

        // next: 101-101
        if (bulbs[last_i] && !bulbs[i] && bulbs[next_i] && bulbs[next_i_2] && !bulbs[next_i_3] && bulbs[next_i_4]) {
            lightOn(bulbs, next_i);
            lightOn(bulbs, next_i_2);
        }

        // next: 110-001
        if (bulbs[last_i] && bulbs[i] && !bulbs[next_i] && !bulbs[next_i_2] && !bulbs[next_i_3] && bulbs[next_i_4]) {
            lightOn(bulbs, next_i_2);
        }

    }

    generateElement(bulbs);

    if (!is_exit && !allBright(bulbs)) {
        exct();
    } else {
        console.log('end:', bulbs);
        console.timeEnd('exct time');
    }
});

}

var is_exit = false;

function exit() {

is_exit = true;

}

function start() {

is_exit = false;
exct();

}

var bulbs = generateBulb(100);
console.log('begin:', bulbs);
console.time('exct time');
exct();

</script>
</body>
</html>

回复

0

我这方法我亲测时间复杂度12秒左右,欢迎提意见

wuwentao · 3月10日
载入中...