【Leecode 随笔】C语言版看了不后悔系列持续更新中。。。

在这里插入图片描述

🌈你好呀!我是 山顶风景独好
🎈欢迎踏入我的博客世界,能与您在此邂逅,真是缘分使然!😊
🌸愿您在此停留的每一刻,都沐浴在轻松愉悦的氛围中。
📖这里不仅有丰富的知识和趣味横生的内容等您来探索,更是一个自由交流的平台,期待您留下独特的思考与见解。🌟
🚀让我们一起踏上这段探索与成长的旅程,携手挖掘更多可能,共同进步!💪✨

题目一:盛最多水的容器

题目描述:

给定 n 个非负整数 a1,a2,…,an,每个数代表一个坐标点 (i, ai) 。在坐标内画 n 条垂直线,使得 i 垂直线的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴构成的容器可以容纳最多的水。

题目分析:

这是一个典型的双指针问题。我们可以使用两个指针分别指向数组的首尾,然后计算当前两个指针所构成的容器的面积。接着,我们移动指向较短线段的指针(因为容器的高度由较短的线段决定,移动较长线段的指针无法增加容器的高度,而只会减少容器的宽度),直到两个指针相遇。

解题思路:

初始化两个指针,一个指向数组的开始,另一个指向数组的末尾。
计算当前两个指针所构成的容器的面积,并更新最大面积。
移动指向较短线段的指针。
重复步骤2和3,直到两个指针相遇。
返回最大面积。

示例代码:

#include <stdio.h>  
  
// 函数声明  
int maxArea(int* height, int heightSize);  
  
int main() {  
    int height[] = {1,8,6,2,5,4,8,3,7};  
    int heightSize = sizeof(height) / sizeof(height[0]);  
    int result = maxArea(height, heightSize);  
    printf("Maximum area: %d\n", result);  
    return 0;  
}  
  
// 计算最大容器面积的函数实现  
int maxArea(int* height, int heightSize) {  
    int max_area = 0;  
    int left = 0;  
    int right = heightSize - 1;  
      
    while (left < right) {  
        // 计算当前容器的面积  
        int current_area = (right - left) * ((height[left] < height[right]) ? height[left] : height[right]);  
        // 更新最大面积  
        if (current_area > max_area) {  
            max_area = current_area;  
        }  
        // 移动指向较短线段的指针  
        if (height[left] < height[right]) {  
            left++;  
        } else {  
            right--;  
        }  
    }  
      
    return max_area;  
}

深入剖析:

该算法的时间复杂度为O(n),因为我们只遍历了数组一次。空间复杂度为O(1),因为我们只使用了常数级别的额外空间。这种双指针的技巧在处理类似问题时非常有用,特别是当问题涉及到数组或链表的两端时。

题目二:最长无重复字符的子串

题目描述:

给定一个字符串,找出其中没有重复字符的最长子串的长度。

题目分析:

这是一个滑动窗口问题。我们可以使用两个指针来定义一个窗口,窗口内的字符都是唯一的。当遇到重复字符时,我们移动左指针来缩小窗口,直到窗口内没有重复字符为止。同时,我们需要一个哈希表来记录每个字符在窗口中的位置,以便在O(1)时间内判断字符是否重复。

解题思路:

初始化两个指针(left和right)和一个哈希表(用于记录字符的位置)。
使用right指针扩展窗口,直到遇到重复字符。
当遇到重复字符时,移动left指针缩小窗口,直到窗口内没有重复字符。
在每次移动窗口后,更新最大长度。
重复步骤2-4,直到right指针到达字符串的末尾。
返回最大长度。

示例代码:

#include <stdio.h>  
#include <string.h>  
  
// 函数声明  
int lengthOfLongestSubstring(char * s);  
  
int main() {  
    char s[] = "abcabcbb";  
    int result = lengthOfLongestSubstring(s);  
    printf("Length of longest substring without repeating characters: %d\n", result);  
    return 0;  
}  
  
// 计算最长无重复字符子串长度的函数实现  
int lengthOfLongestSubstring(char * s) {  
    int n = strlen(s);  
    if (n == 0) {  
        return 0;  
    }  
      
    int max_len = 0;  
    int left = 0;  
    int right = 0;  
    int char_map[256] = { -1 }; // 假设输入字符为ASCII码  
      
    while (right < n) {  
        if (char_map[s[right]] != -1) {  
            // 遇到重复字符,移动左指针  
            left = (char_map[s[right]] + 1 > left) ? char_map[s[right]] + 1 : left;  
        }  
        // 更新字符的位置  
        char_map[s[right]] = right;  
        // 更新最大长度  
        max_len = (right - left + 1 > max_len) ? right - left + 1 : max_len;  
        // 移动右指针  
        right++;  
    }  
      
    return max_len;  
}

