📅  最后修改于: 2023-12-03 15:42:26.909000             🧑  作者: Mango
在程序员面试中,算法是一个非常重要的方面。有些算法是经典问题,每个应聘者都应该熟悉,而有些算法则是出现在某些公司的面试中常常被问到。以下是我们总结的面试题中的前 10 名算法。
二分查找是一种非常基本的算法。在一个有序数组中查找目标数字时,可以通过不断缩小查找范围来达到较快的查询时间复杂度。
def binary_search(lst, target):
left, right = 0, len(lst) - 1
while left <= right:
mid = (left + right) // 2
if lst[mid] == target:
return mid
elif lst[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1
快速排序是一种排序算法,通过不断将数据集分成较小的子集,再对这些子集进行排序,最终得到有序数据集的方法。
def quick_sort(lst):
if len(lst) < 2:
return lst
pivot = lst[0]
left = [x for x in lst[1:] if x < pivot]
right = [x for x in lst[1:] if x >= pivot]
return quick_sort(left) + [pivot] + quick_sort(right)
滑动窗口算法是解决一类子字符串或者子数组问题的方法。在一个字符串或者数组中,通过控制窗口的大小和移动来找到子字符串或者子数组的最优解。
def sliding_window(s, t):
left, right = 0, 0
need = Counter(t)
window = {}
valid = 0
start = 0
length = float('inf')
while right < len(s):
c = s[right]
right += 1
if c in need:
window[c] = window.get(c, 0) + 1
if window[c] == need[c]:
valid += 1
while valid == len(need):
if right - left < length:
start = left
length = right - left
d = s[left]
left += 1
if d in need:
if window[d] == need[d]:
valid -= 1
window[d] -= 1
return s[start:start+length] if length != float('inf') else ''
堆排序是一种排序算法,通过建立一个最小(或最大)堆,不断弹出堆顶元素,得到排序后的数据集的方法。
def heap_sort(lst):
def sift_down(start, end):
root = start
while True:
child = 2 * root + 1
if child > end:
break
if child + 1 <= end and lst[child] < lst[child + 1]:
child += 1
if lst[root] < lst[child]:
lst[root], lst[child] = lst[child], lst[root]
root = child
else:
break
for start in range((len(lst)-2) // 2, -1, -1):
sift_down(start, len(lst)-1)
for end in range(len(lst)-1, 0, -1):
lst[end], lst[0] = lst[0], lst[end]
sift_down(0, end - 1)
return lst
KMP 算法是一种字符串匹配算法,在主串和模式串匹配时,不需要回溯主串的已经匹配的部分,大大提高了匹配的效率。
def kmp_search(s, p):
def get_next(s):
j, k = 0, -1
next_lst = [-1] * len(s)
while j < len(s) - 1:
if k == -1 or s[k] == s[j]:
j += 1
k += 1
next_lst[j] = k
else:
k = next_lst[k]
return next_lst
i, j = 0, 0
next_lst = get_next(p)
while i < len(s) and j < len(p):
if j == -1 or s[i] == p[j]:
i += 1
j += 1
else:
j = next_lst[j]
if j == len(p):
return i - j
else:
return -1
斐波那契数列是一种非常基础的数列,该数列的每一项都是前两项的和。
def fibonacci(n):
if n in [0,1]:
return n
return fibonacci(n-1) + fibonacci(n-2)
求解最长公共前缀是字符串处理中的一个典型问题。可以通过比较每个字符串的每一位来解决这个问题。
def longest_common_prefix(strs):
if not strs:
return ''
prefix = strs[0]
for word in strs[1:]:
while not word.startswith(prefix):
prefix = prefix[:-1]
if not prefix:
return ''
return prefix
回文串是一个正着和反着读都一样的字符串,在字符串处理中比较常见。
def longest_palindrome(s):
if not s:
return ''
def helper(s, l, r):
while l >= 0 and r < len(s) and s[l] == s[r]:
l -= 1
r += 1
return s[l+1:r]
res = ''
for i in range(len(s)):
odd = helper(s, i, i)
even = helper(s, i, i+1)
if len(odd) > len(res):
res = odd
if len(even) > len(res):
res = even
return res
并查集是一种数据结构,可以快速合并和查找不相交集合的信息。
class UnionFind:
def __init__(self, n):
self.parent = list(range(n))
self.rank = [1] * n
self.count = n
def find(self, i):
if i != self.parent[i]:
self.parent[i] = self.find(self.parent[i])
return self.parent[i]
def union(self, p, q):
root_p = self.find(p)
root_q = self.find(q)
if root_p != root_q:
if self.rank[root_p] > self.rank[root_q]:
self.parent[root_q] = root_p
elif self.rank[root_p] < self.rank[root_q]:
self.parent[root_p] = root_q
else:
self.parent[root_q] = root_p
self.rank[root_p] += 1
self.count -= 1
二叉树的遍历是一个非常基础的数据结构问题。可以通过递归和迭代两种方式实现。
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def preorder_traversal(root):
res = []
def dfs(node):
if not node:
return
res.append(node.val)
dfs(node.left)
dfs(node.right)
dfs(root)
return res
def inorder_traversal(root):
res = []
def dfs(node):
if not node:
return
dfs(node.left)
res.append(node.val)
dfs(node.right)
dfs(root)
return res
def postorder_traversal(root):
res = []
def dfs(node):
if not node:
return
dfs(node.left)
dfs(node.right)
res.append(node.val)
dfs(root)
return res
以上是我们总结的面试题中的前 10 名算法。这些算法都是非常基础的算法,特别是在数据结构和算法方面,实现这些算法的过程是非常丰富和有趣的。希望对你在面试中更好的发挥和掌握这些算法有所帮助。