系列文章目录
前言
本博客的主要目的是在于记录leetcode的刷题历程,编程语言为python,本人也处于学习阶段,可能程序会存在一些错误或者不规范处,欢迎指正。
一、两数之和(Two Sum)
问题描述:给定一个整数数组nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
示例1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
示例2:
输入:nums = [3,2,4], target = 6
输出:[1,2]
如果允许时间复杂度为o(n^2),问题解决方案就是一个二重循环,分别比较各个元素与剩下的元素之和是否等于target,代码示例如下:
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
index = []
for i in range(0, len(nums)):
for j in range(i+1, len(nums)):
if nums[i] + nums[j] == target:
index = [i, j]
return index
上述这种方法比较容易想到,但是时间复杂度较高,我们可以采用散列表(哈希表)的方式,用空间换取时间。python中的哈希数据结构,比较常见的就是字典,我们也可以通过字典完成这道题,代码如下:
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
a_dict = dict()
for i in range(0, len(nums)):
another = target - nums[i]
if another in a_dict:
result = [a_dict[another], i]
return result
else:
a_dict[nums[i]] = i
大致思路:从前往后遍历列表,计算目标值减去自身值后的结果是否在字典中,如果在就返回这两个数的数组下标,如果不在就将其保存在字典中,字典的键值对分别对应着数组元素的值和数组下标值。
该算法的时间复杂度为o(n),主要是因为查找字典的时间花费为线性时间o(1)。python中的in操作符在不同数据结构中的时间复杂度为:
list:o(n), set:o(1), dict:o(1)
二、两数相加(Add Two Numbers)
问题描述:给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。请你将两个数相加,并以相同形式返回一个表示和的链表。
示例1:
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例2:
输入: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.python没有链表这种数据结构,需要自己实现一个伪链表类
代码如下:
class ListNode(object):
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution(object):
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
result = ListNode()
head = result
count = 0
while l1 is not None or l2 is not None:
node = ListNode()
if l1 is not None and l2 is not None:
node.val = l1.val + l2.val + count
count, node.val = self.is_ten(node.val)
result.next = node
result = node
l1 = l1.next
l2 = l2.next
continue
if l1 is not None and l2 is None:
node.val = l1.val + 0 + count
count, node.val = self.is_ten(node.val)
result.next = node
result = node
l1 = l1.next
continue
if l1 is None and l2 is not None:
node.val = l2.val + 0 + count
count, node.val = self.is_ten(node.val)
result.next = node
result = node
l2 = l2.next
continue
if count == 1:
node = ListNode(1)
result.next = node
return head.next
def is_ten(self, num):
count = 0
result = 0
if num >= 10:
count = 1
result = num - 10
else:
count = 0
result = num
return count, result
三、无重复字符的最长子串
问题描述:给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
大致思路:定义max_length用来保存最长值,max_list用来保存无重复字符的子串序列。从左到右遍历字符串,若字符没出现在max_list中,就将字符添加进去,若出现在max_list中,比较当前max_list的长度和max_length的大小,对max_length进行更新,对max_list进行切片,将包括重复字符在内的之前的字符舍弃。代码如下:
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
max_length = 0
max_list = []
for i in range(0, len(s)):
if s[i] not in max_list:
max_list.append(s[i])
else:
if max_length < len(max_list):
max_length = len(max_list)
index = max_list.index(s[i])
max_list.append(s[i])
max_list = max_list[index+1:]
if max_length < len(max_list):
max_length = len(max_list)
return max_length
注意事项:
1.单个字符情况没考虑在内,循环提前结束
2.切片操作时,获得重复字符在max_list中的下标index,将重复字符先添加到max_list中,切片时为[index+1:]