两数之和(day2)

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。(逆序做和,注意是链表)

示例 1:

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

示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]

示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

提示:

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

python版本

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        dummy_head = ListNode(0)  # 创建一个虚拟头节点
        current = dummy_head  # 初始化当前节点为虚拟头节点

        carry = 0  # 初始化进位为0

        while l1 or l2:
            # 获取两个链表当前节点的值,如果链表已经遍历完,则值为0
            val1 = l1.val if l1 else 0
            val2 = l2.val if l2 else 0

            # 计算当前位的和,以及进位
            total = val1 + val2 + carry
            carry = total // 10  # 更新进位
            digit = total % 10  # 当前位的值

            # 创建新节点,并将其连接到当前节点的后面
            current.next = ListNode(digit)
            current = current.next

            # 移动到下一个节点
            if l1:
                l1 = l1.next
            if l2:
                l2 = l2.next

        # 处理最后可能存在的额外进位
        if carry:
            current.next = ListNode(carry)

        return dummy_head.next  # 返回虚拟头节点的下一个节点,即相加结果的头节点

Leecode两数之和

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

提示:

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

进阶:你可以想出一个时间复杂度小于 O(n2) 的算法吗?

 时间复杂度O(n):暴力枚举

chatgpt使用Python3(哈希,时间复杂度O(n))

class Solution:
    def twoSum(self, nums, target):
        # 创建一个字典,用于存储数字和它们的索引
        num_dict = {}

        # 遍历数组
        for i, num in enumerate(nums):
            # 计算当前数字需要的补数
            complement = target - num
            # 如果补数在字典中,返回结果
            if complement in num_dict:
                return [num_dict[complement], i]
            # 否则将当前数字和索引存入字典
            num_dict[num] = i

        # 如果没有找到符合条件的数,返回空列表
        return []

得分更高

class Solution:

    def twoSum(self,nums,target):

        dict={}

        for i in range(len(nums)):

            a=target-nums[i]

            if a not in dict:

                dict[nums[i]] = i

            else:

                return [dict[target-nums[i]],i]

一些疑惑的点:

使用字典 num_dict 来存储数字和它们的索引。字典的键是数组中的数字,值是对应的索引。

还可以直接利用数组来获取某个元素的索引(当存在重复元素时,返回第一个对应元素的索引)

nums = [1, 2, 3, 4, 5, 6, 1, 9]
print nums.index(2)
print nums[::-1].index(2)

用这种方法可以判断某个元素在数组或字符串中是否只出现一次。

正序index + 逆序index = 数组或者字符串的长度-1

enumerate()函数

用于将一个可遍历的数据对象(如列表,元组或者字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。
语法
以下是 enumerate() 方法的语法:

enumerate(sequence, [start=0])

参数

sequence -- 一个序列、迭代器或其他支持迭代对象。
start -- 下标起始返回值

返回
enumerate(枚举) 对象。

C语言版本

int* twoSum(int* nums, int numsSize, int target, int* returnSize) {

    int* indices = (int*)malloc(2 * sizeof(int));

    if (indices == NULL) {

        *returnSize = 0;

        return NULL;

    }

   

    // 创建一个哈希表用于存储数字和它们的索引

    int hash[100000] = {0}; // 假设数组元素不超过 100000

   

    // 遍历数组

    for (int i = 0; i < numsSize; ++i) {

        // 计算当前数字需要的补数

        int complement = target - nums[i];

        // 如果补数在哈希表中,返回结果

        if (hash[complement] != 0) {

            indices[0] = hash[complement] - 1;

            indices[1] = i;

            *returnSize = 2;

            return indices;

        }

        // 否则将当前数字和索引存入哈希表

        hash[nums[i]] = i + 1;

    }

   

    // 如果没有找到符合条件的数,返回空指针

    *returnSize = 0;

    return NULL;

}

好的,下面是 C 语言版本的代码,以及详细的解释:

#include <stdio.h>
#include <stdlib.h>

int* two_sum(int* nums, int numsSize, int target, int* returnSize) {
    // 创建一个动态分配的整数数组,用于存储结果
    int* indices = (int*)malloc(2 * sizeof(int));
    if (indices == NULL) {
        *returnSize = 0;
        return NULL; // 内存分配失败,返回空指针
    }
    
    // 创建一个哈希表用于存储数字和它们的索引
    int hash[100000] = {0}; // 假设数组元素不超过 100000
    
    // 遍历数组
    for (int i = 0; i < numsSize; ++i) {
        // 计算当前数字需要的补数
        int complement = target - nums[i];
        // 如果补数在哈希表中,返回结果
        if (hash[complement] != 0) {
            indices[0] = hash[complement] - 1;
            indices[1] = i;
            *returnSize = 2;
            return indices;
        }
        // 否则将当前数字和索引存入哈希表
        hash[nums[i]] = i + 1;
    }
    
    // 如果没有找到符合条件的数,返回空指针
    *returnSize = 0;
    return NULL;
}

int main() {
    // 示例输入
    int nums[] = {2, 7, 11, 15};
    int target = 9;
    int numsSize = sizeof(nums) / sizeof(nums[0]);
    int returnSize;
    
    // 调用函数获取结果
    int* result = two_sum(nums, numsSize, target, &returnSize);
    if (result != NULL && returnSize == 2) {
        // 输出结果
        printf("[%d, %d]\n", result[0], result[1]);
        // 释放动态分配的内存
        free(result);
    } else {
        printf("No solution found.\n");
    }
    
    return 0;
}

1. `two_sum` 函数接收一个整数数组 `nums`、数组大小 `numsSize`、目标值 `target` 和一个指向返回数组大小的指针 `returnSize` 作为参数,并返回一个包含两个索引的动态分配的整数数组,这两个索引指向数组中相加等于目标值的两个元素。
2. 在函数中,我们首先动态分配了一个包含两个整数的数组 `indices`,用于存储结果。如果内存分配失败,我们将返回空指针。
3. 我们使用一个固定大小的哈希表 `hash` 来存储数字和它们的索引,哈希表的大小假设为 100000,这是因为题目没有给出数组的大小限制,所以我们选择一个足够大的值来保证不会出现索引溢出。
4. 我们遍历数组 `nums`,对于每个数字,我们计算它所需要的补数 `complement`,即目标值 `target` 减去当前数字。
5. 如果补数在哈希表中,那么我们找到了两个数字,它们的和等于目标值。这时,我们将找到的两个数字的索引存储到 `indices` 数组中,并返回它。
6. 如果补数不在哈希表中,我们将当前数字及其索引存入哈希表中。
7. 如果遍历完整个数组后都没有找到符合条件的数,则返回一个空指针。
8. 在 `main` 函数中,我们提供了示例输入,并调用 `two_sum` 函数获取结果。然后根据结果的长度来判断是否找到了符合条件的数,如果找到了,我们输出结果并释放动态分配的内存;否则输出提示信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值