注:本文中的题目参考自leetcode
两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
你可以按任意顺序返回答案。
解法1
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
for i in range(len(nums)):
for j in range(i+1,len(nums)):
if nums[i]+nums[j] == target:
return i,j
解法2
class Solution:
def twoSum(self, nums, target):
class Iter:
value = -1
def __init__(self, nums):
self.nums = nums
def __next__(self):
if self.value >= len(self.nums): raise StopIteration
self.value += 1
return self.value
def __iter__(self):
return self
c = Iter(nums)
num = list(c)
for i in num:
for j in num[i+1:-1]:
if nums[i] + nums[j] == target:
return i,j
两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
疑问:不明白链表、结点怎么使用类进行抽象表述
数组实现:
class Solution:
def palnum(self,num1,num2):
if len(num1) > len(num2):
for i in range(len(num1) - len(num2)):
num2.append(0)
else:
for i in range(len(num2 - len(num1))):
num1.append(0)
return num1,num2
def TwoSum(self,num1,num2):
num = []
carry = [0]
num1, num2 = self.palnum(num1, num2)
for i in range(len(num1)+1):
if i != len(num1):
sumi = num1[i] + num2[i] + carry[-1]
num.append(sumi % 10)
carry.append(sumi // 10)
else:
sumi = carry[-1]
if sumi != 0:num.append(sumi % 10)
return(num)
无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
自己的思路
思路,定义一个空列表num,遍历字符串,如果num中不存在某个字符,则追加至列表中,最后获取num的长度
解题的时候发现自己理解错了,这里寻找的子串应该是连续的字符
而且没有注意到空字符串和开头为空的字符串情况
自己的逻辑:
先找出字符串中字符种类的个数,即字符串最大子串的长度m
遍历字符串,寻找有无m长度不重复子串,否则寻找m-1长度不重复子串
class Solution:
def fnum(self,str1):
num = []
for i in str1:
if i not in num:
num.append(i)
return num
def det(self,str1):
if len(str1) == len(self.fnum(str1)) : return True
else: return False
def lengthOfLongestSubstring(self, s: str) -> int:
for m in reversed(range(1,len(self.fnum(s))+1)):
for n in range(len(s) - m + 1):
if self.det(s[n:n+m]) :
return(len(s[n:n+m]))
if s == "": return 0
链表实现
class Node:
def __init__(self, initdata):
self.data = initdata
self.next = None
def getData(self):
return self.data
def getNext(self):
return self.next
def setData(self, newdata):
self.data = newdata
def setNext(self, newnext):
self.next = newnext
class UnorderList:
def __init__(self):
self.head = None
def isEmpty(self):
return self.head == None
def add(self, item):
temp = Node(item)
temp.setNext(self.head)
self.head = temp
def pop(self):
current = self.head
if current != None:
previous = current
self.head = current.getNext()
return previous.getData()
def length(self):
current = self.head
count = 0
while current != None:
count = count + 1
current = current.getNext()
return count
def search(self, item):
current = self.head
found = False
while current != None and not found:
if current.getData() == item:
found = True
else:
current = current.getNext()
return found
def remove(self, item):
current = self.head
previous = None
found = False
while not found:
if current.getData() == item:
found = True
else:
previous = current
current = current.getNext()
if previous == None:
self.head = current.getNext()
else:
previous.setNext(current.getNext())
class Solution:
def palnum(self,num1,num2):
if len(num1) > len(num2):
for i in range(len(num1) - len(num2)):
num2.append(0)
else:
for i in range(len(num2) - len(num1)):
num1.append(0)
return num1,num2
def addTwoNumbers(self, list1:UnorderList, list2:UnorderList):
num1 = []
while(list1.isEmpty()):
num1.append(list1.pop())
num2 = []
while(list2.isEmpty()):
num2.append(list2.pop())
num = []
carry = [0]
num1, num2 = self.palnum(num1, num2)
for i in range(len(num1)+1):
if i != len(num1):
sumi = num1[i] + num2[i] + carry[-1]
num.append(sumi % 10)
carry.append(sumi // 10)
else:
sumi = carry[-1]
if sumi != 0:num.append(sumi % 10)
out = UnorderList()
while(len(num) != 0):
out.add(num.pop())
return(out)
惭愧! 纸上得来终觉浅,绝知此事要躬行!
复杂度分析
与解答相比,自己的代码中不重复子串的判断是定义了一个类似于set的列表来完成的。
使用set改进自己的代码
class Solution:
def fnum(self,str1):
return len(set(str1))
def det(self,str1):
if len(str1) == self.fnum(str1): return True
else: return False
def lengthOfLongestSubstring(self, s: str) -> int:
for m in reversed(range(1,self.fnum(s)+1)):
for n in range(len(s) - m + 1):
if self.det(s[n:n+m]) :
return(len(s[n:n+m]))
if s == "": return 0
官方解答用到了哈希集合
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# 哈希集合,记录每个字符是否出现过
occ = set()
n = len(s)
# 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
rk, ans = -1, 0
for i in range(n):
if i != 0:
# 左指针向右移动一格,移除一个字符
occ.remove(s[i - 1])
while rk + 1 < n and s[rk + 1] not in occ:
# 不断地移动右指针
occ.add(s[rk + 1])
rk += 1
# 第 i 到 rk 个字符是一个极长的无重复字符子串
ans = max(ans, rk - i + 1)
return ans
我们使用两个指针表示字符串中的某个子串(的左右边界)。其中左指针代表着上文中「枚举子串的起始位置
在每一步的操作中,我们会将左指针向右移动一格,表示 我们开始枚举下一个字符作为起始位置,然后我们可以不断地向右移动右指针,但需要保证这两个指针对应的子串中没有重复的字符。在移动结束后,这个子串就对应着 以左指针开始的,不包含重复字符的最长子串。我们记录下这个子串的长度;
在枚举结束后,我们找到的最长的子串的长度即为答案。
python 内置函数set的用法:
x = set("pwwkew")
print(x)
print(list(x))
{'e', 'w', 'k', 'p'}
['e', 'w', 'k', 'p']