字节跳动笔试第三题解题思路分享(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队列的遍历数超过百万
时间复杂度和空间复杂度都不满足条件
但这已经是我能想到的唯一办法了,也希望大佬可以补充和纠正,谢谢