LeetCode题库-1~10(C语言)

1 两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。

  1. 示例1
    • 输入: nums = [2,7,11,15],target = 9
    • 输出: [0,1]
    • 解释: 因为 nums[0] + nums[1] == 9,返回[0,1]。
  2. 示例2
    • 输入: nums = [3,2,4],target = 6
    • 输出: [1,2]
  3. 示例3
    • 输入: nums = [3,3],target = 6
    • 输出: [0,1]
  4. 提示:

2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案

代码:

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* twoSum(int* nums, int numsSize, int target, int* returnSize)
{
    for (int i = 0; i < numsSize; ++i)//从nums数组中的第i个数开始
    {
        for (int j = i + 1; j < numsSize; ++j)//从第i+1个数开始向后找
        {
            if (nums[i] + nums[j] == target)//第i个数和第j个数相加得target
            {
                int *ret;//设指针变量ret
                ret = malloc(sizeof(int) * 2); //给ret分配2*4字节大小得地址空间
                ret[0] = i, ret[1] = j;//存储指针i、j
                *returnSize = 2;//空间大小为2
                return ret;//输出结果
            }
        }
    }
    *returnSize = 0;//释放内存
    return NULL;
}

2 两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

  1. 示例1
    • 输入: l1 = [2,4,3],l2 = [5,6,4]
    • 输出: [7,0,8]
    • 解释: 342 + 465 = 807.
  2. 示例2
    • 输入: l1 = [0],l2 = [0]
    • 输出: [0]
  3. 示例3
    • 输入: l1 = [9,9,9,9,9,9,9],l2 = [9,9,9,9]
    • 输出: [8,9,9,9,0,0,0,1]
  4. 提示:

每个链表中的节点数在范围[1,100]内
0 <= Node.val <= 9
题目数据保证列表表示的数字不含前导零

代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2)
{
    int val;                                    //数据
    struct ListNode *head = NULL, *tail = NULL; //头、尾节点
    int jinwei = 0;                             //进位
    while (l1 || l2)
    {
        //指针l不为空,n=l指向得节点的值;l为空,n=0。
        int n1 = l1 ? l1->val : 0;
        int n2 = l2 ? l2->val : 0;
        int sum = n1 + n2 + jinwei;
        if (!head)
        {
            head = tail = malloc(sizeof(struct ListNode)); //申请内存空间
            tail->val = sum % 10; //尾节点的值=sum的个位数
            tail->next = NULL;    //尾节点后为空
        }
        else
        {
            tail->next = malloc(sizeof(struct ListNode)); //申请内存空间
            tail->next->val = sum % 10; //尾结点的值=sum的十位数
            tail = tail->next;          //更新尾节点
            tail->next = NULL;          //尾节点后为空
        }
        jinwei = sum / 10;
        if (l1) //遍历l1到尾端
        {   l1 = l1->next;  }
        if (l2) //遍历l2到尾端
        {   l2 = l2->next;  }
    }
    if (jinwei > 0) //进位大于0,申请一个进位的节点
    {
        tail->next = malloc(sizeof(struct ListNode));
        tail->next->val = jinwei;
        tail->next->next = NULL;
    }
    return head;
}

3 无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

  1. 示例1
    • 输入: s = “abcabcbb”
    • 输出: 3
    • 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
  2. 示例2
    • 输入: s = “bbbbb”
    • 输出: 1
    • 解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
  3. 示例3
    • 输入: s = “pwwkew”
    • 输出: 3
    • 解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
    • 注意: 你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
  4. 提示:

0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成

代码:

int lengthOfLongestSubstring(char* s)
{
    int size = strlen(s); //字符串长度
    int length;           //子串长度
    int zichuan = 0;      //不重复子串初始化为0
    int flag = 0;         //标记
    for (int i = 0; i < size; i++)
    {
        for (int j = i + 1; j < size; j++)
        {
            for (int k = i; k < j; k++) //从i到j查找重复
            {
                if (s[j] == s[k]) //遇到重复字符,中断
                {
                    flag = 1;
                    break;
                }
            }
            if (flag == 1) //遇到重复字符,中断
            {
                length = j - i;
                break;
            }
        }
        if (flag == 0) //无重复字符
        {   length = size - i;  }
        flag = 0;             //还原标记
        if (length > zichuan) //更新子串
        {   zichuan = length;   }
    }
    return zichuan;
}

