From 1fc68b6d049670bd11cdfef603d83bea14632e7c Mon Sep 17 00:00:00 2001 From: anan <771181720@qq.com> Date: Fri, 8 Mar 2024 18:47:00 +0800 Subject: [PATCH] Site updated: 2024-03-08 18:47:00 --- 2024/03/02/LeetCode01/index.html | 11 +++-------- 2024/03/02/PAT01/index.html | 19 ++++++++----------- 2024/03/06/LeetCode02/index.html | 11 ++--------- 2024/03/07/PAT02/index.html | 22 ++++++++-------------- 2024/03/08/LeetCode03/index.html | 12 ++++-------- index.html | 6 +++--- local-search.xml | 8 ++++---- 7 files changed, 32 insertions(+), 57 deletions(-) diff --git a/2024/03/02/LeetCode01/index.html b/2024/03/02/LeetCode01/index.html index 152d408..e02cd09 100644 --- a/2024/03/02/LeetCode01/index.html +++ b/2024/03/02/LeetCode01/index.html @@ -25,7 +25,7 @@ - + @@ -225,7 +225,7 @@ - 622 字 + 625 字 @@ -291,19 +291,14 @@

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

示例 2:

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

示例 3:

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

题解

(1)暴力枚举

枚举数组中的每一个数x,寻找数组中是否存在target-x

1
2
3
4
5
6
7
8
class Solution:
def twoSum(self,nums,target):
n = len(nums)
for i in range(n):
for j in range(i+1,n):
if nums[i] + nums[j] == target:
return [i,j]
return []
-

(2)哈希表

对于数组中的每一个数x,首先查询哈希表中是否存在target-x,如果存在则返回结果,不存在就将x插入到哈希表中,保证不会让x和自己匹配。

1
2
3
4
5
6
7
8
9
10
11
class Solution:
def twoSum(self,nums,target):
hashtable = dict()
for i,num in enumerate(nums):
num2 = target - num
print(num,num2)
if num2 in hashtable:
return [i,hashtable[num2]]
hashtable[num] = i
print(hashtable)
return []
-

知识点

diff --git a/2024/03/06/LeetCode02/index.html b/2024/03/06/LeetCode02/index.html index 34b1c25..bde07ec 100644 --- a/2024/03/06/LeetCode02/index.html +++ b/2024/03/06/LeetCode02/index.html @@ -290,27 +290,19 @@

1
2
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]
-

示例 2:

1
2
输入: strs = [""]
输出: [[""]]
-

示例 3:

1
2
输入: strs = ["a"]
输出: [["a"]]
-

题解

(1)字母排序

1、首先需要理解什么是字母异位词(相同的字母不同的排列顺序组成的单词)

2、根据特征进行归类,考虑使用哈希表

3、构造单词的字符排序,作为键;分组结果,作为值

1
2
3
4
5
6
7
8
9
10
import collections
class Solution:
def groupAnagrams(self, strs):
mp = collections.defaultdict(list)

for st in strs:
key = "".join(sorted(st))
mp[key].append(st)

return list(mp.values())
-

(2)字符计数

1、观察发现,每个字符出现的次数完全相同

2、根据特征进行归类,考虑使用哈希表

3、“#1#3…#0”构造各字母出现次数的特征字符串,作为键;具有相同特征字符串的单词放在一组,作为值

官方题解

1
2
3
4
5
6
7
8
9
10
11
12
13
import collections

class Solution:
def groupAnagrams(self,strs):
mp = collections.defaultdict(list)

for st in strs:
counts = [0] *26
for ch in st:
counts[ord(ch)-ord("a")] += 1
# 需要将list转换为tuple才可以进行哈希
mp[tuple(counts)].append(st)
return list(mp.values())
-

我的解法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution(object):
def groupAnagrams(self, strs):
total_dict = {}
same_map = {}
res = []
for index,word in enumerate(strs):
word_dict = {}
for s in word:
word_dict[s] = word_dict.get(s,0) + 1
total_dict[index] = sorted(word_dict.items())
for key, val in total_dict.items():
if tuple(val) not in same_map:
same_map[tuple(val)] = [key]
else:
same_map[tuple(val)].append(key)
for tar in same_map.values():
target = [strs[i] for i in tar]
res.append(target)
return res
- - -

知识点

@@ -363,7 +355,8 @@

