算法相关问题记录
经典时尚算法题思路
两数之和(Two Sum)
问题描述:给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。
解决方法:使用哈希表存储每个数及其索引,遍历数组,对于每个数,检查目标值减去该数的差是否在哈希表中。
反转链表(Reverse Linked List)
问题描述:反转一个单链表。
解决方法:迭代或递归。迭代时,维护三个指针:前一个节点、当前节点、下一个节点。
有效的括号(Valid Parentheses)
问题描述:给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
解决方法:使用栈,遇到左括号入栈,遇到右括号则检查栈顶是否匹配。
合并两个有序链表(Merge Two Sorted Lists)
问题描述:将两个升序链表合并为一个新的升序链表。
解决方法:递归或迭代。迭代时,比较两个链表的当前节点,将较小的节点连接到结果链表。
最大子数组和(Maximum Subarray)
问题描述:给定一个整数数组,找出一个具有最大和的连续子数组。
解决方法:动态规划(Kadane算法)。遍历数组,对于每个元素,决定是将其加入当前子数组还是开始新的子数组。
爬楼梯(Climbing Stairs)
问题描述:每次可以爬1或2个台阶,到达n阶楼梯有多少种不同方法。
解决方法:动态规划。dp[i] = dp[i-1] + dp[i-2],初始条件dp[0]=1, dp[1]=1。
二叉树的中序遍历(Binary Tree Inorder Traversal)
问题描述:给定一个二叉树,返回它的中序遍历。
解决方法:递归或使用栈迭代。
二叉树的层次遍历(Binary Tree Level Order Traversal)
问题描述:给定一个二叉树,返回其节点值的层次遍历。
解决方法:使用队列进行BFS。
最长公共子序列(Longest Common Subsequence)
问题描述:给定两个字符串,找出它们的最长公共子序列。
解决方法:动态规划。dp[i][j]表示text1[0:i]和text2[0:j]的最长公共子序列长度。
最长递增子序列(Longest Increasing Subsequence)
问题描述:给定一个整数数组,找到其中最长严格递增子序列的长度。
解决方法:动态规划(O(n^2))或贪心+二分查找(O(n log n))。
股票买卖问题(Best Time to Buy and Sell Stock)
问题描述:给定一个数组,第i个元素是第i天的股票价格,设计算法来获取最大利润。
解决方法:一次遍历,记录历史最低点,然后计算每天卖出能获得的最大利润。
打家劫舍(House Robber)
问题描述:给定一个数组,表示每个房屋的金额,不能抢劫相邻的房屋,求最大金额。
解决方法:动态规划。dp[i] = max(dp[i-1], dp[i-2] + nums[i])。
岛屿数量(Number of Islands)
问题描述:给定一个由 '1'(陆地)和 '0'(水)组成的二维网格,计算岛屿的数量。
解决方法:DFS或BFS。遍历网格,遇到陆地时进行DFS/BFS标记所有相连的陆地。
括号生成(Generate Parentheses)
问题描述:给定n对括号,生成所有有效的括号组合。
解决方法:回溯。递归时记录当前字符串以及左右括号的数量。
全排列(Permutations)
问题描述:给定一个没有重复数字的序列,返回其所有可能的全排列。
解决方法:回溯。交换元素,递归,再交换回来。
LRU缓存(LRU Cache)
问题描述:设计一个LRU缓存,支持get和put操作。
解决方法:使用哈希表+双向链表。哈希表存储键到节点的映射,双向链表维护访问顺序。
实现Trie(前缀树)(Implement Trie (Prefix Tree))
问题描述:实现一个Trie,包含insert, search, 和 startsWith操作。
解决方法:每个节点包含一个子节点数组(或哈希表)和一个标志表示是否为单词结尾。
数组中的第K个最大元素(Kth Largest Element in an Array)
问题描述:在未排序的数组中找到第k个最大的元素。
解决方法:快速选择算法(基于快速排序的分区思想)或使用堆。
滑动窗口最大值(Sliding Window Maximum)
问题描述:给定一个数组和一个滑动窗口的大小,找出所有滑动窗口里的最大值。
解决方法:使用双端队列维护一个递减序列,队列头部为当前窗口最大值。
最小路径和(Minimum Path Sum)
问题描述:给定一个包含非负整数的m x n网格,找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
解决方法:动态规划。dp[i][j] = grid[i][j] + min(dp[i-1][j], dp[i][j-1])。
以上是一些经典题目,覆盖了数组、链表、树、动态规划、回溯、堆、栈、队列等常见数据结构和算法。在准备秋招时,建议不仅理解这些题目的解法,还要能够举一反三,掌握算法思想。
数组/字符串类
两数之和
def twoSum(nums, target):hashmap = {}for i, num in enumerate(nums):complement = target - numif complement in hashmap:return [hashmap[complement], i]hashmap[num] = ireturn []
链表类
迭代和递归
# 迭代解法
def reverseList(head):prev, curr = None, headwhile curr:next_temp = curr.nextcurr.next = prevprev = currcurr = next_tempreturn prev# 递归解法
def reverseListRecursive(head):if not head or not head.next:return headnew_head = reverseListRecursive(head.next)head.next.next = headhead.next = Nonereturn new_head
二叉树的层序遍历
def levelOrder(root):if not root:return []result = []queue = collections.deque([root])while queue:level_size = len(queue)current_level = []for _ in range(level_size):node = queue.popleft()current_level.append(node.val)if node.left:queue.append(node.left)if node.right:queue.append(node.right)result.append(current_level)return result
最长递增子序列
def lengthOfLIS(nums):if not nums:return 0dp = [1] * len(nums)for i in range(1, len(nums)):for j in range(i):if nums[i] > nums[j]:dp[i] = max(dp[i], dp[j] + 1)return max(dp)
背包问题
# 0-1背包
def knapsack(weights, values, capacity):n = len(weights)dp = [[0] * (capacity + 1) for _ in range(n + 1)]for i in range(1, n + 1):for w in range(1, capacity + 1):if weights[i-1] <= w:dp[i][w] = max(dp[i-1][w], dp[i-1][w-weights[i-1]] + values[i-1])else:dp[i][w] = dp[i-1][w]return dp[n][capacity]
全排列
def permute(nums):def backtrack(path, used):if len(path) == len(nums):result.append(path[:])returnfor i in range(len(nums)):if not used[i]:used[i] = Truepath.append(nums[i])backtrack(path, used)path.pop()used[i] = Falseresult = []backtrack([], [False] * len(nums))return result
冒泡排序
def bubble_sort(arr):n = len(arr)# 进行n-1轮比较for i in range(n - 1):# 每轮将最大的元素"冒泡"到最后for j in range(n - 1 - i):if arr[j] > arr[j + 1]:# 交换相邻元素arr[j], arr[j + 1] = arr[j + 1], arr[j]return arr