整天除了看招聘和数据分析的课程,唯一的乐趣就是刷题了,本计划昨天更新链表+树和图,由一点事耽误了;本次更新有点多,而且这类中级的题目也很简单,就不在此写解题思路了,看程序可以秒懂的。
链表
题目一:两树相加 |
内容: 给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。 您可以假设除了数字 0 之外,这两个数都不会以 0 开头。 |
程序: # Definition for singly-linked list. # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode: l3 = ListNode(0) A = l1 B = l2 C = l3 Jin = 0 while A and B: tem = A.val + B.val + Jin if tem 10: C.next = ListNode(tem) Jin = 0 else: Jin = 1 C.next = ListNode(tem % 10) A = A.next B = B.next C = C.next print(A) while A: tem = A.val + Jin if tem 10: C.next = ListNode(tem) C.next.next = A.next return l3.next else: Jin = 1 C.next = ListNode(tem % 10) A = A.next C = C.next while B: tem = B.val + Jin if tem 10: C.next = ListNode(tem) C.next.next = B.next return l3.next else: Jin = 1 C.next = ListNode(tem % 10) B = B.next C = C.next if Jin == 1: C.next = ListNode(1) return l3.nex |
题目二:奇偶链表 |
内容: 给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。 请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。 |
程序: # Definition for singly-linked list. # class ListNode: # def __init__(self, val=0, next=None): # self.val = val # self.next = next class Solution: def oddEvenList(self, head: ListNode) -> ListNode: if not head: return None l1 = ListNode() l2 = ListNode() A = l1 B = l2 cur = head tem = 1 while cur: if tem % 2 == 1: A.next = ListNode(cur.val) A = A.next else: B.next = ListNode(cur.val) B = B.next tem += 1 cur = cur.next # A = A.next # B = B.next A.next = l2.next return l1.next ##################### ##方法二 # if not head: # return None # cur = head # tem = 1 # count = 0 # New = head # while cur.next: # count += 1 # cur = cur.next # if count <= 1: # return head # while New and tem <= count + 1: # if tem % 2 != 0: # pre = New # New = New.next # tem += 1 # else: # cur.next = ListNode(New.val) # pre.next = New.next # New = pre.next # cur = cur.next # tem += 1 # return head |
问题三:相交链表 |
内容: 编写一个程序,找到两个单链表相交的起始节点。
|
本题还是很有意思的,这种题目的解题思路在于---有缘千里来相会; 送给准备过七夕的小伙伴 |
程序: # Definition for singly-linked list. # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode: """ 有缘千里来相会 """ if not headA or not headB: return None if headA == headB: return headB A = headA B = headB while A != B: if not A: A = headB else: A = A.next if not B: B = headA else: B = B.next if A: return A else: return A |
树和图
问题一:二叉树的中序遍历 |
内容: 给定一个二叉树,返回它的中序 遍历。 |
程序: # Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: def inorderTraversal(self, root: TreeNode) -> List[int]: self.res = [] def func(root): if not root: return func(root.left) self.res.append(root.val) func(root.right) func(root) return self.res |
问题二:二叉树的锯齿形层次遍历 |
内容: 给定一个二叉树,返回其节点值的锯齿形层次遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。 |
程序: # Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]: res = [] if not root: return res queue = [root] A = 0 while queue: tem = [] r = [] for cur in queue: r.append(cur.val) if cur.right: tem.append(cur.right) if cur.left: tem.append(cur.left) if A % 2 == 1: res.append(r) else: res.append(r[::-1]) A += 1 queue = tem return res |
问题三:从前序与中序遍历构造二叉树 |
内容: 根据一棵树的前序遍历与中序遍历构造二叉树。 |
程序: # Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode: if not preorder: return res = TreeNode(preorder[0]) idex = inorder.index(preorder[0]) res.left = self.buildTree(preorder[1:idex+1], inorder[:idex]) res.right = self.buildTree(preorder[idex+1:],inorder[idex+1:]) return res |
问题四:填充每个节点的下一个右侧节点指针 |
内容: 给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点。二叉树定义如下: struct Node { int val; Node *left; Node *right; Node *next; } 填充它的每个 next 指针,让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点,则将 next 指针设置为 NULL。 初始状态下,所有 next 指针都被设置为 NULL。 |
程序: """ # Definition for a Node. class Node: def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None): self.val = val self.left = left self.right = right self.next = next """ class Solution: def connect(self, root: 'Node') -> 'Node': if not root: return queue = [root] root.next = None while queue: tem = [] for cur in queue: if cur.left: tem.append(cur.left) if len(tem) == 1: A = tem[0] else: A.next = tem[-1] A = A.next tem.append(cur.right) A.next = tem[-1] A = A.next try: A.next = None except: return root queue = tem return root |
问题五:二叉搜索树中第K小的元素 |
内容: 给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素。 |
程序: # Definition for a binary tree node. # class TreeNode: # def __init__(self, val=0, left=None, right=None): # self.val = val # self.left = left # self.right = right class Solution: def kthSmallest(self, root: TreeNode, k: int) -> int: self.res= [] def func(root): if not root: return func(root.left) # self.res.append(root.val) if len(self.res) == k: return else: self.res.append(root.val) func(root.right) func(root) return self.res[-1] |
问题六:岛屿数量 |
内容: 给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。 岛屿总是被水包围,并且每座岛屿只能由水平方向或竖直方向上相邻的陆地连接形成。 此外,你可以假设该网格的四条边均被水包围。 |
程序: class Solution: def numIslands(self, grid: List[List[str]]) -> int: def DFS(x,y,grid): grid[x][y] = 'X' if 0 <= x len(grid) and 0 <= y len(grid[0]): for i,j in [[1,0],[-1,0],[0,1],[0,-1]]: if 0 <= x+i len(grid) and 0 <= y+j len(grid[0]) and grid[x+i][y+j] == '1': DFS(x+i,y+j,grid) else: return res = 0 for i in range(len(grid)): for j in range(len(grid[0])): if grid[i][j] == '1': res += 1 DFS(i,j,grid) return res |
回溯算法
问题一:电话号码的字母组合 |
内容: 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。 给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。 |
程序: class Solution: def letterCombinations(self, digits: str) -> List[str]: if not digits: return [] dic = {'2':'abc', '3':'def', '4':'ghi', '5':'jkl', '6':'mno', '7':'pqrs', '8':'tuv', '9':'wxyz'} self.res = [] def DFS(digits,k,queue): if len(queue) == len(digits): self.res.append(queue) return if k >= len(digits): return for i in range(k,len(digits)): if len(queue)!= k: return for j in range(len(dic[digits[i]])): queue += dic[digits[i]][j] DFS(digits,k + 1,queue) if j == len(dic[digits[i]]) - 1: continue queue = queue[:-1] DFS(digits,0,'') return self.res |
问题二:括号生成 |
内容: 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。 |
程序: class Solution: def generateParenthesis(self, n: int) -> List[str]: left = 0 right = 0 self.res = [] def DFS(left,right,n,queue): if right > left: return if left > n: return if len(queue) == 2 * n : if queue not in self.res: self.res.append(queue + '') return for i in range(1,n-left+1): DFS(left +i,right,n, queue + '('*i) for j in range(1,n-right+1): DFS(left,right+j,n,queue + ')'*j ) DFS(left,right,n,'') return self.res |
问题三:全排列 |
内容: 给定一个 没有重复 数字的序列,返回其所有可能的全排列。 |
程序: class Solution: def permute(self, nums: List[int]) -> List[List[int]]: nums = sorted(nums) end = nums[::-1] res = [] while nums != end: res.append(nums+[]) for i in range(len(nums)-1,-1,-1): if i == len(nums)-1: continue else: if nums[i] 1]: for j in range(len(nums[i+1:])-1,-1,-1): if nums[i+1:][j] > nums[i]: nums[i], nums[i+1+j] = nums[i+1+j], nums[i] nums[i+1:] = sorted(nums[i+1:]) break break res.append(end) return res ############# ################ # self.res = [] # def All_sorted(nums,k): # if k == len(nums): # return # for i in range(k,len(nums)): # nums[k] ,nums[i] = nums[i], nums[k] # if nums not in self.res: # self.res.append(nums+[]) # All_sorted(nums,k+1) # nums[k],nums[i] = nums[i], nums[k] # All_sorted(nums,0) # return self.res |
问题四:子集 |
内容: 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。 说明:解集不能包含重复的子集。 |
程序: class Solution: def subsets(self, nums: List[int]) -> List[List[int]]: self.res = [] def DFS(nums,i,queue): if i >= len(nums): self.res.append(queue + []) return queue.append(nums[i]) DFS(nums,i+1,queue) queue.pop() DFS(nums,i+1,queue) DFS(nums,0,[]) return self.res |
问题五:单词搜索 |
内容: 给定一个二维网格和一个单词,找出该单词是否存在于网格中。 单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。 |
程序: class Solution: def exist(self, board: List[List[str]], word: str) -> bool: def DFS(i,j,board,visit,k): if 0 <= i len(board) and 0 <= j len(board[0]) and k <= len(word): if k == len(word): return True for x,y in [[1,0],[-1,0],[0,1],[0,-1]]: if 0 <= i+x len(board) and 0 <= j+y len(board[0]) and board[i+x][j+y] == word[k] and [x+i,j+y] not in visit: if k == len(word) - 1: return True if DFS(i+x,j+y,board,visit + [[i+x,j+y]],k+1): return True else: return False for i in range(len(board)): for j in range(len(board[0])): if board[i][j] == word[0]: visit = [[i,j]] if DFS(i,j,board,visit,1): return True return False |
排序和搜索
问题一:颜色分类 |
内容: 给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。 此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 注意: 不能使用代码库中的排序函数来解决这道题。 |
程序: class Solution: def sortColors(self, nums: List[int]) -> None: """ Do not return anything, modify nums in-place instead. """ i = 0 j = len(nums) - 1 while i if nums[i] == 0: i += 1 elif nums[i] == 1: if nums[j] == 2: j -= 1 elif nums[j] == 0: nums[i], nums[j] = nums[j], nums[i] i += 1 else: state = True for k in range(i+1,j): if nums[k] == 0 or nums[k] == 2: state = False if nums[k] == 0: nums[k], nums[i] = nums[i], nums[k] i += 1 break if nums[k] == 2: nums[k], nums[j] = nums[j], nums[k] j -= 1 break if state: break else: if nums[j] == 2: j-= 1 else: nums[i], nums[j] = nums[j], nums[i] j -= 1 |
问题二:前K个高频元素 |
内容: 给定一个非空的整数数组,返回其中出现频率前 k 高的元素。 |
程序: class Solution: def findKthLargest(self, nums: List[int], k: int) -> int: # nums = sorted(nums,reverse=True) nums = sorted(nums)[::-1] return nums[k-1] |
问题三:数组中的第K个最大元素 |
内容: 在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 |
程序: class Solution: def findKthLargest(self, nums: List[int], k: int) -> int: # nums = sorted(nums,reverse=True) nums = sorted(nums)[::-1] return nums[k-1] |
问题四:寻找峰值 |
内容: 峰值元素是指其值大于左右相邻值的元素。 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。 数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。 你可以假设 nums[-1] = nums[n] = -∞。 |
程序: class Solution: def findPeakElement(self, nums: List[int]) -> int: tem = float('inf') nums = collections.deque(nums) nums.appendleft(tem) nums.append(float('-inf')) for i in range(1,len(nums)-1): if nums[i-1] and nums[i] > nums[i+1]: return i-1 return 0 |
问题五:在排序数组中查找元素的第一个和最后一个位置 |
内容: 给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。 你的算法时间复杂度必须是 O(log n) 级别。 如果数组中不存在目标值,返回 [-1, -1]。 |
程序: class Solution: def searchRange(self, nums: List[int], target: int) -> List[int]: try: idx = nums.index(target) res = [] res.append(idx) for i in range(idx+1,len(nums)): if nums[i] !=target: res.append(i-1) return res res.append(len(nums)-1) return res except: return [-1,-1] |
问题六:合并区间 |
内容: 给出一个区间的集合,请合并所有重叠的区间。 |
程序: class Solution: def merge(self, intervals: List[List[int]]) -> List[List[int]]: if not intervals: return [] s = sorted(intervals, key = lambda x :x[0]) print(s) tem = s[0] res = [] for i in range(1,len(s)): if tem[1] 0]: res.append(tem) tem = s[i] else: if tem[1] > s[i][1]: continue else: tem[1] = s[i][1] res.append(tem) return res |
问题七:搜索旋转排序数组 |
内容: 假设按照升序排序的数组在预先未知的某个点上进行了旋转。 ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。 搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。 你可以假设数组中不存在重复的元素。 你的算法时间复杂度必须是 O(log n) 级别。 |
程序: class Solution: def search(self, nums: List[int], target: int) -> int: try: return nums.index(target) except: return -1 |
问题八:搜索二维矩阵 |
内容: 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性: 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 |
程序: class Solution: def searchMatrix(self, matrix, target): """ :type matrix: List[List[int]] :type target: int :rtype: bool """ for i in range(len(matrix)): if not matrix[i]: return False if matrix[i][-1] continue if matrix[i][0] > target: continue if target in matrix[i]: return True else: continue return False |