70,022
社区成员




#define WORD_LEN 4 //这两个宏看懂了就不解释了
#define MAX_CHAR_LEN 10000
// 向上旋转 9->0
char* moveUp(char* str, int pos) //第一个参数是传入的字符串,比如传入“1234”,第二个参数是旋转的位置,比如1,旋转后的结果为“1334”
{
char* tempStr = (char *)malloc(sizeof(char) * (WORD_LEN + 1)); //这里加1是因为还多了个字符串结束符'\n'
if (tempStr == NULL) { return NULL; }
strncpy(tempStr, str, strlen(str) + 1); //这里+1也是因为str也有个字符串结束符,其实用strcpy也一样,只是strncpy可以指定长度拷贝,相对来说比strcpy安全,也就是更能保证拷贝后数组不越界
tempStr[pos] = (tempStr[pos] == '9') ? '0' : tempStr[pos] + 1; //这里就不用解释了吧,如果是9,向上转就回到0,否则就是转到当前数字+1
return tempStr;
}
// 向下旋转 0->9
char* moveDown(char* str, int pos) //这个函数和上面的一样,只是向下转,比如“1234”,位置1,旋转的结果就是“1134”
{
char* tempStr = (char *)malloc(sizeof(char) * (WORD_LEN + 1));
if (tempStr == NULL) { return NULL; }
strncpy(tempStr, str, WORD_LEN + 1);
tempStr[pos] = (tempStr[pos] == '0') ? '9' : tempStr[pos] - 1;
return tempStr;
}
int openLock(char ** deadends, int deadendsSize, char * target)
{
int index = 0; //index是visited的下标,用于记录该下标是否出现过(或者叫访问过)
int step = 0; //step是记录找到开始结果为止所用的旋转步数
int head = 0; //head是记录dataQuene的当前旋转可能结果的下标
int tail = 0; //tail是记录dataQuene的最后一个旋转可能结果的下标
int leavel = 0; //记录从head到tail一共有多少转旋转可能结果
char* tempStr; //记录当前旋转结果
char* tempStrUp; //记录向上旋转的可能结果
char* tempStrDown; //记录向下旋转的可能结果
char* dataQuene[MAX_CHAR_LEN] = {}; //保存旋转可能的结果(也就是下一步向上或向下转是什么样的,这些可能的结果都保存下来挨个访问)
int visited[MAX_CHAR_LEN] = {0}; //记录某个旋转结果是否出现过,没出现则为0,出现过则为1
// 将deadends作为下标的visited置为1
for (int i = 0; i < deadendsSize; i++) { //这个for循环看懂了就不解释了,就是把死亡数字都记录为出现过(或访问过)
index = atoi(deadends[i]);
visited[index] = 1;
}
//如果头已经在死亡序列中,直接返回-1
if (visited[head] == 1) { //你的理解是对的,就是判断“0000”是否在死亡数字里,你改成用visited[0]也没问题
return -1;
}
dataQuene[tail++] = "0000"; // 将头入队列 //这里就是把头放在下一步旋转的可能结果队列里,因为都是从“0000”出发,所以无条件放入,同时最后一个旋转可能结果的位置+1(表示队列里多了一个旋转可能)
visited[head] = 1; //这里赋值为1,是表示“0000”出现过了,因为从“0000”出发,把它放入队列的同时也记录它出现过
while (head != tail) { //这个while循环表示dataQuene的旋转可能结果还没转完就继续循环,如果过head和tail一样,则说明所有可能旋转的结果都已经转完了
leavel = tail - head; //这里是表示从head到tail一共有多少种旋转可能结果
for (int k = 0; k < leavel; k++) { //然后依次循环这些旋转可能结果,判断里面是否有开锁数字
tempStr = dataQuene[head++]; //这里是获得当前的旋转结果
if (strcmp(tempStr, target) == 0) { //判断当前旋转结果是否和开锁数字一样,如果一样,则返回旋转步数
return step;
}
for (int pos = 0; pos < WORD_LEN; pos++) { //如果当前旋转结果和开锁数字不一样,则每个位置依次旋转,并把旋转可能的结果保留到dataQuene
// 向上旋转
tempStrUp = moveUp(tempStr, pos); //这里首先获得向上旋转的可能结果
index = atoi(tempStrUp);
if (visited[index] == 0) {//如果该旋转可能结果的数字还没出现过,则放到dataQuene里等待访问
dataQuene[tail] = tempStrUp;
visited[index] = 1; //并记录该数字为出现过(或访问过),也就是控制出现过的数字不要再重复访问了
tail++;
}
// 向下旋转
tempStrDown = moveDown(tempStr, pos); //其次获得向下旋转的可能结果
index = atoi(tempStrDown);
if (visited[index] == 0) { //如果该旋转可能结果的数字还没出现过,则放到dataQuene里等待访问
dataQuene[tail] = tempStrDown;
visited[index] = 1; //并记录该数字为出现过(或访问过),也就是控制出现过的数字不要再重复访问了
tail++;
}
}
}
step++; //如果找不到开锁结果,就累加旋转步数
}
return -1;
}