Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
CharonChui committed Oct 12, 2024
1 parent e6bd892 commit 071c628
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 34 deletions.
27 changes: 13 additions & 14 deletions JavaKnowledge/数据结构和算法/1. LeetCode_两数之和.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,28 @@
1. LeetCode_两数之和
===

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

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

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


---

示例 1
示例 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:

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]
Expand All @@ -27,9 +31,6 @@

提示:

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


Expand Down Expand Up @@ -89,11 +90,11 @@ public:

### 方法二: 哈希表

注意到方法一的时间复杂度较高的原因是寻找 target - x 的时间复杂度过高
注意到方法一的时间复杂度较高的原因是寻找target - x的时间复杂度过高

因此,我们需要一种更优秀的方法,能够快速寻找数组中是否存在目标元素。如果存在,我们需要找出它的索引。

使用哈希表,可以将寻找 target - x 的时间复杂度降低到从 O(N) 降低到 O(1)。
使用哈希表,可以将寻找target - x的时间复杂度降低到从O(N)降低到O(1)。


---
Expand All @@ -104,17 +105,15 @@ public:
- key: 存储数组里的值
- value: 存储数组的下标index

这样我们只需要通过target - nums[i]的值去Map中查找即可。
但是这样存在一个问题,就是你需要先把数组中的值都放到Map中,需要多一步循环。


这样我们只需要通过target - nums[i]的值去Map中查找即可。
但是这样存在一个问题,就是你需要先把数组中的值都放到Map中,需要多一步循环。


---

其实我们可以先创建一个Map,在Map的初始化过程中什么元素都不放。
其实我们可以先创建一个Map,在Map的初始化过程中什么元素都不放。

对于每一个 x,我们首先查询哈希表中是否存在 target - x,如果已存在就返回,如果不存在那再将 x 插入到哈希表中,即可保证不会让 x 和自己匹配
对于每一个x,我们首先查询哈希表中是否存在target-x,如果已存在就返回,如果不存在那再将x插入到哈希表中,即可保证不会让x和自己匹配

这样只需要一次循环就可以了,而且Map数组不用提前初始化,在性能和内存占用率都比较低。

Expand Down
40 changes: 20 additions & 20 deletions JavaKnowledge/数据结构和算法/2. LeetCode_两数相加.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
2. LeetCode_两数相加
2. LeetCode_两数相加
===

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

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

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


输入:l1 = [2,4,3], l2 = [5,6,4]
Expand All @@ -18,44 +18,44 @@
输出:[8,9,9,9,0,0,0,1]


提示
提示:

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



想法
想法:

我的想法是先把两个链表转成两个整数相加,然后把这个整数转成字符串再次生成链表。

这种方案是不可行的,因为链表的长度可能会很长,整数是操作不了的,例如:


方法
方法:

由于输入的两个链表都是逆序存储数字的位数的,因此两个链表中同一位置的数字可以直接相加。
- 由于输入的两个链表都是逆序存储数字的位数的,因此两个链表中同一位置的数字可以直接相加。

我们同时遍历两个链表,逐位计算它们的和,并与当前位置的进位值相加。具体而言,如果当前两个链表处相应位置的数字为 n1,n2,进位值为 carry,则它们的和为 n1+n2+carry;
- 我们同时遍历两个链表,逐位计算它们的和,并与当前位置的进位值相加。具体而言,如果当前两个链表处相应位置的数字为 n1,n2,进位值为 carry,则它们的和为 n1+n2+carry;
其中,答案链表处相应位置的数字为 (n1+n2+carry)mod10,而新的进位值为 [(n1+n2+carry) / 10]

如果两个链表的长度不同,则可以认为长度短的链表的后面有若干个 0 。
- 如果两个链表的长度不同,则可以认为长度短的链表的后面有若干个 0 。

此外,如果链表遍历结束后,有 carry>0,还需要在答案链表的后面附加一个节点,节点的值为 carry。
- 此外,如果链表遍历结束后,有carry>0,还需要在答案链表的后面附加一个节点,节点的值为 carry。




![image](https://raw.githubusercontent.com/CharonChui/Pictures/master/leetcode_2_twoaddsum.png?raw=true)


- 将链表反过来看,头结点在右侧
- 横线上的数字为进位
- 2 + 5 + 0(第一个进位默认为0) = 7
- 将链表反过来看,头结点在右侧
- 横线上的数字为进位
- 2 + 5 + 0(第一个进位默认为0) = 7

- 7 % 10得到新节点中的元素为7
- 7 / 10得到下一个进位为0
- 7 % 10得到新节点中的元素为7
- 7 / 10得到下一个进位为0


![image](https://raw.githubusercontent.com/CharonChui/Pictures/master/leetcode_2_twoaddsum_2.png?raw=true)
Expand Down Expand Up @@ -123,11 +123,11 @@ class Solution {



复杂度分析:
复杂度分析:

- 时间复杂度O(max(m,n)),其中 m 和 n 分别为两个链表的长度。我们要遍历两个链表的全部位置,而处理每个位置只需要 O(1) 的时间。
- 时间复杂度: O(max(m,n)),其中m和n分别为两个链表的长度。我们要遍历两个链表的全部位置,而处理每个位置只需要O(1)的时间。

- 空间复杂度O(1)。注意返回值不计入空间复杂度。
- 空间复杂度: O(1)。注意返回值不计入空间复杂度。


### 改进: 递归
Expand All @@ -139,7 +139,7 @@ class Solution {
}
}

public ListNode add(ListNode l1, ListNode l2, int carry) {
public ListNode add(ListNode l1, ListNode l2, int carry) {
if (l1 == null && l2 == null && carry == 0) {
return null;
}
Expand Down

0 comments on commit 071c628

Please sign in to comment.