给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 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` 函数获取结果。然后根据结果的长度来判断是否找到了符合条件的数,如果找到了,我们输出结果并释放动态分配的内存;否则输出提示信息。