LeetCode //C - 301. Remove Invalid Parentheses

301. Remove Invalid Parentheses

Given a string s that contains parentheses and letters, remove the minimum number of invalid parentheses to make the input string valid.

Return a list of unique strings that are valid with the minimum number of removals. You may return the answer in any order.

Example 1:

Input: s = "()())()"
Output: "(())()","()()()"

Example 2:

Input: s = "(a)())()"
Output: "(a())()","(a)()()"

Example 3:

Input: s = ")("
Output: ""

Constraints:
  • 1 <= s.length <= 25
  • s consists of lowercase English letters and parentheses '(' and ')'.
  • There will be at most 20 parentheses in s.

From: LeetCode

Link: 301. Remove Invalid Parentheses


Solution:

Ideas:

1. Dynamic Queue and Result Resizing:

  • Queue Resizing: The BFS queue is initialized with a default size and dynamically resized if more space is needed.
  • Result Resizing: The result array is similarly resized to accommodate more valid strings as they are discovered.

2. Proper Memory Management:

  • Freeing Strings: Each dynamically allocated string in the queue and results is properly freed once it is no longer needed.
  • Clearing Visited Set: The visited set is cleared after BFS to avoid memory leaks.

3. Queue Management:

  • BFS Logic: The BFS queue is processed level by level, ensuring that all possibilities are explored and that only the minimum removal solutions are considered.
  • Memory Safety: All reallocations ensure that sufficient space is available, preventing buffer overflows and related errors.

4. Edge Cases:

  • Empty Strings: An explicit check is added for empty or null input strings, returning an empty string as the valid output.
Code:
c 复制代码
#define INITIAL_QUEUE_SIZE 1000
#define INITIAL_RESULT_SIZE 1000

// Define a structure for a hash table to store unique strings
typedef struct {
    char *str;          // Pointer to the stored string
    UT_hash_handle hh;  // Hash handle for uthash
} VisitedSet;

// Function to check if a given string has valid parentheses
bool isValid(char *s) {
    int balance = 0;
    for (int i = 0; s[i]; ++i) {
        if (s[i] == '(') balance++;
        if (s[i] == ')') balance--;
        if (balance < 0) return false; // More closing than opening
    }
    return balance == 0;
}

// Function to add a string to the visited set
bool addToVisited(VisitedSet **visited, const char *str) {
    VisitedSet *entry;
    HASH_FIND_STR(*visited, str, entry); // Check if already present
    if (!entry) {
        entry = (VisitedSet *)malloc(sizeof(VisitedSet));
        entry->str = strdup(str);
        HASH_ADD_KEYPTR(hh, *visited, entry->str, strlen(entry->str), entry);
        return true;
    }
    return false;
}

// Function to clear the visited set
void clearVisitedSet(VisitedSet *visited) {
    VisitedSet *current_entry, *tmp;
    HASH_ITER(hh, visited, current_entry, tmp) {
        HASH_DEL(visited, current_entry);
        free(current_entry->str);
        free(current_entry);
    }
}

// Function to remove invalid parentheses
char **removeInvalidParentheses(char *s, int *returnSize) {
    char **result = malloc(INITIAL_RESULT_SIZE * sizeof(char *));
    int resultCapacity = INITIAL_RESULT_SIZE;
    *returnSize = 0;

    if (!s || !*s) {
        // If string is empty or NULL, return empty string as the only valid result
        result[0] = strdup("");
        *returnSize = 1;
        return result;
    }

    VisitedSet *visited = NULL;
    char **queue = malloc(INITIAL_QUEUE_SIZE * sizeof(char *));
    int front = 0, rear = 0, queueCapacity = INITIAL_QUEUE_SIZE;
    bool found = false;

    // Initialize BFS
    queue[rear++] = strdup(s);
    addToVisited(&visited, s);

    while (front < rear) {
        int levelSize = rear - front;
        for (int i = 0; i < levelSize; ++i) {
            char *current = queue[front++];

            // Check if current string is valid
            if (isValid(current)) {
                if (!found) {
                    found = true;
                    // Reset result since this is the first valid solution
                    *returnSize = 0;
                }
                // Add valid string to result
                if (*returnSize >= resultCapacity) {
                    resultCapacity *= 2;
                    result = realloc(result, resultCapacity * sizeof(char *));
                }
                result[(*returnSize)++] = strdup(current);
            }

            // If found, skip generating further states
            if (found) {
                free(current);
                continue;
            }

            // Generate new states by removing one parenthesis at a time
            int len = strlen(current);
            for (int j = 0; j < len; ++j) {
                if (current[j] != '(' && current[j] != ')') continue;

                char *next = strdup(current);
                memmove(&next[j], &next[j + 1], len - j);

                if (addToVisited(&visited, next)) {
                    // Resize queue if needed
                    if (rear >= queueCapacity) {
                        queueCapacity *= 2;
                        queue = realloc(queue, queueCapacity * sizeof(char *));
                    }
                    queue[rear++] = next;
                } else {
                    free(next);
                }
            }

            free(current);
        }

        // If a valid expression was found, stop further exploration
        if (found) break;
    }

    clearVisitedSet(visited);
    free(queue);

    // If no valid expression found, return empty string
    if (*returnSize == 0) {
        result[0] = strdup("");
        *returnSize = 1;
    }

    return result;
}

// Helper function to free the result array
void freeResults(char **results, int returnSize) {
    for (int i = 0; i < returnSize; ++i) {
        free(results[i]);
    }
    free(results);
}
相关推荐
典典分享指南8 小时前
VS Code Git 工作树:解锁多分支并行开发新体验
算法·决策树·逻辑回归·启发式算法
_Narcissus_9 小时前
枚举和模拟算法笔记
c语言·数据结构·c++·笔记·算法·模拟·枚举
天疆说9 小时前
策略的进化:从随心所欲到稳健前行
算法
冻柠檬飞冰走茶9 小时前
《数据结构实验指导-C++语言版》 在顺序表 list 中查找元素 x
开发语言·数据结构·c++·算法·list
happyprince10 小时前
03-深刻观-CodeX哲学与升华(源码)
算法·ai编程
不会打球的王子10 小时前
Day 27:迁移学习与微调 — 站在巨人的肩膀上
算法
老当益壮梁奶奶10 小时前
Linux软件编程学习笔记(二)Linux文件IO编程入门:从fopen到fgetc
linux·c语言·c++·笔记·学习
sunoo-22910 小时前
C 语言文件 IO 全攻略:从基础函数到实战踩坑(BMP 读取 + 词典查询)
linux·c语言·前端·笔记·vscode·学习
数模竞赛Paid answer11 小时前
2025年中青杯数学建模A题康养城市建设求解全过程论文及程序
算法·数学建模·数据分析·中青杯
网安蟹佬霸11 小时前
密码学安全实战:从加密原理到哈希破解的完整攻防指南
网络·算法·安全·web安全·开源·密码学·哈希算法