1
value = my_dict.get('A', 0)  # 获取键'A'的值,如果不存在则返回默认值0
  • 使用字典推导式创建字典:

    -
    1
    squares = {x: x*x for x in range(1, 6)}  # 创建包含1到5的平方的字典
  • +
    1
    squares = {x: x*x for x in range(1, 6)}  # 创建包含1到5的平方的字典
    + diff --git a/2024/03/07/PAT02/index.html b/2024/03/07/PAT02/index.html index c02c413..b7dbfdc 100644 --- a/2024/03/07/PAT02/index.html +++ b/2024/03/07/PAT02/index.html @@ -16,12 +16,12 @@ - + - + @@ -225,7 +225,7 @@ - 916 字 + 911 字 @@ -286,25 +286,19 @@

    PAT02:数字分类

    -

    2.数字分类

    题目

    给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字:
    A1 = 能被5整除的数字中所有偶数的和;

    -

    A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算n1-n2+n3-n4…;

    -

    A3 = 被5除后余2的数字的个数;

    -

    A4 = 被5除后余3的数字的平均数,精确到小数点后1位;

    -

    A5 = 被5除后余4的数字中最大数字。

    +

    2.数字分类

    题目

    给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字:
    A1 = 能被5整除的数字中所有偶数的和;

    +

    A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算n1-n2+n3-n4…;

    +

    A3 = 被5除后余2的数字的个数;

    +

    A4 = 被5除后余3的数字的平均数,精确到小数点后1位;

    +

    A5 = 被5除后余4的数字中最大数字。

    输入:每个输入包含1个测试用例。
    每个测试用例先输入一个不超过1000的正整数N。
    然后给出N个不超过1000的待分类的正整数。数字间以空格分隔。

    输出:对给定的N个正整数,按题目要求计算A1~A5并在一行中顺序输出。数字间以空格分隔,但行末不得有多余空格。若其中某一类数字不存在,则在相应位置输出“N”。

    输入例子:

    1
    13 1 2 3 4 5 6 7 8 9 10 20 16 18
    -

    输出例子:

    1
    30 11 2 9.7 9
    -

    题解

    (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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    import sys

    for line in sys.stdin:
    a1 = []
    a2 = []
    a3 = []
    a4 = []
    a5 = []
    nums = list(map(int,line.split(' ')))
    n = nums[0]
    for i in nums[1:]:
    if i % 5 == 0 and i % 2 == 0:
    a1.append(i)
    if i % 5 == 1:
    a2.append(i)
    if i % 5 == 2:
    a3.append(i)
    if i % 5 == 3:
    a4.append(i)
    if i % 5 == 4:
    a5.append(i)
    if a1:
    A1 = sum(a1)
    else:
    A1 = 'N'

    A2 = 0
    if a2:
    for i,num in enumerate(a2):
    A2 += -((-1)**(i+1)*num)
    else:
    A2 = 'N'

    if a3:
    A3 = len(a3)
    else:
    A3 = 'N'

    if a4:
    A4 = round(sum(a4) / len(a4),1)
    else:
    A4 = 'N'

    if a5:
    A5 = max(a5)
    else:
    A5 = 'N'

    print(A1,A2,A3,A4,A5,sep=' ')

    -

    (2)其他解法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    ary = list(map(int, input().split()))
    n, ary = ary[0], ary[1:]
    A1, A2, A4 = [], [], []
    A3, A5 = 0, -1
    for i in ary:
    if i % 10 == 0:
    A1.append(i)
    elif i % 5 == 1:
    A2.append(i)
    elif i % 5 == 2:
    A3 += 1
    elif i % 5 == 3:
    A4.append(i)
    elif i % 5 == 4:
    if i > A5:
    A5 = i
    A1 = str(sum(A1)) if A1 else 'N'
    A2 = str(sum(A2[::2]) - sum(A2[1::2])) if A2 else 'N'
    A3 = str(A3) if A3 else 'N'
    A4 = '{:.1f}'.format(sum(A4) / len(A4)) if A4 else 'N'
    A5 = str(A5) if A5 != -1 else 'N'
    print(' '.join((A1, A2, A3, A4, A5)))
    - - -

    知识点

    切片操作

    在Python中,对列表进行切片操作时,可以使用[start:stop:step]的形式来指定切片的开始、结束和步长。这里的start表示起始索引,stop表示结束索引(不包含该索引处的元素),step表示步长。计算交错求和的时候,可以计算奇数索引位置上的数字之和减去偶数索引位置上的数字之和。sum(A2[::2])表示求取A2列表中所有偶数索引位置上的数字之和,sum(A2[1::2])表示求取A2列表中所有奇数索引位置上的数字之和。

    diff --git a/2024/03/08/LeetCode03/index.html b/2024/03/08/LeetCode03/index.html index 40ccd2c..89f41a2 100644 --- a/2024/03/08/LeetCode03/index.html +++ b/2024/03/08/LeetCode03/index.html @@ -16,16 +16,16 @@ - + - + - + @@ -290,25 +290,21 @@

    请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

    示例 1:

    1
    2
    3
    输入:nums = [100,4,200,1,3,2]
    输出:4
    解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4
    -

    示例 2:

    1
    2
    输入:nums = [0,3,7,2,5,8,4,6,0,1]
    输出:9
    -

    题解

    (1)官方题解

    哈希表

    考虑枚举数组中的每个数x,考虑以其为起点,不断尝试寻找x+1,x+2…是否存在。假设匹配到了x+y,那么以x为起点的最长连续序列为x,x+1,x+2x+y,其长度为y+1,不断枚举并更新答案即可。

    对于匹配的过程,暴力匹配是O(n)遍历数组去看是否存在这个数,更高效的匹配是用一个哈希表存储数组中的数,查看一个数是否存在,优化到O(1)的时间复杂度。

    -

    仅仅是这样,算法时间复杂度最坏情况下还是会达到image-20240308160521269(即外层需要枚举O(n)个数,内层需要暴力匹配O(n)次),无法满足题目的要求。但仔细分析这个过程,我们会发现其中执行了很多不必要的枚举,已知有一个x,x+1,x+2x+y的连续序列,而重新从x+1,x+2x+y处开始匹配,得到的结果一定不会优于枚举x为起点的答案,因此,需要跳过。

    +

    仅仅是这样,算法时间复杂度最坏情况下还是会达到O($n^2$)(即外层需要枚举O(n)个数,内层需要暴力匹配O(n)次),无法满足题目的要求。但仔细分析这个过程,我们会发现其中执行了很多不必要的枚举,已知有一个x,x+1,x+2x+y的连续序列,而重新从x+1,x+2x+y处开始匹配,得到的结果一定不会优于枚举x为起点的答案,因此,需要跳过。

    判断是否跳过:要枚举的数x一定是在数组中不存在前驱数 x-1的。

    时间复杂度:外层循环需要O(n)的时间复杂度,只有当一个数是连续序列的第一个数的情况下才会进入内层循环,然后在内层循环中匹配连续序列中的数,因此数组中的每个数只会进入内层循环一次。根据上述分析可知,总时间复杂度为 O(n)。

    空间复杂度:O(n)。哈希表存储数组中所有的数需要 O(n)的空间。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Solution(object):
    def longestConsecutive(self,nums):
    longest_streak = 0
    num_set = set(nums)

    for num in num_set:
    if num - 1 not in num_set:
    current_num = num
    current_streak = 1

    while current_num + 1 in num_set:
    current_num += 1
    current_streak += 1

    longest_streak = max(longest_streak,current_streak)
    return longest_streak
    -

    (2)我的解法

    时间复杂度:
    排序:首先,算法中使用了排序,其时间复杂度为 O(n log n),其中 n 是数组 nums 的长度。这是因为大多数比较排序算法(如快速排序、归并排序等)的时间复杂度都是 O(n log n)。

    遍历:排序之后,算法遍历了排序后的数组一次以计算最长连续序列的长度。这个遍历的时间复杂度是 O(n),因为每个元素都被访问一次。

    因此,算法的总体时间复杂度主要由排序这一步骤决定,即 O(n log n)。虽然遍历也涉及到数组中的所有元素,但其时间复杂度 O(n) 在排序的时间复杂度 O(n log n) 面前可以忽略不计。

    空间复杂度:

    算法的空间复杂度主要取决于排序算法的空间复杂度。在 Python 中,排序通常使用 Timsort 算法,其最坏情况下的空间复杂度为 O(n)。除此之外,还使用了一个列表 res 来存储每个连续序列的长度,以及几个用于记录状态的变量(如 max_len)。因此,总体空间复杂度也是 O(n)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class Solution(object):
    def longestConsecutive(self, nums):
    if nums == []:
    return 0
    if len(nums) == 1:
    return 1
    nums = sorted(nums)
    res = []
    max_len = 1
    for i,num in enumerate(nums):
    if i<len(nums)-1:
    if nums[i+1] - num == 1:
    max_len +=1
    elif nums[i+1] == num:
    pass
    else:
    res.append(max_len)
    max_len = 1
    res.append(max_len)
    return max(res)
    -

    知识点

    使用哈希表的优势

    如果输入数组非常大,排序可能会成为性能瓶颈。与之相比,使用哈希表的方法虽然在理论上最坏情况下的时间复杂度也是 O(n),但在实际应用中往往能够更高效地解决问题,尤其是当数据量大且数组中包含大量连续序列时。

    diff --git a/index.html b/index.html index 2e86abd..fdfc2d4 100644 --- a/index.html +++ b/index.html @@ -242,7 +242,7 @@

    - 3.最长连续序列题目给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1: 123输入:nums = [100,4,200,1,3,2]输出:4解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。 示例 2: 12输入:nums = [0,3,7,2,5,8,4,6 + 3.最长连续序列题目给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1: 123输入:nums = [100,4,200,1,3,2]输出:4解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。 示例 2: 12输入:nums = [0,3,7,2,5,8,4,6,
    @@ -311,7 +311,7 @@

    - 2.数字分类题目给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字: A1 = 能被5整除的数字中所有偶数的和; A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算n1-n2+n3-n4…; A3 = 被5除后余2的数字的个数; A4 = 被5除后余3的数字的平均数,精确到小数点后1位; A5 = 被5除后余4的数字中最 + 2.数字分类题目给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字: A1 = 能被5整除的数字中所有偶数的和; A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算n1-n2+n3-n4…; A3 = 被5除后余2的数字的个数; A4 = 被5除后余3的数字的平均数,精确到小数点后1位; A5 = 被5除后余4的数字中最大数字。 输入:每个输入包含1个测试用例。每个测试
    @@ -449,7 +449,7 @@

    - 1.A+B和C题目给定区间[-231, 231]内的3个整数A、B和C,请判断A+B是否大于C。 输入:输入第1行给出正整数T(<=10),是测试用例的个数。随后给出T组测试用例,每组占一行,顺序给出A、B和C。整数间以空格分隔。 输出:对每组测试用例,在一行中输出“Case #X: true”如果A+B>C,否则输出“Case #X: false”,其中X是测试用例的编号( + 1.A+B和C题目给定区间[-231, 231]内的3个整数A、B和C,请判断A+B是否大于C。 输入:输入第1行给出正整数T(<=10),是测试用例的个数。随后给出T组测试用例,每组占一行,顺序给出A、B和C。整数间以空格分隔。 输出:对每组测试用例,在一行中输出“Case #X: true”如果A+B>C,否则输出“Case #X: false”,其中X是测试用例的编号(从1开始)
    diff --git a/local-search.xml b/local-search.xml index f80a607..3138c5f 100644 --- a/local-search.xml +++ b/local-search.xml @@ -8,7 +8,7 @@ /2024/03/08/LeetCode03/ - 3.最长连续序列

    题目

    给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

    请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

    示例 1:

    1
    2
    3
    输入:nums = [100,4,200,1,3,2]
    输出:4
    解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4

    示例 2:

    1
    2
    输入:nums = [0,3,7,2,5,8,4,6,0,1]
    输出:9

    题解

    (1)官方题解

    哈希表

    考虑枚举数组中的每个数x,考虑以其为起点,不断尝试寻找x+1,x+2…是否存在。假设匹配到了x+y,那么以x为起点的最长连续序列为x,x+1,x+2x+y,其长度为y+1,不断枚举并更新答案即可。

    对于匹配的过程,暴力匹配是O(n)遍历数组去看是否存在这个数,更高效的匹配是用一个哈希表存储数组中的数,查看一个数是否存在,优化到O(1)的时间复杂度。

    仅仅是这样,算法时间复杂度最坏情况下还是会达到image-20240308160521269(即外层需要枚举O(n)个数,内层需要暴力匹配O(n)次),无法满足题目的要求。但仔细分析这个过程,我们会发现其中执行了很多不必要的枚举,已知有一个x,x+1,x+2x+y的连续序列,而重新从x+1,x+2x+y处开始匹配,得到的结果一定不会优于枚举x为起点的答案,因此,需要跳过。

    判断是否跳过:要枚举的数x一定是在数组中不存在前驱数 x-1的。

    时间复杂度:外层循环需要O(n)的时间复杂度,只有当一个数是连续序列的第一个数的情况下才会进入内层循环,然后在内层循环中匹配连续序列中的数,因此数组中的每个数只会进入内层循环一次。根据上述分析可知,总时间复杂度为 O(n)。

    空间复杂度:O(n)。哈希表存储数组中所有的数需要 O(n)的空间。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Solution(object):
    def longestConsecutive(self,nums):
    longest_streak = 0
    num_set = set(nums)

    for num in num_set:
    if num - 1 not in num_set:
    current_num = num
    current_streak = 1

    while current_num + 1 in num_set:
    current_num += 1
    current_streak += 1

    longest_streak = max(longest_streak,current_streak)
    return longest_streak

    (2)我的解法

    时间复杂度:
    排序:首先,算法中使用了排序,其时间复杂度为 O(n log n),其中 n 是数组 nums 的长度。这是因为大多数比较排序算法(如快速排序、归并排序等)的时间复杂度都是 O(n log n)。

    遍历:排序之后,算法遍历了排序后的数组一次以计算最长连续序列的长度。这个遍历的时间复杂度是 O(n),因为每个元素都被访问一次。

    因此,算法的总体时间复杂度主要由排序这一步骤决定,即 O(n log n)。虽然遍历也涉及到数组中的所有元素,但其时间复杂度 O(n) 在排序的时间复杂度 O(n log n) 面前可以忽略不计。

    空间复杂度:

    算法的空间复杂度主要取决于排序算法的空间复杂度。在 Python 中,排序通常使用 Timsort 算法,其最坏情况下的空间复杂度为 O(n)。除此之外,还使用了一个列表 res 来存储每个连续序列的长度,以及几个用于记录状态的变量(如 max_len)。因此,总体空间复杂度也是 O(n)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class Solution(object):
    def longestConsecutive(self, nums):
    if nums == []:
    return 0
    if len(nums) == 1:
    return 1
    nums = sorted(nums)
    res = []
    max_len = 1
    for i,num in enumerate(nums):
    if i<len(nums)-1:
    if nums[i+1] - num == 1:
    max_len +=1
    elif nums[i+1] == num:
    pass
    else:
    res.append(max_len)
    max_len = 1
    res.append(max_len)
    return max(res)

    知识点

    使用哈希表的优势

    如果输入数组非常大,排序可能会成为性能瓶颈。与之相比,使用哈希表的方法虽然在理论上最坏情况下的时间复杂度也是 O(n),但在实际应用中往往能够更高效地解决问题,尤其是当数据量大且数组中包含大量连续序列时。

    集合set()方法

    set()方法在Python中用于创建一个无序且不重复的元素集合。这是一种基本的数据结构,适用于去除重复元素以及执行各种集合操作(如并集、交集、差集等)。set()可以接收一个可迭代对象作为输入,比如列表、元组、字典等,然后将其转换成一个集合。如果不提供任何参数,set()会创建一个空集合。

    • 集合中的元素必须是不可变类型(如整数、浮点数、字符串、元组),不能是可变类型(如列表、字典)。
    • 使用{}可以创建集合,但如果没有提供任何元素,Python会将其解释为一个空字典而不是空集合。因此,创建空集合必须使用set()
    • set()创建的集合是无序的,所以无法保证每次遍历集合时元素的顺序相同。
    ]]> + 3.最长连续序列

    题目

    给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

    请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

    示例 1:

    1
    2
    3
    输入:nums = [100,4,200,1,3,2]
    输出:4
    解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4

    示例 2:

    1
    2
    输入:nums = [0,3,7,2,5,8,4,6,0,1]
    输出:9

    题解

    (1)官方题解

    哈希表

    考虑枚举数组中的每个数x,考虑以其为起点,不断尝试寻找x+1,x+2…是否存在。假设匹配到了x+y,那么以x为起点的最长连续序列为x,x+1,x+2x+y,其长度为y+1,不断枚举并更新答案即可。

    对于匹配的过程,暴力匹配是O(n)遍历数组去看是否存在这个数,更高效的匹配是用一个哈希表存储数组中的数,查看一个数是否存在,优化到O(1)的时间复杂度。

    仅仅是这样,算法时间复杂度最坏情况下还是会达到O($n^2$)(即外层需要枚举O(n)个数,内层需要暴力匹配O(n)次),无法满足题目的要求。但仔细分析这个过程,我们会发现其中执行了很多不必要的枚举,已知有一个x,x+1,x+2x+y的连续序列,而重新从x+1,x+2x+y处开始匹配,得到的结果一定不会优于枚举x为起点的答案,因此,需要跳过。

    判断是否跳过:要枚举的数x一定是在数组中不存在前驱数 x-1的。

    时间复杂度:外层循环需要O(n)的时间复杂度,只有当一个数是连续序列的第一个数的情况下才会进入内层循环,然后在内层循环中匹配连续序列中的数,因此数组中的每个数只会进入内层循环一次。根据上述分析可知,总时间复杂度为 O(n)。

    空间复杂度:O(n)。哈希表存储数组中所有的数需要 O(n)的空间。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Solution(object):
    def longestConsecutive(self,nums):
    longest_streak = 0
    num_set = set(nums)

    for num in num_set:
    if num - 1 not in num_set:
    current_num = num
    current_streak = 1

    while current_num + 1 in num_set:
    current_num += 1
    current_streak += 1

    longest_streak = max(longest_streak,current_streak)
    return longest_streak

    (2)我的解法

    时间复杂度:
    排序:首先,算法中使用了排序,其时间复杂度为 O(n log n),其中 n 是数组 nums 的长度。这是因为大多数比较排序算法(如快速排序、归并排序等)的时间复杂度都是 O(n log n)。

    遍历:排序之后,算法遍历了排序后的数组一次以计算最长连续序列的长度。这个遍历的时间复杂度是 O(n),因为每个元素都被访问一次。

    因此,算法的总体时间复杂度主要由排序这一步骤决定,即 O(n log n)。虽然遍历也涉及到数组中的所有元素,但其时间复杂度 O(n) 在排序的时间复杂度 O(n log n) 面前可以忽略不计。

    空间复杂度:

    算法的空间复杂度主要取决于排序算法的空间复杂度。在 Python 中,排序通常使用 Timsort 算法,其最坏情况下的空间复杂度为 O(n)。除此之外,还使用了一个列表 res 来存储每个连续序列的长度,以及几个用于记录状态的变量(如 max_len)。因此,总体空间复杂度也是 O(n)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class Solution(object):
    def longestConsecutive(self, nums):
    if nums == []:
    return 0
    if len(nums) == 1:
    return 1
    nums = sorted(nums)
    res = []
    max_len = 1
    for i,num in enumerate(nums):
    if i<len(nums)-1:
    if nums[i+1] - num == 1:
    max_len +=1
    elif nums[i+1] == num:
    pass
    else:
    res.append(max_len)
    max_len = 1
    res.append(max_len)
    return max(res)

    知识点

    使用哈希表的优势

    如果输入数组非常大,排序可能会成为性能瓶颈。与之相比,使用哈希表的方法虽然在理论上最坏情况下的时间复杂度也是 O(n),但在实际应用中往往能够更高效地解决问题,尤其是当数据量大且数组中包含大量连续序列时。

    集合set()方法

    set()方法在Python中用于创建一个无序且不重复的元素集合。这是一种基本的数据结构,适用于去除重复元素以及执行各种集合操作(如并集、交集、差集等)。set()可以接收一个可迭代对象作为输入,比如列表、元组、字典等,然后将其转换成一个集合。如果不提供任何参数,set()会创建一个空集合。

    • 集合中的元素必须是不可变类型(如整数、浮点数、字符串、元组),不能是可变类型(如列表、字典)。
    • 使用{}可以创建集合,但如果没有提供任何元素,Python会将其解释为一个空字典而不是空集合。因此,创建空集合必须使用set()
    • set()创建的集合是无序的,所以无法保证每次遍历集合时元素的顺序相同。
    ]]>
    @@ -35,7 +35,7 @@ /2024/03/07/PAT02/ - 2.数字分类

    题目

    给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字:
    A1 = 能被5整除的数字中所有偶数的和;

    A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算n1-n2+n3-n4…;

    A3 = 被5除后余2的数字的个数;

    A4 = 被5除后余3的数字的平均数,精确到小数点后1位;

    A5 = 被5除后余4的数字中最大数字。

    输入:每个输入包含1个测试用例。
    每个测试用例先输入一个不超过1000的正整数N。
    然后给出N个不超过1000的待分类的正整数。数字间以空格分隔。

    输出:对给定的N个正整数,按题目要求计算A1~A5并在一行中顺序输出。数字间以空格分隔,但行末不得有多余空格。若其中某一类数字不存在,则在相应位置输出“N”。

    输入例子:

    1
    13 1 2 3 4 5 6 7 8 9 10 20 16 18

    输出例子:

    1
    30 11 2 9.7 9

    题解

    (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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    import sys

    for line in sys.stdin:
    a1 = []
    a2 = []
    a3 = []
    a4 = []
    a5 = []
    nums = list(map(int,line.split(' ')))
    n = nums[0]
    for i in nums[1:]:
    if i % 5 == 0 and i % 2 == 0:
    a1.append(i)
    if i % 5 == 1:
    a2.append(i)
    if i % 5 == 2:
    a3.append(i)
    if i % 5 == 3:
    a4.append(i)
    if i % 5 == 4:
    a5.append(i)
    if a1:
    A1 = sum(a1)
    else:
    A1 = 'N'

    A2 = 0
    if a2:
    for i,num in enumerate(a2):
    A2 += -((-1)**(i+1)*num)
    else:
    A2 = 'N'

    if a3:
    A3 = len(a3)
    else:
    A3 = 'N'

    if a4:
    A4 = round(sum(a4) / len(a4),1)
    else:
    A4 = 'N'

    if a5:
    A5 = max(a5)
    else:
    A5 = 'N'

    print(A1,A2,A3,A4,A5,sep=' ')

    (2)其他解法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    ary = list(map(int, input().split()))
    n, ary = ary[0], ary[1:]
    A1, A2, A4 = [], [], []
    A3, A5 = 0, -1
    for i in ary:
    if i % 10 == 0:
    A1.append(i)
    elif i % 5 == 1:
    A2.append(i)
    elif i % 5 == 2:
    A3 += 1
    elif i % 5 == 3:
    A4.append(i)
    elif i % 5 == 4:
    if i > A5:
    A5 = i
    A1 = str(sum(A1)) if A1 else 'N'
    A2 = str(sum(A2[::2]) - sum(A2[1::2])) if A2 else 'N'
    A3 = str(A3) if A3 else 'N'
    A4 = '{:.1f}'.format(sum(A4) / len(A4)) if A4 else 'N'
    A5 = str(A5) if A5 != -1 else 'N'
    print(' '.join((A1, A2, A3, A4, A5)))

    知识点

    切片操作

    在Python中,对列表进行切片操作时,可以使用[start:stop:step]的形式来指定切片的开始、结束和步长。这里的start表示起始索引,stop表示结束索引(不包含该索引处的元素),step表示步长。计算交错求和的时候,可以计算奇数索引位置上的数字之和减去偶数索引位置上的数字之和。sum(A2[::2])表示求取A2列表中所有偶数索引位置上的数字之和,sum(A2[1::2])表示求取A2列表中所有奇数索引位置上的数字之和。

    格式化字符串

    '{:.1f}' 是一个格式化字符串,它表示将要格式化的值为浮点数,并保留一位小数。这样的格式化字符串会将浮点数格式化为带有一位小数的字符串。

    • {} 表示一个占位符,用于接受要格式化的值。
    • : 表示格式说明符的开始。
    • .1 表示精度为1,即保留一位小数。
    • f 表示格式化为浮点数。

    .format() 方法用于对字符串进行格式化,它可以将指定的值插入到格式化字符串中的大括号处。

    ' '.join()sep=' '

    ' '.join() 方法的作用是将序列中的元素以指定的字符连接起来形成一个字符串。根据需要在 ' ' 中间放置任何你想要的分隔符。sep=' 'print() 函数的一个参数,用于指定多个要打印内容之间的分隔符

    ]]>
    + 2.数字分类

    题目

    给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字:
    A1 = 能被5整除的数字中所有偶数的和;

    A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算n1-n2+n3-n4…;

    A3 = 被5除后余2的数字的个数;

    A4 = 被5除后余3的数字的平均数,精确到小数点后1位;

    A5 = 被5除后余4的数字中最大数字。

    输入:每个输入包含1个测试用例。
    每个测试用例先输入一个不超过1000的正整数N。
    然后给出N个不超过1000的待分类的正整数。数字间以空格分隔。

    输出:对给定的N个正整数,按题目要求计算A1~A5并在一行中顺序输出。数字间以空格分隔,但行末不得有多余空格。若其中某一类数字不存在,则在相应位置输出“N”。

    输入例子:

    1
    13 1 2 3 4 5 6 7 8 9 10 20 16 18

    输出例子:

    1
    30 11 2 9.7 9

    题解

    (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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    import sys

    for line in sys.stdin:
    a1 = []
    a2 = []
    a3 = []
    a4 = []
    a5 = []
    nums = list(map(int,line.split(' ')))
    n = nums[0]
    for i in nums[1:]:
    if i % 5 == 0 and i % 2 == 0:
    a1.append(i)
    if i % 5 == 1:
    a2.append(i)
    if i % 5 == 2:
    a3.append(i)
    if i % 5 == 3:
    a4.append(i)
    if i % 5 == 4:
    a5.append(i)
    if a1:
    A1 = sum(a1)
    else:
    A1 = 'N'

    A2 = 0
    if a2:
    for i,num in enumerate(a2):
    A2 += -((-1)**(i+1)*num)
    else:
    A2 = 'N'

    if a3:
    A3 = len(a3)
    else:
    A3 = 'N'

    if a4:
    A4 = round(sum(a4) / len(a4),1)
    else:
    A4 = 'N'

    if a5:
    A5 = max(a5)
    else:
    A5 = 'N'

    print(A1,A2,A3,A4,A5,sep=' ')

    (2)其他解法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    ary = list(map(int, input().split()))
    n, ary = ary[0], ary[1:]
    A1, A2, A4 = [], [], []
    A3, A5 = 0, -1
    for i in ary:
    if i % 10 == 0:
    A1.append(i)
    elif i % 5 == 1:
    A2.append(i)
    elif i % 5 == 2:
    A3 += 1
    elif i % 5 == 3:
    A4.append(i)
    elif i % 5 == 4:
    if i > A5:
    A5 = i
    A1 = str(sum(A1)) if A1 else 'N'
    A2 = str(sum(A2[::2]) - sum(A2[1::2])) if A2 else 'N'
    A3 = str(A3) if A3 else 'N'
    A4 = '{:.1f}'.format(sum(A4) / len(A4)) if A4 else 'N'
    A5 = str(A5) if A5 != -1 else 'N'
    print(' '.join((A1, A2, A3, A4, A5)))

    知识点

    切片操作

    在Python中,对列表进行切片操作时,可以使用[start:stop:step]的形式来指定切片的开始、结束和步长。这里的start表示起始索引,stop表示结束索引(不包含该索引处的元素),step表示步长。计算交错求和的时候,可以计算奇数索引位置上的数字之和减去偶数索引位置上的数字之和。sum(A2[::2])表示求取A2列表中所有偶数索引位置上的数字之和,sum(A2[1::2])表示求取A2列表中所有奇数索引位置上的数字之和。

    格式化字符串

    '{:.1f}' 是一个格式化字符串,它表示将要格式化的值为浮点数,并保留一位小数。这样的格式化字符串会将浮点数格式化为带有一位小数的字符串。

    • {} 表示一个占位符,用于接受要格式化的值。
    • : 表示格式说明符的开始。
    • .1 表示精度为1,即保留一位小数。
    • f 表示格式化为浮点数。

    .format() 方法用于对字符串进行格式化,它可以将指定的值插入到格式化字符串中的大括号处。

    ' '.join()sep=' '

    ' '.join() 方法的作用是将序列中的元素以指定的字符连接起来形成一个字符串。根据需要在 ' ' 中间放置任何你想要的分隔符。sep=' 'print() 函数的一个参数,用于指定多个要打印内容之间的分隔符

    ]]>
    @@ -89,7 +89,7 @@ /2024/03/02/PAT01/ - 1.A+B和C

    题目

    给定区间[-231, 231]内的3个整数A、B和C,请判断A+B是否大于C。

    输入:输入第1行给出正整数T(<=10),是测试用例的个数。随后给出T组测试用例,每组占一行,顺序给出A、B和C。整数间以空格分隔。

    输出:对每组测试用例,在一行中输出“Case #X: true”如果A+B>C,否则输出“Case #X: false”,其中X是测试用例的编号(从1开始)。

    输入例子:

    1
    2
    3
    4
    5
    4
    1 2 3
    2 3 4
    2147483647 0 2147483646
    0 -2147483648 -2147483647

    输出例子:

    1
    2
    3
    4
    Case #1: false
    Case #2: true
    Case #3: true
    Case #4: false

    题解

    (1)我的解法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import sys

    index = 0
    for line in sys.stdin:
    index +=1
    a = line.split()
    a = [int(i) for i in a]
    if index == 1:
    pass
    else:
    print(f'Case #{index-1}: {str(a[0]+a[1]>a[2]).lower()}')

    (2)其他解法

    1
    2
    3
    4
    n = int(input())
    for i in range(n):
    a,b,c = map(int,input().split())
    print('Case #'+str((i+1))+': true' if a+b>c else 'Case #'+str((i+1))+': false')

    知识点

    • sys.stdin

    sys.stdin是Python中sys模块的一个属性,代表了标准输入流。在计算机程序中,标准输入流是一个用于接收输入数据的通道,通常情况下它是与键盘输入关联的,但也可以通过重定向或管道从文件或其他程序接收输入。

    在Python程序中,使用sys.stdin可以读取来自命令行(或任何被重定向为标准输入源的数据)的输入。sys.stdin本质上是一个文件对象,因此可以对它使用文件操作的方法,如read(), readline()readlines()等,来读取输入的数据。

    1、sys.stdin.read(): 读取并返回所有剩余的输入数据,直到遇到EOF(文件结束符)。

    2、sys.stdin.readline(): 每次调用读取一行输入,包括行尾的换行符,如果已经到达EOF,则返回一个空字符串。

    3、sys.stdin.readlines(): 读取所有剩余的输入行,并将它们作为字符串列表返回。

    for line in sys.stdin:循环会逐行读取标准输入直到EOF。这种方式特别适合处理不确定数量的输入行。

    在命令行环境中,通常可以通过Ctrl+D(在Unix/Linux/macOS系统中)或Ctrl+Z然后回车(在Windows系统中)来发送EOF信号。此外,sys.stdin也常被用于从文件中读取输入,通过命令行重定向操作,例如python script.py < inputfile.txt,这时inputfile.txt的内容会被作为标准输入传递给脚本。

    • 三元运算符

    print("Case #"+str(i+1)+": true" if b+c>d else "Case #"+str(i+1)+": false"):

    使用条件表达式(三元操作符)简化逻辑判断,而且字符串不能直接拼接整数,需要先对整数进行str()

    ]]>
    + 1.A+B和C

    题目

    给定区间[-231, 231]内的3个整数A、B和C,请判断A+B是否大于C。

    输入:输入第1行给出正整数T(<=10),是测试用例的个数。随后给出T组测试用例,每组占一行,顺序给出A、B和C。整数间以空格分隔。

    输出:对每组测试用例,在一行中输出“Case #X: true”如果A+B>C,否则输出“Case #X: false”,其中X是测试用例的编号(从1开始)。

    输入例子:

    1
    2
    3
    4
    5
    4
    1 2 3
    2 3 4
    2147483647 0 2147483646
    0 -2147483648 -2147483647

    输出例子:

    1
    2
    3
    4
    Case #1: false
    Case #2: true
    Case #3: true
    Case #4: false

    题解

    (1)我的解法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import sys

    index = 0
    for line in sys.stdin:
    index +=1
    a = line.split()
    a = [int(i) for i in a]
    if index == 1:
    pass
    else:
    print(f'Case #{index-1}: {str(a[0]+a[1]>a[2]).lower()}')

    (2)其他解法

    1
    2
    3
    4
    n = int(input())
    for i in range(n):
    a,b,c = map(int,input().split())
    print('Case #'+str((i+1))+': true' if a+b>c else 'Case #'+str((i+1))+': false')

    知识点

    • sys.stdin

    sys.stdin是Python中sys模块的一个属性,代表了标准输入流。在计算机程序中,标准输入流是一个用于接收输入数据的通道,通常情况下它是与键盘输入关联的,但也可以通过重定向或管道从文件或其他程序接收输入。

    在Python程序中,使用sys.stdin可以读取来自命令行(或任何被重定向为标准输入源的数据)的输入。sys.stdin本质上是一个文件对象,因此可以对它使用文件操作的方法,如read(), readline()readlines()等,来读取输入的数据。

    1、sys.stdin.read(): 读取并返回所有剩余的输入数据,直到遇到EOF(文件结束符)。

    2、sys.stdin.readline(): 每次调用读取一行输入,包括行尾的换行符,如果已经到达EOF,则返回一个空字符串。

    3、sys.stdin.readlines(): 读取所有剩余的输入行,并将它们作为字符串列表返回。

    for line in sys.stdin:循环会逐行读取标准输入直到EOF。这种方式特别适合处理不确定数量的输入行。

    在命令行环境中,通常可以通过Ctrl+D(在Unix/Linux/macOS系统中)或Ctrl+Z然后回车(在Windows系统中)来发送EOF信号。此外,sys.stdin也常被用于从文件中读取输入,通过命令行重定向操作,例如python script.py < inputfile.txt,这时inputfile.txt的内容会被作为标准输入传递给脚本。

    • 三元运算符

      print("Case #"+str(i+1)+": true" if b+c>d else "Case #"+str(i+1)+": false"):

      使用条件表达式(三元操作符)简化逻辑判断,而且字符串不能直接拼接整数,需要先对整数进行str()

    ]]>
    @@ -116,7 +116,7 @@ /2024/03/02/LeetCode01/ - 1. 两数之和

    题目

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

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

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

    示例 1:

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

    示例 2:

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

    示例 3:

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

    题解

    (1)暴力枚举

    枚举数组中的每一个数x,寻找数组中是否存在target-x

    1
    2
    3
    4
    5
    6
    7
    8
    class Solution:
    def twoSum(self,nums,target):
    n = len(nums)
    for i in range(n):
    for j in range(i+1,n):
    if nums[i] + nums[j] == target:
    return [i,j]
    return []

    (2)哈希表

    对于数组中的每一个数x,首先查询哈希表中是否存在target-x,如果存在则返回结果,不存在就将x插入到哈希表中,保证不会让x和自己匹配。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Solution:
    def twoSum(self,nums,target):
    hashtable = dict()
    for i,num in enumerate(nums):
    num2 = target - num
    print(num,num2)
    if num2 in hashtable:
    return [i,hashtable[num2]]
    hashtable[num] = i
    print(hashtable)
    return []

    知识点

    • 是否会报超出索引异常

      在方法一的双层for循环中,假设nums为5个元素,当for的外层循环遍历到最后一个元素时,i为4,内层循环涉及到for j in range(5,5),生成的序列将是空的。因此,for j in range(5,5) 实际上不会执行循环体内的任何代码,也不存在报错。在 Python 中,尝试访问超出数组(列表)索引的元素会引发错误。具体来说,如果尝试访问一个不存在的索引位置,Python 会抛出 IndexError 异常。

    • 时间与空间复杂度

      1、使用暴力枚举,时间复杂度为image-20240306095011380,因为需要使用两层循环来检查数组中每对不同的元素,看它们的和是否等于 target;空间复杂度为O(1),因为除了输入和输出之外,只需要有限的额外空间。

      2、使用哈希表,时间复杂度为O(n),因为只需要遍历数组一次,对于每个元素,可以在 O(1) 的时间内通过哈希表检查 target - num 是否存在;空间复杂度为O(n),因为最坏的情况下,可能需要将数组中的所有元素都存储在哈希表中。

    ]]>
    + 1. 两数之和

    题目

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

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

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

    示例 1:

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

    示例 2:

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

    示例 3:

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

    题解

    (1)暴力枚举

    枚举数组中的每一个数x,寻找数组中是否存在target-x

    1
    2
    3
    4
    5
    6
    7
    8
    class Solution:
    def twoSum(self,nums,target):
    n = len(nums)
    for i in range(n):
    for j in range(i+1,n):
    if nums[i] + nums[j] == target:
    return [i,j]
    return []

    (2)哈希表

    对于数组中的每一个数x,首先查询哈希表中是否存在target-x,如果存在则返回结果,不存在就将x插入到哈希表中,保证不会让x和自己匹配。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class Solution:
    def twoSum(self,nums,target):
    hashtable = dict()
    for i,num in enumerate(nums):
    num2 = target - num
    print(num,num2)
    if num2 in hashtable:
    return [i,hashtable[num2]]
    hashtable[num] = i
    print(hashtable)
    return []

    知识点

    • 是否会报超出索引异常

      在方法一的双层for循环中,假设nums为5个元素,当for的外层循环遍历到最后一个元素时,i为4,内层循环涉及到for j in range(5,5),生成的序列将是空的。因此,for j in range(5,5) 实际上不会执行循环体内的任何代码,也不存在报错。在 Python 中,尝试访问超出数组(列表)索引的元素会引发错误。具体来说,如果尝试访问一个不存在的索引位置,Python 会抛出 IndexError 异常。

    • 时间与空间复杂度

      1、使用暴力枚举,时间复杂度为O($n^2$),因为需要使用两层循环来检查数组中每对不同的元素,看它们的和是否等于 target;空间复杂度为O(1),因为除了输入和输出之外,只需要有限的额外空间。

      2、使用哈希表,时间复杂度为O(n),因为只需要遍历数组一次,对于每个元素,可以在 O(1) 的时间内通过哈希表检查 target - num 是否存在;空间复杂度为O(n),因为最坏的情况下,可能需要将数组中的所有元素都存储在哈希表中。

    ]]>