本题来源于一算法同学的面试题
第一想到使用数组,因为存在循环排列,觉得构造循环链表更不错,写完感觉可能还是使用数组简洁些
/**
* liyang 2021-06-19
* 算法题:一个圆环上有100个灯泡,灯泡有打开和关闭两种状态,灯泡的状态随机,
* 按一个灯泡的开关,相邻的两个灯泡的状态也发生一次变化。
* 比如暗-亮-暗,按中间灯泡,变化为亮-暗-亮。问设计一道算法,使得所有灯泡最后都亮。
*/
struct Node {
int state;
Node* next = nullptr;
Node() {}
Node(int state) {
this->state = state;
}
};
static Node * head = nullptr;
static Node * tail = nullptr;
static Node * lastNodeOff = nullptr;
class LightGame {
public:
void static lightAllOn() {
generateLightWithRandomState();
/**
* step1
* 贪心策略,尽可能的让灯变亮
* 如果灯可以全部变量,这就是我们想要的答案
* 如果灯不能全部亮进入step2
*/
greedyWithLightOn();
if (lastNodeOff == nullptr) {
cout << "let all light with state on - step1" << endl;
printAllLightState(head);
return;
} else {
cout << "after step1" << endl;
printAllLightState(head);
}
/**
* step2
* 贪心策略,让所有的灯全灭
* 以 lastNodeOff 当作本轮循环的第一个位置,后面 3 个 1 组,将中间的灯熄灭
*/
greedyWithLightOff();
cout << "let all light with state off - step2" << endl;
printAllLightState(head);
/**
* step3
* 懒惰策略,每个开关按一遍
* 至此,所有的灯都将变量
*/
// simpleLazy();
complexLazy();
cout << "let all light with state off - step3" << endl;
printAllLightState(head);
}
private:
static void complexLazy() {
Node* pre = tail;
Node* node = head;
for (int i = 0; i < 100; ++i) {
pre->state ^= 1;
node->state ^= 1;
node->next->state ^= 1;
pre = node;
node = node->next;
}
}
static void simpleLazy() {
Node* node = head;
for (int i = 0; i < 100; ++i) {
node->state = 1;
}
}
static void greedyWithLightOff() {
tail->next = head;
Node* node = lastNodeOff->next;
for (int i = 1; i <= 99; ++i) {
node->state = 0;
node = node->next;
}
}
static void greedyWithLightOn() {
Node* node = head;
while (node->next) {
if (node->state == 0) {
if (node->next->next) {
node->state = 1;
node->next->state ^= 1;
node->next->next->state ^= 1;
} else {
if (node->next->state == 0) {
node->state = node->next->state = 1;
head->state = 0;
lastNodeOff = head;
} else {
lastNodeOff = node;
}
}
}
node = node->next;
}
if (lastNodeOff != nullptr && lastNodeOff->state == 1) {
lastNodeOff = nullptr;
}
if (node->state == 0) {
lastNodeOff = node;
}
}
/**
* state => 0 -> OFF 1 -> ON
*/
void static generateLightWithRandomState() {
srand((unsigned)time(NULL));
head = new Node(rand() % 10 > 5 ? 1 : 0);
Node* node = head;
for (int i = 1; i < 100; ++i) {
node->next = new Node(rand() % 10 > 5 ? 1 : 0);
node = node->next;
}
tail = node;
cout << "generateLightWithRandomState" << endl;
printAllLightState(head);
}
void static printAllLightState(Node* node) {
int count = 0;
while (count < 100) {
++count;
cout << node->state << " ";
node = node->next;
if (count % 10 == 0) {
cout << endl;
}
}
cout << endl;
}
};
int main() {
LightGame::lightAllOn();
return 0;
}