leetCode1091.二进制矩阵中的最短路径

209 阅读2分钟

问题描述

leetcode1901

1
2
3

思路

最短路径题目想到的算法是BFS,通过队列实现,把当前位置压入队列,再弹出一个队列元素,把该元素可能到达的位置再压如队列,这样一层一层的找,直到找到目标位置,走过的就是最短路径。

代码

队列初始化

因为要用队列实现BFS,所以首先定义队列的函数

//创建结点
typedef struct dataType{
    int x;
    int y;
}DType;
struct Node{
    DType val;
    struct Node* next;
};
//创建队列数据结构
struct Queue{
    struct Node* head;
    struct Node* tail;
    int size;
};
typedef struct Queue* Qpinter;
typedef struct  Node* nodePr;
//创建队列
Qpinter creatQueue()
{
    Qpinter tempQ = (Qpinter)malloc(sizeof(struct Queue));
    if(tempQ == NULL)
        return NULL;
    tempQ->head = NULL;
    tempQ->tail = NULL;
    tempQ->size = 0;
    return tempQ;
}
//插入元素
Qpinter insetQueue(Qpinter q, DType a)
{
    nodePr tempN = (nodePr)malloc(sizeof(struct Node));
    tempN->val = a;
    tempN->next = NULL;
    if(q->head == NULL)
    {
        q->tail = tempN;
        q->head = tempN;
    }
    else{
        q->tail->next = tempN;
    }
    q->tail = tempN;
    q->size++;
    return q;
}
//删除元素
DType deleQueue(Qpinter q)
{
    DType res;
    nodePr temp;
    if(q->head == NULL)
        exit(0);
    if(q->head == q->tail)
    {
        res = q->head->val;
        temp = q->head;
        q->head = NULL;
        q->tail = NULL;
    }
    else{
        res = q->head->val;
        temp = q->head;
        q->head = q->head->next;
    }
    free(temp);
    q->size--;
    return res;
}
//销毁队列
void destoryQ(Qpinter q)
{
    nodePr temp;
    while(q->head != NULL)
    {
        temp = q->head;
        q->head = q->head->next;
        free(temp);
    }
}

主程序

int shortestPathBinaryMatrix(int** grid, int gridSize, int* gridColSize){
    Qpinter Q1 = creatQueue();
    DType temp = {0, 0}; //可以直接按照结构体顺序初始化
    //判断一些边界条件
    if(grid[0][0] == 1 || grid[gridSize - 1][*gridColSize - 1] == 1)
        return -1;
    if(gridSize == 1 && *gridColSize == 1) return 1; 
    //首先压如第一个元素
    int res = 1;
    int mark[gridSize][*gridColSize];
    insetQueue(Q1, temp);
    //mark记录走过的位置,以免重复走
    mark[temp.x][temp.x] = 1;
    //如果队列不为空,就一直往下走,若队列为空了,说明走完了所有的路也没找到目标位置,直接返回
    while(Q1->head != NULL)
    {
        //计算当前队列的元素个数,来确定弹出元素的次数,因为每弹出一个元素就会加入一些元素,队列长度会变
        int size = Q1->size;
        for(int i = 0; i < size; i++){
            temp = deleQueue(Q1);
           // mark[x][y] = 1; mark标记应该放在8向遍历中,不然会重复很多操作,会超时
            int x = temp.x;
            int y = temp.y;
           //相对位置计算
           int destion[8][2] = {{x-1,y-1},{x-1,y},{x-1,y+1},{x,y-1},{x,y+1},{x+1,y-1},{x+1,y},{x+1,y+1}};
            for(int j = 0; j < 8; j++)
            {
                int x = destion[j][0];
                int y = destion[j][1];
                //数组越界
                if(x < 0 || x >= gridSize || y < 0 || y >= *gridColSize)
                    continue;
                //找到了
                if(x == gridSize - 1 && y == *gridColSize - 1) return res + 1;              //已经走过了
                if(mark[x][y] == 1) 
                    continue;
                //此路不通
                if(grid[x][y] == 1) continue;
                temp.x = x;
                temp.y = y;
                mark[temp.x][temp.y] = 1; //应该在8向遍历时更新,在pop时更新会超时
                insetQueue(Q1, temp);
            }
        }
        res++;
    }
    return -1;
}

总结

  • 时间复杂度O(n):n为元素个数
  • 空间复杂度O(K):K为队列的最大长度