深入剖析:

该算法的时间复杂度为O(n),因为我们只遍历了字符串一次。空间复杂度为O(1)(如果考虑哈希表的大小为常数,因为ASCII码字符集是有限的),但实际上哈希表的大小取决于字符集的大小,对于Unicode字符集,空间复杂度会稍大一些。滑动窗口技巧在处理子串、子数组相关问题时非常有效。

题目三:合并区间

题目描述:

给出一个区间的集合,请合并所有重叠的部分。

题目分析:

这是一个排序和合并问题。首先,我们需要对区间按照起始位置进行排序。然后,我们遍历排序后的区间列表,使用一个变量来跟踪当前的合并区间。如果下一个区间的起始位置小于或等于当前合并区间的结束位置,则将它们合并;否则,将当前合并区间添加到结果列表中,并更新合并区间为下一个区间。

解题思路:

对区间按照起始位置进行排序。
初始化一个空的结果列表和一个变量来跟踪当前的合并区间。
遍历排序后的区间列表:
如果当前区间与合并区间重叠,则合并它们。
否则,将合并区间添加到结果列表中,并更新合并区间为当前区间。
将最后一个合并区间添加到结果列表中。
返回结果列表。

示例代码:

#include <stdio.h>  
#include <stdlib.h>  
  
// 区间结构体定义  
typedef struct {  
    int start;  
    int end;  
} Interval;  
  
// 比较函数,用于qsort排序  
int compare(const void *a, const void *b) {  
    Interval *intervalA = (Interval *)a;  
    Interval *intervalB = (Interval *)b;  
    return intervalA->start - intervalB->start;  
}  
  
// 合并区间的函数声明  
Interval* merge(Interval* intervals, int intervalsSize, int* returnSize);  
  
int main() {  
    Interval intervals[] = {{1, 3}, {2, 6}, {8, 10}, {15, 18}};  
    int intervalsSize = sizeof(intervals) / sizeof(intervals[0]);  
    int returnSize = 0;  
    Interval* result = merge(intervals, intervalsSize, &returnSize);  
  
    printf("Merged intervals:\n");  
    for (int i = 0; i < returnSize; i++) {  
        printf("[%d, %d] ", result[i].start, result[i].end);  
    }  
    printf("\n");  
  
    // 释放动态分配的内存  
    free(result);  
    return 0;  
}  
  
// 合并区间的函数实现  
Interval* merge(Interval* intervals, int intervalsSize, int* returnSize) {  
    if (intervalsSize == 0) {  
        *returnSize = 0;  
        return NULL;  
    }  
  
    // 按照起始位置排序区间  
    qsort(intervals, intervalsSize, sizeof(Interval), compare);  
  
    // 动态分配结果数组的内存  
    Interval* merged = (Interval*)malloc(intervalsSize * sizeof(Interval));  
    *returnSize = 0;  
  
    // 初始化当前合并区间  
    Interval current = intervals[0];  
  
    for (int i = 1; i < intervalsSize; i++) {  
        if (intervals[i].start <= current.end) {  
            // 当前区间与合并区间重叠,合并它们  
            current.end = (intervals[i].end > current.end) ? intervals[i].end : current.end;  
        } else {  
            // 当前区间与合并区间不重叠,将合并区间添加到结果列表中,并更新合并区间  
            merged[*returnSize] = current;  
            (*returnSize)++;  
            current = intervals[i];  
        }  
    }  
  
    // 添加最后一个合并区间到结果列表中  
    merged[*returnSize] = current;  
    (*returnSize)++;  
  
    return merged;  
}

深入剖析:

该算法的时间复杂度为O(n log n),其中n是区间的数量,因为我们需要对区间进行排序。空间复杂度为O(n),因为我们需要动态分配一个与区间数量相等大小的结果数组。合并区间的技巧在处理类似问题时非常有用,特别是当问题涉及到重叠区间的合并、求并集等操作时。


✨ 这就是今天要分享给大家的全部内容了,我们下期再见!😊
🏠 我在CSDN等你哦!我的主页😍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山顶风景独好

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值