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;
}