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;
}
相关推荐
Jerry14 小时前
LeetCode 28. 找出字符串中第一个匹配项的下标
算法
Jerry15 小时前
LeetCode 459. 重复的子字符串
算法
海石18 小时前
1500分的题目,确实有实力,不过还是我略胜一筹
算法·leetcode
海石18 小时前
【记忆化搜索】条条大路通AC,走好适合你的那一条,走到后再考虑走得快
算法·leetcode
gugucoding20 小时前
21. 【C语言】打包不同类型:结构体
c语言·开发语言
Jerry20 小时前
LeetCode 151. 反转字符串中的单词
算法
gugucoding21 小时前
31. 【C语言】堆栈与队列的实现
c语言·开发语言·数据结构·链表
a1117761 天前
LM 算法迭代过程动画演示(SLAM)
算法
头茬韭菜1 天前
Context 的生死抉择:四层压缩、截断算法与 Session Memory
算法·ai
Jerry1 天前
LeetCode 541. 反转字符串 II
算法