user-0 提问: 求大佬帮忙看看这道题目的代码的思路

回复:
user: user-0
content: 有大佬答疑解惑吗？是不是我问的太难了

user: user-1
content: 呵呵，怎么又是你？ 代码太长，就在代码用注释给你解释吧  #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; }    总体思路很简单 就是循环一次访问每种旋转可能的结果（其中访问过的不需要在访问），然后在当前的旋转结果的基础上，派生出下一次旋转的所有可能，继续遍历访问，知道找到开锁数字为止，如果所有的旋转可能都遍历访问完了，还是没找到开锁数字，那就返回-1 举个例子 首先访问 “0000”，然后在“0000”的基础上，派生出下一次旋转可能的结果，就是 for (int pos = 0; pos < WORD_LEN; pos++) {  这个循环，得到的结果为 向上转：“1000”，“0100”，“0010”，“0001”，向下转：“9000”，“0900”，“0090”，“0009”  然后继续访问 “1000”，从“1000”又派生出了下一次旋转的可能结果 向上转：“2000”，“1100”，“1010”，“1001”，向下转：“0000”（重复，去掉），“1900”，“1090”，“1009”  画一个图就清楚了，就是个网络图   就这样依次从当前的旋转结果去访问派生出的旋转可能结果，直到找到开锁数字