文章目录
1. Contains Duplicate 包含重复项
给定一个整数数组nums ,如果任何值在数组中出现多次,则返回true ,否则返回false 。
Example 1: 示例1:
Input: nums = [1, 2, 3, 3]
Output: true
解题1: 暴力法
class Solution:
def hasDuplicate(self, nums: List[int]) -> bool:
for i in range(len(nums)):
for j in range(i+1, len(nums)):
if nums[i] == nums[j]:
return True
return False
时间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
空间复杂度:
O
(
1
)
O(1)
O(1)
解题2: 排序
class Solution:
def hasDuplicate(self, nums: List[int]) -> bool:
nums.sort()
for i in range(1, len(nums)):
if nums[i] == nums[i - 1]:
return True
return False
时间复杂度:
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
空间复杂度:
O
(
1
)
或者
O
(
n
)
取决于排序算法
O(1)或者 O(n)取决于排序算法
O(1)或者O(n)取决于排序算法
解题3: 哈希集
class Solution:
def hasDuplicate(self, nums: List[int]) -> bool:
seen = set()
for num in nums:
if num in seen:
return True
seen.add(num)
return False
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
n
)
O(n)
O(n)
解题4: 哈希集长度
class Solution:
def hasDuplicate(self, nums: List[int]) -> bool:
return len(set(nums)) < len(nums)
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
n
)
O(n)
O(n)
2. Valid Anagram 有效的字谜词
给定两个字符串s和t ,如果这两个字符串是彼此的字谜,则返回true ,否则返回false 。
字谜词是一个字符串,其中包含与另一个字符串完全相同的字符,但字符的顺序可以不同。
Example 1:
Input: s = "racecar", t = "carrace"
Output: true
Example 2: 示例2:
Input: s = "jar", t = "jam"
Output: false
解题1: 使用hash的方法
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
if len(s) != len(t):
return False
counts, countt = {}, {}
for i in range(len(s)):
# 这里需要注意的是, 刚开始的时候hash表中不存在键值,直接加会出错
counts[s[i]] = 1 + counts.get(s[i], 0)
countt[t[i]] = 1 + countt.get(t[i], 0)
for c in counts:
# 这里使用get方法和上面的同理
if counts[c] != countt.get(c,0):
return False
return True
时间复杂度:o(n+m)
空间复杂度:o(1)或o(n+m)取决于排序算法
解题2: 使用排序的方法
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
if len(s) != len(t):
return False
if sorted(s) != sorted(t):
return False
return True
解题3:使用Counter计算器的方法
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
return Counter(s) == Counter(t)
3. Two Sum 两和
给定一个整数数组nums和一个整数target ,返回索引i和j使得nums[i] + nums[j] == target且i != j 。
您可以假设每个输入恰好有一对满足条件的索引i和j 。
Example 1: 示例1:
Input: nums = [3,4,5,6], target = 7
Output: [0,1]
Example 2: 示例2:
Input: nums = [4,5,6], target = 10
Output: [0,2]
解题1暴力法
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
for i in range(len(nums)-1):
for j in range(i+1, len(nums)):
if nums[i] + nums[j] == target:
return [i,j]
return []
时间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
空间复杂度:
O
(
1
)
O(1)
O(1)
解题2:使用hash表
在我们遍历到某个数值的时候,我们用总和值减去遍历的值就知道另一个值是多少,然后查看该值是否在hash表中,返回他对应的索引即可,如果不在就把遍历到是数值加入hash表中
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
prevMap = {} # val:index
for index, num in enumerate(nums):
diff = target - num
if diff in prevMap:
return [prevMap[diff], index]
prevMap[num] = index
return []
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
n
)
O(n)
O(n)
4. Valid Palindrome 有效回文
给定一个字符串s ,如果它是回文,则返回true ,否则返回false 。回文是向前和向后读相同的字符串。它也不区分大小写,并忽略所有非字母数字字符。
Example 1: 示例1:
Input: s = "Was it a car or a cat I saw?"
Output: true
Example 2: 示例2:
Input: nums = [4,5,6], target = 10
Output: [0,2]
解题1: 反转字符串
得到一个只有字母和数字的新字符串,比较反转前后是否相等
class Solution:
def isPalindrome(self, s: str) -> bool:
newStr = ""
for c in s:
if c.isalnum():
newStr += c.lower()
return newStr == newStr[::-1]
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
n
)
O(n)
O(n)
解题2: 利用双指针的方法
自己编写一个函数来判断字符是否满足条件,左指针总左往右,右指针从右往左
class Solution:
def isPalindrome(self, s: str) -> bool:
# 这里需要注意r值需要减一,因为从0开始计数
l, r = 0, len(s)-1
while l < r:
# 如果是非字母或数字,需要移动
# 这里一定要注意不要忘记l < r 这个条件
while l < r and not self.alphaNum(s[l]):
l += 1
while l < r and not self.alphaNum(s[r]):
r -= 1
if s[l].lower() != s[r].lower():
return False
l, r = l+1, r-1
return True
# 用来判断是否是大小写字母或者数字
# 因为该方法在类内部,需要用self,调用它也需要
def alphaNum(self, c):
# ord()返回一个字符对应的 Unicode 码点
return(ord('A') <= ord(c) <= ord('Z') or
ord('a') <= ord(c) <= ord('z') or
ord('0') <= ord(c) <= ord('9'))
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
1
)
O(1)
O(1)
5. Valid Parentheses 有效括号
给定一个由以下字符组成的字符串s : ‘(’ , ‘)’ , ‘{’ , ‘}’ , ‘[‘和’]’
输入字符串s有效当且仅当:
1.每个左括号都由相同类型的右括号封闭。
2.左括号按正确的顺序关闭。
3.每个右括号都有一个对应的相同类型的左括号。
如果s是有效字符串,则返回true ,否则返回false 。
Example 1: 示例1:
Input: s = "[]"
Output: true
Example 2: 示例2:
Input: s = "[(])"
Output: false
解题1: 堆栈
class Solution:
def isValid(self, s: str) -> bool:
stack = []
CloseToOpen = {
")":"(",
"]":"[",
"}":"{"
}
for c in s:
if c in CloseToOpen:
if stack and stack[-1] == CloseToOpen[c]:
stack.pop()
else:
return False
else:
stack.append(c)
return True if not stack else False
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
n
)
O(n)
O(n)
6. Binary Search 二分查找
您将获得一个由不同整数nums组成的数组(按升序排序)和一个整数target
实现一个在nums中搜索target函数。如果存在,则返回其索引,否则返回-1 。
您的解决方案必须运行在
O
(
l
o
g
n
)
O(logn)
O(logn)时间
示例1:
Input: nums = [-1,0,2,4,6,8], target = 4
Output: 3
示例2:
Input: nums = [-1,0,2,4,6,8], target = 3
Output: -1
解题1: 堆栈
class Solution:
def search(self, nums: List[int], target: int) -> int:
l, r = 0, len(nums)-1
while l <= r:
# 但实际上当数组很长的时候,这种方式会出现溢出的问题
# m = (r+l) // 2
# 这种情况就永远不会存在溢出的问题了
m = l + (r-l) // 2
if nums[m] == target:
return m
elif nums[m] > target:
r = m - 1
else:
l = m + 1
return -1
时间复杂度:
O
(
l
o
g
n
)
O(log n)
O(logn)
空间复杂度:
O
(
1
)
O(1)
O(1)
7. Reverse Linked List 反向链表
给定单链表head的开头,反转列表,并返回列表的新开头。
示例1:
Input: head = [0,1,2,3]
Output: [3,2,1,0]
示例2:
Input: head = []
Output: []
解题1: 迭代
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
# 这里的头节点就是指向了第一个元素,没有设立一个空的指针
prev,curr = None, head
while curr:
nxt = curr.next
curr.next = prev
prev = curr
curr = nxt
return prev
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
1
)
O(1)
O(1)
解题2: 递归
怎么办啊,递归还是没看懂啊
class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if not head:
return None
newHead = head
if head.next:
newHead = self.reverseList(head.next)
head.next.next = head
head.next = None
return newHead
时间复杂度:
O
(
n
)
O(n)
O(n)
空间复杂度:
O
(
n
)
O(n)
O(n)
这个B站视频讲解得非常清楚
https://www.bilibili.com/video/BV1nB4y1i7eL/?spm_id_from=333.337.search-card.all.click&vd_source=066d465b6991e4204ca82edfb173de26
8. Merge Two Sorted Linked Lists 合并两个已排序的链表
给定两个已排序链表list1和list2的头。
将两个列表合并为一个已排序链表,并返回新已排序链表的头。
新列表应由list1和list2中的节点组成。
示例1:
Input: list1 = [1,2,4], list2 = [1,3,5]
Output: [1,1,2,3,4,5]
解题1: 迭代
class Solution:
def mergeTwoLists(self, list1: ListNode, list2: ListNode) -> ListNode:
dummy = node = ListNode()
while list1 and list2:
if list1.val < list2.val:
node.next = list1
list1 = list1.next
else:
node.next = list2
list2 = list2.next
node = node.next
node.next = list1 or list2
return dummy.next
时间复杂度:
O
(
n
+
m
)
O(n+m)
O(n+m)
空间复杂度:
O
(
1
)
O(1)
O(1)