字节跳动笔试第三题解题思路分享(3月14日,环形按钮问题)
字节跳动 笔试第三题
输入一个bool类型的数组,首尾相接组成一个圆环
每个位置都有一个按钮,按钮按下以后自身及相邻位置改变状态(0->1;1->0)
求把所有位置都置为1所需要的最少按键次数
输入一个n代表数组长度,输入n个数字代表按钮状态
例题:
输入
10
0 1 1 0 0 0 1 0 0 1
输出
4
说明:
按下第二个位置
1 0 0 0 0 0 1 0 0 1
按下第三个位置
1 1 1 1 0 0 1 0 0 1
按下第六个位置
1 1 1 1 1 1 0 0 0 1
按下第八个位置
1 1 1 1 1 1 1 1 1 1
一共按了4次按钮,所以输出4
补充:
0 < n <= 16
解法:
BFS搜索算法
遇到前一个按钮/当前按钮/后一个按钮状态是 0 的情况
把按下按钮后的状态记录入队,并判断按下按钮后的状态是否满足条件
如果满足条件,返回按下按钮的次数
如果不满足条件,继续遍历
更多案例:
16
#笔经##Java工程师##字节跳动#
输入一个bool类型的数组,首尾相接组成一个圆环
每个位置都有一个按钮,按钮按下以后自身及相邻位置改变状态(0->1;1->0)
求把所有位置都置为1所需要的最少按键次数
输入一个n代表数组长度,输入n个数字代表按钮状态
例题:
输入
10
0 1 1 0 0 0 1 0 0 1
输出
4
说明:
按下第二个位置
1 0 0 0 0 0 1 0 0 1
按下第三个位置
1 1 1 1 0 0 1 0 0 1
按下第六个位置
1 1 1 1 1 1 0 0 0 1
按下第八个位置
1 1 1 1 1 1 1 1 1 1
一共按了4次按钮,所以输出4
补充:
0 < n <= 16
解法:
BFS搜索算法
遇到前一个按钮/当前按钮/后一个按钮状态是 0 的情况
把按下按钮后的状态记录入队,并判断按下按钮后的状态是否满足条件
如果满足条件,返回按下按钮的次数
如果不满足条件,继续遍历
更多案例:
16
0 0 1 0 0 0 1 1 0 1 0 0 1 0 0 1
int sub(int a, int b, int size) { return a - b < 0 ? a + size - b : a - b; } int add(int a, int b, int size) { return a + b >= size ? a + b - size : a + b; } bool judge(vector<int> status) { return count(status.begin(), status.end(), 0) == 0; } bool button(queue<vector<int>> &qv, vector<int> status, int index) { int size = status.size(); status[index] = 1 - status[index]; status[sub(index, 1, size)] = 1 - status[sub(index, 1, size)]; status[add(index, 1, size)] = 1 - status[add(index, 1, size)]; qv.push(status); return judge(status); } int BFS(queue<vector<int>> qv) { int cnt = 0; queue<vector<int>> temp = qv; if (judge(qv.front())) { return cnt; } while (!qv.empty()) { while (!qv.empty()) { int size = qv.front().size(); for (int i = 0; i < qv.front().size(); i++) { if (qv.front()[sub(i, 1, size)] == 0 || qv.front()[i] == 0 || qv.front()[add(i, 1, size)] == 0) { if (button(temp, qv.front(), i)) return cnt + 1; } } qv.pop(); } qv = temp; cnt++; if (cnt > 6) return -1; } } int main() { int n; while (cin >> n) { vector<int> status(n); for (auto &b : status) cin >> b; queue<vector<int>> qv; qv.push(status); cout << BFS(qv) << endl; } return 0; }看完有人会觉得这个算法时间复杂度是不是太大了
事实上确实很大,如果最终遍历次数是N
那最坏的时间复杂度就是O(16^N)
并且当我用“更多案例”进行测试时
程序运行了将近半分钟,此时temp队列的遍历数超过百万
时间复杂度和空间复杂度都不满足条件
但这已经是我能想到的唯一办法了,也希望大佬可以补充和纠正,谢谢