4 寻找两个正序数组的中位数

给定两个大小分别为 mn 的正序(从小到大)数组 nums1nums2。请你找出并返回这两个正序数组的 中位数
算法的时间复杂度应该为 O(log (m+n))

  1. 示例1
    • 输入: nums1 = [1,3], nums2 = [2]
    • 输出: 2.00000
    • 解释: 合并数组 = [1,2,3] ,中位数 2
  2. 示例2
    • 输入: nums1 = [1,2], nums2 = [3,4]
    • 输出: 2.50000
    • 解释: 合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
  3. 提示:

nums1.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m+n <= 2000
-106 <= nums1[i], nums2[i] <= 106

代码:

int cmp(const void* a, const void* b)//排序规则
{
    return *(int*)a - *(int*)b;//升序(ab换位,即降序)
}
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size)
{
    int nums[1000000];                    //合并数组
    int numsSize = nums1Size + nums2Size; //合并数组的大小
    for (int i = 0; i < nums1Size; i++) //数组1为合并数组前半部分
    {   nums[i] = nums1[i]; }
    for (int i = nums1Size; i < numsSize; i++) //数组2为合并数组后半部分
    {   nums[i] = nums2[i - nums1Size]; }
    //qsort函数——数组排序
    //数组名、元素个数、数组元素所占字节、排序原则(升序)
    qsort(nums, numsSize, sizeof(int), cmp);
    if (numsSize % 2 == 1)//合并数组中有奇数个数
    {   return (float)nums[numsSize / 2];   }
    if (numsSize % 2 == 0)//合并数组中有偶数个数
    {   return ((float)(nums[numsSize / 2] + nums[(numsSize / 2) - 1])) / 2; }
    return 0;
}

5 最长回文子串

给你一个字符串 s,找到 s 中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

  1. 示例1
    • 输入: s = “babad”
    • 输出: “bab”
    • 解释: “aba” 同样是符合题意的答案。
  2. 示例2
    • 输入: s = “cbbd”
    • 输出: “bb”
  3. 提示:

1 <= s.length <= 1000
s 仅由数字和英文字母组成

代码:

char* longestPalindrome(char* s)
{
    int length = strlen(s);
    int zichuan = 0;                 //回文子串初始化为0
    int start;                       //回文子串开始的位置
    for (int i = 0; i < length; i++) //回文子串为偶数
    {
        int left = i, right = i + 1;
        while (left >= 0 && right <= length && s[left] == s[right]) //左右指针向左右移
        {
            left--;
            right++;
        }
        if (right - left - 1 > zichuan) //更新回文子串
        {
            start = left + 1;
            zichuan = right - left - 1;
        }
    }
    for (int i = 0; i < length; i++) //回文子串为奇数
    {
        int left = i - 1, right = i + 1;
        while (left >= 0 && right <= length && s[left] == s[right]) //左右指针向左右移
        {
            left--;
            right++;
        }
        if (right - left - 1 > zichuan) //更新回文子串
        {
            start = left + 1;
            zichuan = right - left - 1;
        }
    }
    s[start + zichuan] = '\0';
    return s + start; //返回最长回文子串
}

6 Z字形变换

将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:
在这里插入图片描述
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”

  1. 示例1
    • 输入: s = “PAYPALISHIRING”, numRows = 3
    • 输出: “PAHNAPLSIIGYIR”
  2. 示例2
    • 输入: s = “PAYPALISHIRING”, numRows = 4
    • 输出: “PINALSIGYAHRPI”
    • 解释: 在这里插入图片描述
  3. 示例3
    • 输入: s = “A”, numRows = 1
    • 输出: “A”
  4. 提示:

1 <= s.length <= 1000
s 由英文字母(小写和大写)、‘,’ 和 ‘.’ 组成
1 <= numRows <= 1000

代码:

char* convert(char* s, int numRows)
{
    int num = 0;                 // a的下标顺序
    int length = strlen(s);      //字符串长度
    int cycle = 2 * numRows - 2; // numRows+(numRows-2)为一个排列变换周期
    if (numRows == 1 || numRows >= length) //行数为1或大于字符串长度,直接输出字符串
        return s;
    char* a = (char*)malloc(sizeof(char) * (length + 1)); //给指针申请内存空间
    a[length] = '\0'; //结束字符,a中存放length长个字符
    for (int i = 0; i < numRows; i++) //s的下标
    {
        for (int j = 0; j < length; j++) //行数
        {
            if (j % cycle == i || j % cycle == cycle - i) //非空字符位置满足的条件
            {
                a[num++] = s[j];
            }
        }
    }
    return a;
}

7 整数反转

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。

  1. 示例1
    • 输入: x = 123
    • 输出: 321
  2. 示例2
    • 输入: x = -123
    • 输出: -321
  3. 示例3
    • 输入: x = 120
    • 输出: 21
  4. 示例4
    • 输入: x = 0
    • 输出: 0
  5. 提示:

-231 <= x <= 231-1

代码:

int reverse(int x)
{
    int rev = 0;   //反转后的数字
    while (x != 0) // x不等于0时;x等于0,直接返回rev=0
    {
        if (rev < INT_MIN / 10 || rev > INT_MAX / 10) // rev*10+wei;反转后数字不超范围
        {
            return 0;
        }
        int wei = x % 10;     // x每次循环后的尾数
        x /= 10;              // 随着循环,取出x各个位的数
        rev = rev * 10 + wei; //更新数字
    }
    return rev;
}

8 字符串转换整数(atoi)

