2024-11-06-Wed-T-数据结构与算法

1. 简单

1.1 两数之和

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

你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
示例 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) 的算法吗?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// O(n^2)
//按照距离寻找
//相邻, 间隔一位, 间隔二位, 间隔三位....
//01, 12,23,34,45,56....
//02, 13, 24, 35....
class Solution {
public int[] twoSum(int[] nums, int target) {
for(int i = 1; i < nums.length; i++){
for(int j = i; j < nums.length; j++){
if(nums[j-i] + nums[j] == target){
return new int[]{j-i, j};
}
}
}
return new int[]{0,0};
}
}


//哈希表
//注意到方法一的时间复杂度较高的原因是寻找 target - x 的时间复杂度过高。因此,我们需要一种更优秀的方法,能够快速寻找数组中是否存在目标元素。如果存在,我们需要找出它的索引。
// 使用哈希表,可以将寻找 target - x 的时间复杂度降低到从 O(N) 降低到 O(1)。
// 这样我们创建一个哈希表,对于每一个 x,我们首先查询哈希表中是否存在 target - x,然后将 x 插入到哈希表中,即可保证不会让 x 和自己匹配。
// 时间复杂度:O(N),其中 N 是数组中的元素数量。对于每一个元素 x,我们可以 O(1) 地寻找 target - x。
// 空间复杂度:O(N),其中 N 是数组中的元素数量。主要为哈希表的开销。

class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i]; // 寻找 target - x
if (map.containsKey(complement)) { // 如果存在,返回索引
return new int[] { map.get(complement), i };
}
map.put(nums[i], i); // 将 x 插入哈希表
}
throw new IllegalArgumentException("No two sum solution");
}
}

1.2 两数相加

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
示例 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode head = null, tail = null;
int carry = 0;
while (l1 != null || l2 != null) {
int n1 = l1 != null ? l1.val : 0;
int n2 = l2 != null ? l2.val : 0;
int sum = n1 + n2 + carry;
if (head == null) {
head = tail = new ListNode(sum % 10);
} else {
tail.next = new ListNode(sum % 10);
tail = tail.next;
}
carry = sum / 10;
if (l1 != null) {
l1 = l1.next;
}
if (l2 != null) {
l2 = l2.next;
}
}
if (carry > 0) {
tail.next = new ListNode(carry);
}
return head;
}
}

1.3 无重复字符的最长子串

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
示例 1:

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

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

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

提示:

0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

//滑动窗口
class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length();
if(n<=1){
return n;
}
int l = 0, r = 1;
HashSet<Character> set = new HashSet<>();
set.add(s.charAt(l));
int res = 0;
while(r<n){
while(r<n && !set.contains(s.charAt(r))){
set.add(s.charAt(r));
r++;
}
res = Math.max(res, r-l);
set.remove(s.charAt(l)); //
l++;
}
return res;
}
}


1.4 寻找两个正序数组的中位数

2. 一般

3. 困难


2024-11-06-Wed-T-数据结构与算法
http://example.com/2024/11/06/2024-11-06-Wed-T-数据结构与算法/
Author
Fei
Posted on
November 6, 2024
Licensed under