每天固定两道LeetCode,先从easy难度开始,刚入手用的还是python,C语言指针结构那里还不是很熟练,感觉之前没有学好,在算法方面要多下点功夫,水滴石穿,量变将会引起质变
哈希表
第一题求两数之和用时间复杂度O(n^2)的双重循环很简单,但问题是如何将时间复杂度进一步降低?
于是我大概查了一下,用哈希表
存储已经遍历过的元素的索引,以便快速查找目标值的补数:
def two_sum (self, nums, target ): num_to_index = {} for i, num in enumerate (nums): complement = target - num if complement in num_to_index: return [num_to_index[complement], i] num_to_index[num] = i return []
enumerate函数
enumerate意思为:枚举
在Python中,enumerate
函数用于将一个可迭代对象的元素与其索引组合成一个个元组 ,然后返回这些元组组成的迭代器。当在循环中使用 enumerate
时,可以同时获取到元素的索引 和值 。
for i, num in enumerate (nums):
T13 注意字符串边界索引
出自第十三题罗马数字转整数,犯了个低级错误
for i in range (len (s)): if (roman_dict[s[i]]<roman_dict[s[i+1 ]] and i<len (s)-1 ):
这是错误的,实际上要将and
两边的逻辑判断换一下位置,因为and一旦执行到False就会停止判断而输出False,如果不换顺序会出现字符串索引越界的现象
T14 最大公共前缀
刚入手这题的时候怎么写怎么别扭,后面借鉴了GPT,它用了find()函数
def longestCommonPrefix (self, strs ): prefix = strs[0 ] for string in strs[1 :]: while string.find(prefix)!=0 and prefix: prefix=prefix[:-1 ] if not prefix: return "" return prefix
关于find
函数
find
函数是 Python 字符串方法之一,用于查找子字符串在字符串中第一次出现的位置。它的主要功能是返回子字符串在字符串中首次出现的索引
,如果没有找到子字符串,则返回 -1
text = "Hello, world!" index = text.find("world" ) print (index) index = text.find("Python" ) print (index) index = text.find("o" , 5 ) print (index) index = text.find("o" , 5 , 10 ) print (index) index = text.find("lo" ) print (index)
关于"类"
由T21“合并两个有序列表“(归并排序算法)中涉及到链表类
,关于这部分内容之前就有点没搞明白,所以系统地归纳一下
那就从头开始讲解Python中的类和方法。类 是面向对象编程的核心概念,用于创建自定义的数据类型。类定义了一组属性 和方法 ,这些属性和方法是类的实例(对象)所共享的。下面是详细的解释和示例。
基本概念
类(Class) :类是对象的蓝图或模板。通过类可以创建对象。
对象(Object) :对象是类的实例。每个对象都有类定义的属性和方法。
属性(Attribute) :属性是类中定义的变量,表示对象的状态。
方法(Method) :方法是类中定义的函数,用于操作对象的属性。
定义类
在Python中,使用 class
关键字来定义类。下面是一个简单的例子:
class Dog : def __init__ (self, name, age ): self.name = name self.age = age def bark (self ): print (f"{self.name} is barking." ) def get_age (self ): return self.age
解释
__init__
方法 :这是类的构造方法,在创建对象时自动调用。它用于初始化对象的属性。
self
参数 :self
是一个特殊的参数,指向类的实例。通过 self
可以访问类的属性 和方法 。
属性 :name
和 age
是 Dog
类的属性。
方法 :bark
和 get_age
是 Dog
类的方法。
创建对象
使用类来创建对象:
my_dog = Dog("Buddy" , 3 ) print (my_dog.name) print (my_dog.age) my_dog.bark() print (my_dog.get_age())
修改属性
可以直接访问和修改对象的属性:
my_dog.age = 4 print (my_dog.get_age())
完整示例
我们可以结合之前讲到的链表,创建一个更复杂的例子,展示如何使用类来定义和操作链表节点。
class ListNode : def __init__ (self, val=0 , next =None ): self.val = val self.next = next class LinkedList : def __init__ (self ): self.head = None def append (self, val ): new_node = ListNode(val) if self.head is None : self.head = new_node else : current = self.head while current.next : current = current.next current.next = new_node def print_list (self ): current = self.head while current: print (current.val, end=" -> " ) current = current.next print ("None" ) ll = LinkedList() ll.append(1 ) ll.append(2 ) ll.append(3 ) ll.print_list()
解释
ListNode 类 :定义了链表节点,每个节点有一个值和一个指向下一个节点的指针。
LinkedList 类 :定义了链表,包含一个头节点。
append 方法 :在链表末尾添加节点。
print_list 方法 :打印链表的所有节点。
类提供了一种组织代码的方式,使其更易于管理和扩展。
关于链表类
链表是一种数据结构,它由一组节点组成,每个节点包含一个数据域和一个指向下一个节点的指针。链表的主要类型有单向链表(单链表)和双向链表(双链表)。我们将首先介绍单链表,然后再简单介绍双链表。
单链表
基本概念
节点(Node) :链表的基本组成部分。每个节点包含数据域(存储数据)和指针域(指向下一个节点)。
头节点(Head) :链表的起始节点,通常我们用一个单独的变量来保存头节点。
尾节点(Tail) :链表的最后一个节点,其指针域指向 None
(空)。
单链表的定义
在Python中,我们可以定义一个链表节点类 ListNode
,并实现链表的一些基本操作,如插入和删除节点。
class ListNode : def __init__ (self, val=0 , next =None ): self.val = val self.next = next class LinkedList : def __init__ (self ): self.head = None def append (self, val ): new_node = ListNode(val) if self.head is None : self.head = new_node else : current = self.head while current.next : current = current.next current.next = new_node def print_list (self ): current = self.head while current: print (current.val, end=" -> " ) current = current.next print ("None" )
使用示例
ll = LinkedList() ll.append(1 ) ll.append(2 ) ll.append(3 ) ll.print_list()
常见操作
插入节点 :可以在链表头部、尾部或中间插入节点。
删除节点 :可以删除特定值的节点或指定位置的节点。
搜索节点 :可以搜索链表中是否存在特定值的节点。
链表反转 :可以反转整个链表。
链表操作实现
插入节点到头部
def prepend (self, val ): new_node = ListNode(val) new_node.next = self.head self.head = new_node
删除指定值的节点
def delete (self, val ): current = self.head if current and current.val == val: self.head = current.next return prev = None while current and current.val != val: prev = current current = current.next if current: prev.next = current.next
反转链表
def reverse (self ): prev = None current = self.head while current: next_node = current.next current.next = prev prev = current current = next_node self.head = prev
双向链表
双向链表是链表的一个扩展,每个节点不仅有指向下一个节点的指针,还有指向前一个节点的指针。
双向链表的定义
class DoublyListNode : def __init__ (self, val=0 , next =None , prev=None ): self.val = val self.next = next self.prev = prev class DoublyLinkedList : def __init__ (self ): self.head = None self.tail = None def append (self, val ): new_node = DoublyListNode(val) if self.tail is None : self.head = new_node self.tail = new_node else : self.tail.next = new_node new_node.prev = self.tail self.tail = new_node def print_list (self ): current = self.head while current: print (current.val, end=" <-> " ) current = current.next print ("None" )
使用示例
dll = DoublyLinkedList() dll.append(1 ) dll.append(2 ) dll.append(3 ) dll.print_list()