请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。
函数 myAtoi(string s) 的算法如下:

  1. 读入字符串并丢弃无用的前导空格
  2. 检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
  3. 读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
  4. 将前面步骤读入的这些数字转换为整数(即,“123” -> 123, “0032” -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
  5. 如果整数数超过 32 位有符号整数范围 [−231, 231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −231 ,大于 231 − 1 的整数应该被固定为 231 − 1
  6. 返回整数作为最终结果。

注意:

  • 本题中的空白字符只包括空格字符 ’ ’
  • 除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。
  1. 示例1
    • 输入: s = “42”
    • 输出: 42
    • 解释:
      第 1 步:“42”(当前没有读入字符,因为没有前导空格)
      第 2 步:“42”(当前没有读入字符,因为这里不存在 ‘-’ 或者 ‘+’)
      第 3 步:“42”(读入 “42”)解析得到整数 42 。
      由于 “42” 在范围 [-231, 231 - 1] 内,最终结果为 42 。
  2. 示例2
    • 输入: s = " -42"
    • 输出: -42
    • 解释:
      第 1 步:" -42"(读入前导空格,但忽视掉)
      第 2 步:" -42"(读入 ‘-’ 字符,所以结果应该是负数)
      第 3 步:" -42"(读入 “42”)解析得到整数 -42 。
      由于 “-42” 在范围 [-231, 231 - 1] 内,最终结果为 -42 。
  3. 示例3
    • 输入: s = “4193 with words”
    • 输出: 4193
    • 解释:
      第 1 步:“4193 with words”(当前没有读入字符,因为没有前导空格)
      第 2 步:“4193 with words”(当前没有读入字符,因为这里不存在 ‘-’ 或者 ‘+’)
      第 3 步:“4193 with words”(读入 “4193”;由于下一个字符不是一个数字,所以读入停止)
      解析得到整数 4193 。
      由于 “4193” 在范围 [-231, 231 - 1] 内,最终结果为 4193 。
  4. 提示:

0 <= s.length <= 200
s 由英文字母(大写和小写)、数字(0-9)、’ ‘、’+‘、’-’ 和 ‘.’ 组成

代码:

int myAtoi(char* s)
{
    int i = 0;
    double sum = 0;
    int flag = 0; //符号,默认为正
    while (s[i] == ' ') //丢弃前导空格
        i++;
    if (s[i] == '-') //检查符号位
    {
        flag = 1; //符号为负
        i++;
    }
    else if (s[i] == '+') //标记默认为正
        i++;
    while (s[i] >= '0' && s[i] <= '9') //读入数字时
    {
        sum += (s[i] - '0');             //转换为整型
        if (sum >= INT_MAX && flag == 0) //上限
            return INT_MAX;
        if ((0 - sum) <= INT_MIN) //下限
            return INT_MIN;
        if (s[i + 1] >= '0' && s[i + 1] <= '9')
            sum *= 10;
        i++;
    }
    if (flag == 1) //输出负数
        return (int)(-sum);
    return (int)sum;
}

9 回文数

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false
回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

  • 例如,121 是回文,而 123 不是。
  1. 示例1
    • 输入: x = 121
    • 输出: true
  2. 示例2
    • 输入: x = -121
    • 输出: false
    • 解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。
  3. 示例3
    • 输入: x = 10
    • 输出: false
    • 解释: 从右向左读, 为 01 。因此它不是一个回文数。
  4. 提示:

-231 <= x <= 231-1

代码:

bool isPalindrome(int x)
{
    int flag = x;                         //存放变量x
    int wei = 0;                          //初始化尾数
    double huiwen = 0;                       //初始化回文数
    if (x < 0 || (x % 10 == 0 && x != 0)) //负数、尾数为0的数,不是回文数
        return false;
    while (x > 0)
    {
        wei = x % 10;               // x每次循环后的尾数
        x /= 10;                    //随着循环,取出x各个位的数
        huiwen = huiwen * 10 + wei; //更新回文数
    }
    return flag == huiwen;
}

10 正则表达式匹配

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。

  • ‘.’ 匹配任意单个字符
  • ‘*’ 匹配零个或多个前面的那一个元素
    所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
  1. 示例1
    • 输入: s = “aa”, p = “a”
    • 输出: false
    • 解释: “a” 无法匹配 “aa” 整个字符串。
  2. 示例2
    • 输入: s = “aa”, p = “a*”
    • 输出: true
    • 解释: 因为 ‘*’ 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 ‘a’。因此,字符串 “aa” 可被视为 ‘a’ 重复了一次。
  3. 示例3
    • 输入: s = “ab”, p = “.*”
    • 输出: true
    • 解释: "." 表示可匹配零个或多个('‘)任意字符(’.')。
  4. 提示:

1 <= s.length <= 20
1 <= p.length <= 20
s 只包含从 a-z 的小写字母。
p 只包含从 a-z 的小写字母,以及字符 . 和 *。
保证每次出现字符 * 时,前面都匹配到有效的字符

代码:

bool isMatch(char* s, char* p)
{
    int slen = strlen(s);      //字符串s的长度
    int plen = strlen(p);      //字符串p的长度
    int f[slen + 1][plen + 1]; // s与p能否匹配
    for (int i = 0; i <= slen; i++)
    {
        for (int j = 0; j <= plen; j++)
        {
            f[0][0] = 1; // s和p都为空,一定匹配
            f[i][j] = 0; //初始化
            if (j != 0 && j != 1 && p[j - 1] == '*') // s为空,p不为空
                f[0][j] = f[0][j - 2];
        }
    }
    for (int i = 1; i <= slen; i++)
    {
        for (int j = 1; j <= plen; j++)
        {
            if (s[i - 1] == p[j - 1] || p[j - 1] == '.') // s和p匹配一个相同的小写字母
                f[i][j] = f[i - 1][j - 1];
            else if (p[j - 1] == '*') //对p的第j-1个字符匹配任意自然次数
            {
                if (s[i - 1] == p[j - 2] || p[j - 2] == '.') //匹配0次、1次、2次以上
                    f[i][j] = f[i][j - 2] || f[i - 1][j - 2] || f[i - 1][j];
                else //不匹配字符,丢弃
                    f[i][j] = f[i][j - 2];
            }
        }
    }
    return f[slen][plen];
}
  • 15
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Leetcode题库是一个包含了各种算法和数据结构问题的在线题库,供程序员练习和提升技能使用。这个题库中涵盖了大量的题目,包括但不限于图遍历、最短路径、有效的括号、字符串解码、Z字形变换、最长公共前缀、字符串相乘、颠倒字符串中的单词、比较版本号、反转字符串、压缩字符串、验证IP地址等等。它提供了java实现的leetcode解法,这些解法的代码规范,可读性良好,并且其中的解法思想并不受语言限制。通过解决这些题目,程序员可以提高自己的算法和编码能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [leetcode题库-leetcode-java:LeetcodeJava代码](https://download.csdn.net/download/weixin_38661100/19901136)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [LeetCode算法题整理(200题左右)](https://blog.csdn.net/qq_38253797/article/details/126827454)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值