LeetCode C语言版详解(1-5)

LeetCode C语言版详解(1-5)

注解全是自己手打,如果有错请指出

1 两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
    int *num = malloc(sizeof(int)*2);// 定义一个存放数组下标的数组
    for(int i = 0; i < numsSize - 1; i++)
    {
        for(int j = i + 1; j < numsSize; j++)
        {
        // 两层循环,遍历下标为i的和下标从i+1到末尾的元素相加,如果相同则返回
            if(nums[i] + nums[j] == target)
            {
                num[0] = i;
                num[1] = j;
                *returnSize = 2;
                return num;
            }
        }
    }
    return 0;// 如果遍历完return num没有被执行到,则说明没有和为目标值的那两个整数,直接return 0即可
}

2 两数相加

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2){
    struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));// 创建一个链表头,并且分配像ListNode这么大的空间
    struct ListNode* p;// 定义一个节点
    p = head;// 把这个节点的地址换成head的地址(因为链表操作需要向后移动,这样就会丢失掉开头的地址,用head来保存一下链表头的地址,这样就不会丢失掉)
    int carry = 0;// 这个变量是进位标记
    for(;l1&&l2; l1 = l1->next, l2 = l2->next)// 第一个循环是l1和l2都有值的时候一同相加的情况
    {
        p->next = (struct ListNode*)malloc(sizeof(struct ListNode));// 先定义下一个节点
        p = p->next; // 并且把p节点换成下一个节点的地址
        p->val = (l1->val + l2->val + carry) % 10;// 注意看题目中的注释,这个结构体重存放值的是int型的val变量,所以p指向val,并且将l1和l2中的值相加取余10,这样这一个节点的值就确定下来了
        carry = (l1->val + l2->val + carry) / 10;// 进位标志用除10
    }
    l1 = l1 ? l1 : l2; // 判断l1和l2中哪一个没有到末尾,就将剩余的那一段的地址赋到l1中,(因为算法题,内存占用也是关键,就直接用l1当弟弟了,个人不推荐将最原始的地址给替换掉)
    for (; l1; l1 = l1 -> next)// 将剩余的值赋进去
    {
        p->next = (struct ListNode*)malloc(sizeof(struct ListNode));
        p = p->next;
        p->val = (l1->val + carry) % 10;
        carry = (l1->val + carry) / 10;
    }
    if(carry)// 这边是判断carry中有没有进位值,有就在建一个节点赋值进去,针对l1和l2长度相等的情况
    {
        p->next = (struct ListNode*)malloc(sizeof(struct ListNode));
        p = p->next;
        p->val = carry;
    }
    p->next = NULL;// 最后收尾
    p = head;
    head = head->next;
    free(p);// 将p释放掉
    return head;
}

3 无重复字符的最长子串

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

示例 1:

输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:

输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:

输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
思路:
查看了一些博客的,运用了哈希表,感觉这个很不错,主要定义了两个快慢指针,快的为start,慢的为clear。



int lengthOfLongestSubstring(char * s){
    int Hash[128] = {0};// 因为ASCII表有128个,初始化为0
    int max = 0;// 判断最长的字串长度
    int start = 0;// 比较快的指针
    int clear = 0;// 慢的指针,用来清除重复的那个值,并且将它变为零,这个需要自己草稿纸上画一下
    int length = strlen(s);
    while(clear < length && start < length)
    {
        if (Hash[s[start]] == 0)
        {
            Hash[s[start]] = 1;// 如果该字符为零,则把它变成一
            start++;// 快指针并且往前加一位
            max = (start - clear) > max ? (start - clear) : max;// 比较现在的字符串长度是否比max大,如果大就覆盖
        }
        else {
            Hash[s[clear]] = 0;// 如果判断到这个字符已经存在了,那么就将它清空一下,并且慢指针加一
            clear++;
        }
    }
    return max;
}

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

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

示例 1:

nums1 = [1, 3]
nums2 = [2]

则中位数是 2.0
示例 2:

nums1 = [1, 2]
nums2 = [3, 4]

则中位数是 (2 + 3)/2 = 2.5
(这道题我用C一直报错。。。所以用java来做了,思路也很简单)

class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int lenAll = nums1.length + nums2.length;// 获得两个数组的总和
		int i1=0,i2=0;
		int[] alls = new int[lenAll];// 定义一个合并数组
		for(int n = 0; n < lenAll ; n++ ) {
			if(i1 == nums1.length && i2 < nums2.length) {
				alls[n] = nums2[i2];
				i2++;
				continue;
			}
			if(i2 == nums2.length && i1 < nums1.length) {
				alls[n] = nums1[i1];
				i1++;
				continue;
			}
			if(nums1[i1] > nums2[i2]) {
				alls[n] = nums2[i2];
				i2++;
			}else {
				alls[n] = nums1[i1];
				i1++;
			}
		}
		// 合并完之后,判断奇偶返回中位数
		if(lenAll % 2 == 0) {
			return (alls[lenAll/2-1] + alls[lenAll/2])*1.0/2;
		}else {
			return alls[lenAll/2];
		}
    }
}

5 最长回文子串

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:

输入: “cbbd”
输出: “bb”



char * longestPalindrome(char * s){
        int len = strlen(s);
		if (len <= 1) { return s; }
		int start = 0;
		int maxlen = 0;
		//i表示中间元素下标
		for (int i = 1; i < len; i++)
		{
			//偶数长度
			int low = i - 1;
			int high = i;
			while (low >= 0 && high < len && s[low] == s[high])// 中心扩展,low和high为边界,并且回文
			{
				low--;
				high++;
			}
			if (high - low - 1 > maxlen)// 如果这次的中心扩展个数比maxlen大,则重新给maxlen赋值
			{
				maxlen = high - low - 1;
				start = low + 1;
			}
			//奇数长度
			low = i - 1; high = i + 1;
			while (low >= 0 && high < len && s[low] == s[high])
			{
				low--;
				high++;
			}
			if (high - low - 1 > maxlen)
			{
				maxlen = high - low - 1;
				start = low + 1;
			}
		}
		char *arr = (char *)malloc(sizeof(int) * (maxlen * 2));
		int i = 0;
		for (; i < maxlen; i++)
		{
			arr[i] = s[start++];
		}
		arr[i] = '\0';
		return arr;
}

  • 9
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

痴心的萝卜

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

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

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

打赏作者

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

抵扣说明:

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

余额充值