最近在看李春葆老师的数据结构教程,并且做了每一章后面的LeetCode编程题,在这里分享给大家。
1. LeetCode20——有效的括号【简单】
问题描述: 给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
class Solution:
def isValid(self, s: str) -> bool:
if not s:
return False
n = len(s)
pdic = {}
pdic['('] = ')'
pdic['{'] = '}'
pdic['['] = ']'
temp = []
for i in range(n):
if s[i] in pdic:
temp.append(s[i])
else:
if not temp:
return False
if temp[-1] in pdic and pdic[temp[-1]] == s[i]:
temp.pop()
continue
else:
temp.append(s[i])
if temp == []:
return True
else:
return False
2. LeetCode150——有效的括号逆波兰表达式求值有效的括号【中等】
题目描述:给定一个字符串数组 tokens,表示一个根据逆波兰表示法表示的算术表达式。请你计算该表达式,返回一个表示表达式值的整数。
注意:
- 有效的算符为 '+'、'-'、'*' 和 '/' 。
- 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
- 两个整数之间的除法总是 向零截断 。
- 表达式中不含除零运算。
- 输入是一个根据逆波兰表示法表示的算术表达式。
- 答案及所有中间计算结果可以用 32 位 整数表示。
遇到的问题:负数的除法
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
n = len(tokens)
number = []
ans = 0
for i in range(n):
if tokens[i] not in '+-*/':
number.append(int(tokens[i]))
else:
num1 = number.pop()
num2 = number.pop()
if tokens[i] == '+':
ans = num2 + num1
if tokens[i] == '-':
ans = num2 - num1
if tokens[i] == '*':
ans = num2 * num1
if tokens[i] == '/':
ans = int(num2 / num1)
number.append(ans)
return number[0]
3. LeetCode71——简化路径【中等】
问题描述:给定一个字符串 path ,表示指向某一文件或目录的Unix风格绝对路径 (以 '/' 开头),请你将其转化为更加简洁的规范路径。
说明:在 Unix 风格的文件系统中,一个点(.)表示当前目录本身;此外,两个点 (..) 表示将目录切换到上一级(指向父目录);两者都可以是复杂相对路径的组成部分。任意多个连续的斜杠(即,'//')都被视为单个斜杠 '/' 。 对于此问题,任何其他格式的点(例如,'...')均被视为文件/目录名称。
请注意,返回的 规范路径 必须遵循下述格式:
- 始终以斜杠 '/' 开头。
- 两个目录名之间必须只有一个斜杠 '/' 。
- 最后一个目录名(如果存在)不能 以 '/' 结尾。
- 此外,路径仅包含从根目录到目标文件或目录的路径上的目录(即,不含 '.' 或 '..')。
class Solution:
def simplifyPath(self, path: str) -> str:
Pathlist = path.split('/')
n = len(Pathlist)
ans = []
if n == 0:
return '/'
for i in range(n):
if Pathlist[i] == '' or Pathlist[i] == '.':
continue
if Pathlist[i] != '..':
ans.append('/' + Pathlist[i])
else:
if ans:
ans.pop()
if not ans:
ans = ['/']
return ''.join(ans)
4. LeetCode51——N 皇后【困难】
问题描述:按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。给你一个整数 n ,返回所有不同的 n 皇后问题 的解决方案。
每一种解法包含一个不同的 n 皇后问题 的棋子放置方案,该方案中 'Q' 和 '.' 分别代表了皇后和空位。
class Solution:
def solveNQueens(self, n: int) -> List[List[str]]:
def generateBoard():
board = []
for i in range(n):
row[queens[i]] = 'Q'
board.append(''.join(row))
row[queens[i]] = '.'
return board
def backtrack(row):
if row == n:
board = generateBoard()
ans.append(board)
else:
for i in range(n):
if i in columns or row - i in diag1 or row + i in diag2:
continue
else:
queens[row] = i
columns.add(i)
diag1.add(row - i)
diag2.add(row + i)
backtrack(row + 1)
columns.remove(i)
diag1.remove(row - i)
diag2.remove(row + i)
columns = set()
diag1 = set()
diag2 = set()
ans = []
queens = [-1] * n
row = ['.'] * n
backtrack(0)
return ans
5. LeetCode622——设计循环队列【中等】
问题描述:循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
你的实现应该支持如下操作:
- MyCircularQueue(k): 构造器,设置队列长度为 k 。
- Front: 从队首获取元素。如果队列为空,返回 -1 。
- Rear: 获取队尾元素。如果队列为空,返回 -1 。
- enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
- deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
- isEmpty(): 检查循环队列是否为空。
- isFull(): 检查循环队列是否已满。
class MyCircularQueue:
def __init__(self, k: int):
self.cqueue = []
self.front = 0
self.rear = 0
self.maxSize = k + 1
def enQueue(self, value: int) -> bool:
if not self.isFull():
self.cqueue.append(value)
self.rear = (self.rear + 1) % self.maxSize
return True
else:
return False
def deQueue(self) -> bool:
if not self.isEmpty():
self.cqueue.pop(0)
self.front = (self.front + 1) % self.maxSize
return True
else:
return False
def Front(self) -> int:
if not self.isEmpty():
return self.cqueue[0]
else:
return -1
def Rear(self) -> int:
if not self.isEmpty():
return self.cqueue[-1]
else:
return -1
def isEmpty(self) -> bool:
if self.front == self.rear:
return True
else:
return False
def isFull(self) -> bool:
if (self.rear + 1) % self.maxSize == self.front:
return True
else:
return False
6. LeetCode119——杨辉三角 II【简单】
问题描述:给定一个非负索引 rowIndex
,返回「杨辉三角」的第 rowIndex
行。在「杨辉三角」中,每个数是它左上方和右上方的数的和。
class Solution:
def getRow(self, rowIndex: int) -> List[int]:
rows = [[1]]
if rowIndex == 0:
return rows[0]
for i in range(1, rowIndex + 1):
row = [1]
if i >= 2 :
for j in range(1, i):
row.append(rows[i - 1][j - 1] + rows[i - 1][j])
row.append(1)
rows.append(row)
return rows[-1]
7. LeetCode347——前 K 个高频元素【中等】
问题描述:给你一个整数数组 nums
和一个整数k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
nums.sort()
n = len(nums)
temp = [[nums[0], 1]]
fast = 1
count = 1
while fast < n:
if nums[fast] != nums[fast - 1]:
temp[-1][1] = count
temp.append([nums[fast], 1])
count = 1
else:
count += 1
fast += 1
temp[-1][1] = count
temp.sort(key=lambda x:-x[1])
ans = []
for i in range(k):
ans.append(temp[i][0])
return ans
8. LeetCode23——合并 K 个升序链表【困难】
问题描述:给你一个链表数组,每个链表都已经按升序排列。请你将所有链表合并到一个升序链表中,返回合并后的链表。
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
if not lists:
return None
n = len(lists)
if n == 1:
return lists[0]
ans = lists[0]
for i in range(1, n):
ans = self.mergeTwoLists(ans, lists[i])
return ans
def mergeTwoLists(self, list1, list2):
if not list1:
return list2
if not list2:
return list1
if list1.val <= list2.val:
list1.next = self.mergeTwoLists(list1.next, list2)
return list1
else:
list2.next = self.mergeTwoLists(list1, list2.next)
return list2