当前位置:首页 > 技术 > 正文内容

力扣算法刷题总结

访客 技术 2026年5月26日 3

本文主要记录了五种典型算法题的解法,涵盖数组、链表、字符串、栈、队列等常见数据结构。以下是每道题的具体实现思路和代码示例。

一、二维数组搜索

题目概述

给定一个有序二维数组,寻找目标值是否存在。

解法一:逐行筛选

利用每行的有序性,先筛选可能的行,再在候选行中进行逐列查找。时间复杂度最坏为O(m+n)。

bool searchMatrix(int** grid, int rows, int* cols, int target) {
    int row = 0;
    while (row < rows && grid[row][cols[0] - 1] < target) {
        row++;
    }
    for (int i = 0; i < cols[0]; i++) {
        if (grid[row][i] == target) {
            return true;
        }
    }
    return false;
}

解法二:二分查找

将二维矩阵视为一维有序数组,利用二分查找实现高效查找。时间复杂度为O(log(mn))。

bool searchMatrix(int** grid, int rows, int* cols, int target) {
    int left = 0, right = rows * cols[0];
    while (left < right) {
        int mid = left + (right - left) / 2;
        int x = grid[mid / cols[0]][mid % cols[0]];
        if (x == target) {
            return true;
        }
        if (x < target) {
            left = mid + 1;
        } else {
            right = mid;
        }
    }
    return false;
}

二、双链表转数组

题目概述

将双向链表转换为数组,并通过指针返回数组长度。

解法思路

通过三次遍历获取链表长度,再进行数组填充。时间复杂度为O(n)。

struct Node {
    int val;
    struct Node* prev;
    struct Node* next;
};

int* listToArray(struct Node* head, int* returnSize) {
    struct Node* tail = head;
    while (tail->next) tail = tail->next;
    int len = 0;
    while (tail) {
        tail = tail->prev;
        len++;
    }
    int* result = (int*)malloc(sizeof(int) * len);
    struct Node* current = head;
    for (int i = 0; i < len; i++) {
        result[i] = current->val;
        current = current->next;
    }
    *returnSize = len;
    return result;
}

三、重复字符串匹配

题目概述

判断字符串a重复多次后是否包含字符串b。

解法思路

使用KMP算法结合数学计算优化实现,避免实际拼接字符串。时间复杂度为O(a + b)。

int kmpSearch(char* text, int textLen, char* pattern, int patternLen) {
    int* pi = (int*)malloc(sizeof(int) * patternLen);
    pi[0] = 0;
    for (int i = 1; i < patternLen; i++) {
        int j = pi[i - 1];
        while (j > 0 && pattern[i] != pattern[j]) {
            j = pi[j - 1];
        }
        if (pattern[i] == pattern[j]) {
            j++;
        }
        pi[i] = j;
    }
    int j = 0;
    for (int i = 0; i < textLen; i++) {
        while (j > 0 && text[i] != pattern[j]) {
            j = pi[j - 1];
        }
        if (text[i] == pattern[j]) {
            j++;
        }
        if (j == patternLen) {
            return i - patternLen + 1;
        }
    }
    free(pi);
    return -1;
}

int minRepeats(char* a, char* b) {
    int aLen = strlen(a), bLen = strlen(b);
    if (bLen == 0) return 0;
    int pos = kmpSearch(a, aLen, b, bLen);
    if (pos == -1) return -1;
    if (aLen - pos >= bLen) return 1;
    return (bLen + pos - aLen - 1) / aLen + 2;
}

四、下一个更大元素

题目概述

寻找数组中每个元素右边第一个比它大的元素。

解法思路

使用哈希表和单调栈实现,时间复杂度为O(n)。

int* nextGreater(int* nums, int size, int* returnSize) {
    *returnSize = size;
    int* result = (int*)malloc(sizeof(int) * size);
    memset(result, -1, sizeof(int) * size);
    int* hash = (int*)malloc(sizeof(int) * (size + 1));
    memset(hash, -1, sizeof(int) * (size + 1));
    for (int i = 0; i < size; i++) {
        hash[nums[i]] = i;
    }
    int* stack = (int*)malloc(sizeof(int) * size);
    int top = -1;
    for (int i = size - 1; i >= 0; i--) {
        while (top >= 0 && nums[i] >= stack[top]) {
            top--;
        }
        if (top >= 0 && hash[nums[i]] != -1) {
            result[hash[nums[i]]] = stack[top];
        }
        stack[++top] = nums[i];
    }
    free(stack);
    free(hash);
    return result;
}

五、栈实现队列

题目概述

通过两个栈实现队列的先进先出特性。

解法思路

使用两个栈分别实现入队和出队操作,时间复杂度为O(1)。

typedef struct {
    int* data;
    int size;
    int capacity;
} Stack;

Stack* stackCreate(int capacity) {
    Stack* s = (Stack*)malloc(sizeof(Stack));
    s->data = (int*)malloc(sizeof(int) * capacity);
    s->size = 0;
    s->capacity = capacity;
    return s;
}

void stackPush(Stack* s, int value) {
    if (s->size < s->capacity) {
        s->data[s->size++] = value;
    }
}

void stackPop(Stack* s) {
    if (s->size > 0) {
        s->size--;
    }
}

int stackTop(Stack* s) {
    if (s->size > 0) {
        return s->data[s->size - 1];
    }
    return -1;
}

bool stackEmpty(Stack* s) {
    return s->size == 0;
}

void stackDestroy(Stack* s) {
    free(s->data);
    free(s);
}

typedef struct {
    Stack* inStack;
    Stack* outStack;
} Queue;

Queue* queueCreate() {
    Queue* q = (Queue*)malloc(sizeof(Queue));
    q->inStack = stackCreate(100);
    q->outStack = stackCreate(100);
    return q;
}

void transfer(Queue* q) {
    while (!stackEmpty(q->inStack)) {
        stackPush(q->outStack, stackTop(q->inStack));
        stackPop(q->inStack);
    }
}

void queuePush(Queue* q, int value) {
    stackPush(q->inStack, value);
}

int queuePop(Queue* q) {
    if (stackEmpty(q->outStack)) {
        transfer(q);
    }
    if (stackEmpty(q->outStack)) {
        return -1;
    }
    int result = stackTop(q->outStack);
    stackPop(q->outStack);
    return result;
}

bool queueEmpty(Queue* q) {
    return stackEmpty(q->inStack) && stackEmpty(q->outStack);
}

void queueDestroy(Queue* q) {
    stackDestroy(q->inStack);
    stackDestroy(q->outStack);
    free(q);
}

总结

本文提供了五种典型算法题的详细解法,涵盖了从暴力解法到优化算法的完整思考过程,并附有完整的代码实现。每种解法都分析了时间复杂度,为理解算法优化提供了参考。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。