LeetCode //C - 332. Reconstruct Itinerary

332. Reconstruct Itinerary

You are given a list of airline tickets where ticketsi = fromi, toi represent the departure and the arrival airports of one flight. Reconstruct the itinerary in order and return it.

All of the tickets belong to a man who departs from "JFK", thus, the itinerary must begin with "JFK". If there are multiple valid itineraries, you should return the itinerary that has the smallest lexical order when read as a single string.

  • For example, the itinerary "JFK", "LGA" has a smaller lexical order than "JFK", "LGB".

You may assume all tickets form at least one valid itinerary. You must use all the tickets once and only once.

Example 1:

Input: tickets = \["MUC","LHR","JFK","MUC","SFO","SJC","LHR","SFO"]
Output: "JFK","MUC","LHR","SFO","SJC"

Example 2:

Input: tickets = \["JFK","SFO","JFK","ATL","SFO","ATL","ATL","JFK","ATL","SFO"]
Output: "JFK","ATL","JFK","SFO","ATL","SFO"
Explanation: Another possible reconstruction is "JFK","SFO","ATL","JFK","ATL","SFO" but it is larger in lexical order.

Constraints:
  • 1 <= tickets.length <= 300
  • ticketsi.length == 2
  • f r o m i . l e n g t h = = 3 from_i.length == 3 fromi.length==3
  • t o i . l e n g t h = = 3 to_i.length == 3 toi.length==3
  • f r o m i a n d t o i c o n s i s t o f u p p e r c a s e E n g l i s h l e t t e r s . from_i and toi consist of uppercase English letters. fromiandtoiconsistofuppercaseEnglishletters.
  • f r o m i ! = t o i from_i != to_i fromi!=toi

From: LeetCode

Link: 332. Reconstruct Itinerary


Solution:

Ideas:
  • Deferred Memory Freeing: The nodes (Node*) in the adjacency list are no longer freed immediately within the DFS loop. Instead, they're freed only after the DFS traversal is complete, preventing use-after-free errors.
  • DFS Stack Handling: The stack is used to manage the DFS iteration, and nodes are correctly removed from the adjacency list as they are processed. The itinerary is built in reverse order and then freed once fully constructed.
Code:
c 复制代码
#define MAX_TICKETS 300
#define MAX_AIRPORTS 26 * 26 * 26 // Assuming three-letter airport codes
#define AIRPORT_CODE_LEN 4

// Node structure for adjacency list
typedef struct Node {
    char airport[AIRPORT_CODE_LEN];
    struct Node* next;
} Node;

// Function to insert an edge into the adjacency list, maintaining lexicographical order
void insertEdge(Node* adjList[], char* from, char* to) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    strcpy(newNode->airport, to);
    newNode->next = NULL;

    int index = (from[0] - 'A') * 26 * 26 + (from[1] - 'A') * 26 + (from[2] - 'A');

    if (adjList[index] == NULL || strcmp(adjList[index]->airport, to) > 0) {
        newNode->next = adjList[index];
        adjList[index] = newNode;
    } else {
        Node* current = adjList[index];
        while (current->next != NULL && strcmp(current->next->airport, to) < 0) {
            current = current->next;
        }
        newNode->next = current->next;
        current->next = newNode;
    }
}

// Iterative DFS using a stack to build the itinerary
void dfs(char* airport, Node* adjList[], char** itinerary, int* index) {
    char* stack[MAX_TICKETS + 1];
    int stackSize = 0;

    stack[stackSize++] = airport;

    while (stackSize > 0) {
        char* currentAirport = stack[stackSize - 1];
        int idx = (currentAirport[0] - 'A') * 26 * 26 + (currentAirport[1] - 'A') * 26 + (currentAirport[2] - 'A');

        if (adjList[idx] != NULL) {
            Node* nextNode = adjList[idx];
            stack[stackSize++] = nextNode->airport;
            adjList[idx] = nextNode->next;
            // Do not free nextNode here; defer the free operation until the end
        } else {
            itinerary[(*index)--] = stack[--stackSize];
        }
    }
}

// Function to find the itinerary from the list of tickets
char** findItinerary(char*** tickets, int ticketsSize, int* ticketsColSize, int* returnSize) {
    Node* adjList[MAX_AIRPORTS] = {NULL};

    // Populate the adjacency list with the tickets
    for (int i = 0; i < ticketsSize; i++) {
        insertEdge(adjList, tickets[i][0], tickets[i][1]);
    }

    char** itinerary = (char**)malloc((ticketsSize + 1) * sizeof(char*));
    int index = ticketsSize;
    dfs("JFK", adjList, itinerary, &index);

    // Freeing nodes after DFS traversal is complete
    for (int i = 0; i < MAX_AIRPORTS; i++) {
        Node* current = adjList[i];
        while (current) {
            Node* next = current->next;
            free(current->airport);
            free(current);
            current = next;
        }
    }

    *returnSize = ticketsSize + 1;
    return itinerary;
}
相关推荐
ysa0510304 小时前
【板子】短序列dp(换成维护更小常数维度的dp)
c++·笔记·算法·板子
shwill1234 小时前
PID 算法(三)--- 增量 PID ↔ 单神经元 PID 等价映射
linux·算法
wabs6665 小时前
关于图论【卡码网110.字符串迁移的思考】
数据结构·算法·图论
影视飓风TIM5 小时前
Linux下C程序编译:gcc 动态链接与静态链接全解
linux·c语言
hanlin035 小时前
刷题笔记:力扣第242、349题(哈希表)
笔记·算法·leetcode
aramae6 小时前
C++ IO流完全指南:从C标准库到C++流式编程
服务器·c语言·开发语言·c++·后端
only-qi7 小时前
大模型Agent面试攻略:落地工程痛点、评估体系与Agentic RAG核心精讲
人工智能·算法·面试·职场和发展·langchain·rag
麻瓜老宋8 小时前
AI开发C语言应用按步走,表达式计算器calc的第二十四步,结束开发,生成calc 用法指南
c语言·开发语言·atomcode
0x3F(小茶)8 小时前
STM32 SPI的5种方向模式
c语言·stm32·单片机·嵌入式硬件
Gauss松鼠会9 小时前
【GaussDB】GaussDB锁阻塞源头查询
java·开发语言·前端·数据库·算法·gaussdb·经验总结