python面试题六: 剑指offer
Posted qiu-hua
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python面试题六: 剑指offer相关的知识,希望对你有一定的参考价值。
面试题3 二维数组中的查找 LeetCode
题目:二维数组中,每行从左到右递增,每列从上到下递增,给出一个数,判断它是否在数组中
思路:从左下角或者右上角开始比较
def find_integer(matrix, num): """ :param matrix: [[]] :param num: int :return: bool """ if not matrix: return False rows, cols = len(matrix), len(matrix[0]) row, col = rows - 1, 0 while row >= 0 and col <= cols - 1: if matrix[row][col] == num: return True elif matrix[row][col] > num: row -= 1 else: col += 1 return False
面试题4 替换空格
题目:把字符串中的空格替换成‘20%‘
方法1:直接使用Python字符串的内置函数
‘ a b ‘.replace(‘ ‘, ‘20%‘)
面试题5 从尾到头打印单链表
方法1:使用栈,可以使用列表模拟
def print_links(links): stack = [] while links: stack.append(links.val) links = links.next while stack: print stack.pop()
面试题6 重建二叉树 LeetCode
要求:用前序和中序遍历结果构建二叉树,遍历结果中不包含重复值
思路:前序的第一个元素是根结点的值,在中序中找到该值,中序中该值的左边的元素是根结点的左子树,右边是右子树,然后递归的处理左边和右边
提示:二叉树结点,以及对二叉树的各种操作,测试代码见six.py
def construct_tree(preorder=None, inorder=None): """ 构建二叉树 """ if not preorder or not inorder: return None index = inorder.index(preorder[0]) left = inorder[0:index] right = inorder[index+1:] root = TreeNode(preorder[0]) root.left = construct_tree(preorder[1:1+len(left)], left) root.right = construct_tree(preorder[-len(right):], right) return root
面试题7 用两个栈实现队列
要求:用两个栈实现队列,分别实现入队和出队操作 思路:一个栈负责入队,另一个负责出队,出栈为空则从入栈中导入到出栈中
class MyQueue(object): def __init__(self): self.stack = [] self.stack2 = [] def push(self, val): self.stack.append(val) def pop(self): if self.stack2: return self.stack2.pop() while self.stack: self.stack2.append(self.stack.pop()) return self.stack2.pop() if self.stack2 else u‘队列为空‘
面试题8 旋转数组的最小数字
要求:把递增数组的前面部分数字移到队尾,求数组中的最小值,例如[3,4,5,6,1,2]
思路:使用二分法,但要考虑[1, 0, 0, 1]这种数据,只能顺序查找
def find_min(nums): if not nums: return False length = len(nums) left, right = 0, length - 1 while nums[left] >= nums[right]: if right - left == 1: return nums[right] mid = (left + right) / 2 if nums[left] == nums[mid] == nums[right]: return min(nums) if nums[left] <= nums[mid]: left = mid if nums[right] >= nums[mid]: right = mid return nums[0]
面试题9 斐波那契数列
思路:用生成器
def fib(num): a, b = 0, 1 for i in xrange(num): yield b a, b = b, a + b
面试题10 二进制中1的个数
要求:求一个整数的二进制表示中,1的个数
思路:二进制表示中,最后的那个1被减去后,低位都变为0,高位不变,按位与就可以去掉这个1
def num_of_1(n): ret = 0 while n: ret += 1 n = n & n-1 return ret
面试题11 数值的整数次方
要求:求一个数的整数次方
思路:需要考虑次方是正数、负数和0,基数是0
浮点数相等不能直接用==
def power(base, exponent): if equal_zero(base) and exponent < 0: raise ZeroDivisionError ret = power_value(base, abs(exponent)) if exponent < 0: return 1.0 / ret else: return ret def equal_zero(num): if abs(num - 0.0) < 0.0000001: return True def power_value(base, exponent): if exponent == 0: return 1 if exponent == 1: return base ret = power_value(base, exponent >> 1) ret *= ret if exponent & 1 == 1: ret *= base return ret
面试题12 打印1到最大的n位数
要求:输入n,打印出从1到最大的n位数
思路:Python中已经对大整数可以进行自动转换了,所以不需要考虑大整数溢出问题
def print_max_n(n): for i in xrange(10 ** n): print i
面试题13 O(1)时间删除链表结点
要求:O(1)时间删除链表结点
思路:如果有后续结点,后续结点的值前移,删除后续结点,如果没有,只能顺序查找了
def delete_node(link, node): if node == link: # 只有一个结点 del node if node.next is None: # node是尾结点 while link: if link.next == node: link.next = None link = link.next else: node.val = node.next.val n_node = node.next node.next = n_node.next del n_node
面试题14 调整数组顺序使奇数位于偶数前面
思路:使用两个指针,前后各一个,为了更好的扩展性,可以把判断奇偶部分抽取出来
def reorder(nums, func): left, right = 0, len(nums) - 1 while left < right: while not func(nums[left]): left += 1 while func(nums[right]): right -= 1 if left < right: nums[left], nums[right] = nums[right], nums[left] def is_even(num): return (num & 1) == 0
面试题15 链表中倒数第k个结点
要求:求单链表中的倒数第k个结点
思路:使用快慢指针,快的先走k-1步,需要考虑空链表以及k为0
def last_kth(link, k): if not link or k <= 0: return None move = link while move and k-1 >= 0: move = move.next k -= 1 while move: move = move.next link = link.next if k == 0: return link.val return None
面试题16 反转链表
要求:反转链表
思路:需要考虑空链表,只有一个结点的链表
def reverse_link(head): if not head or not head.next: return head then = head.next head.next = None last = then.next while then: then.next = head head = then then = last if then: last = then.next return head
面试题17 合并两个排序的链表
要求:合并两个排序的链表
思路:使用递归
def merge_link(head1, head2): if not head1: return head2 if not head2: return head1 if head1.val <= head2.val: ret = head1 ret.next = merge_link(head1.next, head2) else: ret = head2 ret.next = merge_link(head1, head2.next) return ret
面试题18 树的子结构
要求:判断一棵二叉树是不是另一个的子结构
思路:使用递归
def sub_tree(tree1, tree2): if tree1 and tree2: if tree1.val == tree2.val: return sub_tree(tree1.left, tree2.left) and sub_tree(tree1.right, tree2.right) else: return sub_tree(tree1.left, tree2) or sub_tree(tree1.right, tree2) if not tree1 and tree2: return False return True
面试题19 二叉树的镜像
思路一:可以按层次遍历,每一层从右到左
思路二:使用递归
def mirror_bfs(root): ret = [] queue = deque([root]) while queue: node = queue.popleft() if node: ret.append(node.val) queue.append(node.right) queue.append(node.left) return ret def mirror_pre(root): ret = [] def traversal(root): if root: ret.append(root.val) traversal(root.right) traversal(root.left) traversal(root) return ret
面试题20 顺时针打印矩阵
def print_matrix(matrix): """ :param matrix: [[]] """ rows = len(matrix) cols = len(matrix[0]) if matrix else 0 start = 0 ret = [] while start * 2 < rows and start * 2 < cols: print_circle(matrix, start, rows, cols, ret) start += 1 print ret def print_circle(matrix, start, rows, cols, ret): row = rows - start - 1 # 最后一行 col = cols - start - 1 # left->right for c in range(start, col+1): ret.append(matrix[start][c]) # top->bottom if start < row: for r in range(start+1, row+1): ret.append(matrix[r][col]) # right->left if start < row and start < col: for c in range(start, col)[::-1]: ret.append(matrix[row][c]) # bottom->top if start < row and start < col: for r in range(start+1, row)[::-1]: ret.append(matrix[r][start])
面试题21 包含min函数的栈
要求:栈的push,pop,min操作的时间复杂度都是O(1)
思路:使用一个辅助栈保存最小值
class MyStack(object): def __init__(self): self.stack = [] self.min = [] def push(self, val): self.stack.append(val) if self.min and self.min[-1] < val: self.min.append(self.min[-1]) else: self.min.append(val) def pop(self): if self.stack: self.min.pop() return self.stack.pop() return None def min(self): return self.min[-1] if self.min else None
面试题22 栈的压入弹出序列
要求:判断给定的两个序列中,后者是不是前者的弹出序列,给定栈不包含相同值
思路:使用一个辅助栈, 如果辅助栈栈顶元素不等于出栈元素,则从入栈中找改值,直到入栈为空
如果最后出栈序列为空,则是入栈的弹出序列值
def pop_order(push_stack, pop_stack): if not push_stack or not pop_stack: return False stack = [] while pop_stack: pop_val = pop_stack[0] if stack and stack[-1] == pop_val: stack.pop() pop_stack.pop(0) else: while push_stack: if push_stack[0] != pop_val: stack.append(push_stack.pop(0)) else: push_stack.pop(0) pop_stack.pop(0) break if not push_stack: while stack: if stack.pop() != pop_stack.pop(0): return False if not pop_stack: return True return False
面试题23 从上往下打印二叉树
思路:广度优先搜索,按层次遍历
def bfs(tree): if not tree: return None stack = [tree] ret = [] while stack: node = stack.pop(0) ret.append(node.val) if node.left: stack.append(node.left) if node.right: stack.append(node.right) return ret
面试题24 二叉搜索树的后序遍历序列
要求:判断给定的整数数组是不是二叉搜索树的后序遍历序列
整数数组中不包含重复值
整数序列的最后一个值是根结点,然后比根结点小的值是左子树,剩下的是右子树,递归左右子树
def is_post_order(order): length = len(order) if length: root = order[-1] left = 0 while order[left] < root: left += 1 right = left while right < length - 1: if order[right] < root: return False right += 1 left_ret = True if left == 0 else is_post_order(order[:left]) right_ret = True if left == right else is_post_order(order[left:right]) return left_ret and right_ret return False
面试题25 二叉树中和为某一值的路径
要求:输入一棵二叉树和一个值,求从根结点到叶结点的和等于该值的路径
深度优先搜索变形
def find_path(tree, num): ret = [] if not tree: return ret path = [tree] sums = [tree.val] def dfs(tree): if tree.left: path.append(tree.left) sums.append(sums[-1]+tree.left.val) dfs(tree.left) if tree.right: path.append(tree.right) sums.append(sums[-1] + tree.right.val) dfs(tree.right) if not tree.left and not tree.right: if sums[-1] == num: ret.append([p.val for p in path]) path.pop() sums.pop() dfs(tree) return ret
面试题26 复杂链表的复制
要求:链表中除了指向后一个结点的指针之外,还有一个指针指向任意结点
分为三步完成:
一:复制每个结点,并把新结点放在老结点后面,如1->2,复制为1->1->2->2
二:为每个新结点设置other指针
三:把复制后的结点链表拆开
题目设置了复杂链表的实现,测试代码见文件twenth_six.py
class Solution(object): @staticmethod def clone_nodes(head): # 结点复制 move = head while move: tmp = Node(move.val) tmp.next = move.next move.next = tmp move = tmp.next return head @staticmethod def set_nodes(head): # other指针设置 move = head while move: m_next = move.next if move.other: m_next.other = move.other.next move = m_next.next return head @staticmethod def reconstruct_nodes(head): # 结点拆分 ret = head.next if head else Node move = ret while head: head = move.next if head: move.next = head.next move = move.next return ret @staticmethod def clone_link(head): # 结果 h = Solution.clone_nodes(head) h = Solution.set_nodes(h) ret = Solution.reconstruct_nodes(h) return ret
面试题27 二叉搜索树与双向链表
要求: 将二叉搜索树转化成一个排序的双向链表,只调整树中结点的指向
思路: 中序遍历,根结点的left指向左子树的最后一个(最大)值,right指向右子树的(最小)值
注意: 题目构造了一个普通二叉树用来测试,构造时按照二叉搜索树的顺序输入结点,空结点用None表示,详情见twenty_seven.py
class Solution(object): @staticmethod def convert(tree): """结点转换""" if not tree: return None p_last = Solution.convert_nodes(tree, None) while p_last and p_last.left: # 获取链表头结点 p_last = p_last.left return p_last @staticmethod def convert_nodes(tree, last): if not tree: return None if tree.left: last = Solution.convert_nodes(tree.left, last) if last: last.right = tree tree.left = last last = tree if tree.right: last = Solution.convert_nodes(tree.right, last) return last
面试题28 字符串的排列
要求:求输入字符串的全排列
思路:递归完成,也可以直接使用库函数
def my_permutation(s): str_set = [] ret = [] # 最后的结果 def permutation(string): for i in string: str_tem = string.replace(i, ‘‘) str_set.append(i) if len(str_tem) > 0: permutation(str_tem) else: ret.append(‘‘.join(str_set)) str_set.pop() permutation(s) return ret
面试题29 数组中出现次数超过一半的数字
思路: 使用hash,key是数字,value是出现的次数
注意: 列表的len方法的时间复杂度是O(1)
def get_more_half_num(nums): hashes = dict() length = len(nums) for n in nums: hashes[n] = hashes[n] + 1 if hashes.get(n) else 1 if hashes[n] > length / 2: return n
面试题30 最小的k个数
要求:求数组中出现次数超过一半的数字
思路: 使用heapq,该模块是一个最小堆,需要转化成最大堆,只要在入堆的时候把值取反就可以转化成最大堆(仅适用于数字)
思路二: 数组比较小的时候可以直接使用heapq的nsmallest方法
import heapq def get_least_k_nums(nums, k): # 数组比较小的时候可以直接使用 return heapq.nsmallest(k, nums) class MaxHeap(object): def __init__(self, k): self.k = k self.data = [] def push(self, elem): elem = -elem # 入堆的时候取反,堆顶就是最大值的相反数了 if len(self.data) < self.k: heapq.heappush(self.data, elem) else: least = self.data[0] if elem > least: heapq.heapreplace(self.data, elem) def get_least_k_nums(self): return sorted([-x for x in self.data])
面试题31 连续子数组的最大和
思路: 动态规划问题
def max_sum(nums): ret = float("-inf") # 负无穷 if not nums: return ret current = 0 for i in nums: if current <= 0: current = i else: current += i ret = max(ret, current) return ret
面试题32 从1到n整数中1出现的次数
要求:求从1到n整数的十进制表示中,1出现的次数
思路: 获取每个位数区间上所有数中包含1的个数,然后分别对高位分析,然后递归的处理低位数
此题中,作者的描述我没有理解,按照自己的理解写了一下,具体内容请点击这里
def get_digits(n): # 求整数n的位数 ret = 0 while n: ret += 1 n /= 10 return ret def get_1_digits(n): """ 获取每个位数之间1的总数 :param n: 位数 """ if n <= 0: return 0 if n == 1: return 1 current = 9 * get_1_digits(n-1) + 10 ** (n-1) return get_1_digits(n-1) + current def get_1_nums(n): if n < 10: return 1 if n >= 1 else 0 digit = get_digits(n) # 位数 low_nums = get_1_digits(digit-1) # 最高位之前的1的个数 high = int(str(n)[0]) # 最高位 low = n - high * 10 ** (digit-1) # 低位 if high == 1: high_nums = low + 1 # 最高位上1的个数 all_nums = high_nums else: high_nums = 10 ** (digit - 1) all_nums = high_nums + low_nums * (high - 1) # 最高位大于1的话,统计每个多位数后面包含的1 return low_nums + all_nums + get_1_nums(low)
面试题33 把数组排成最小的数
要求:把数组中的值拼接,找出能产生的最小的数[321,32,3]最小的数是321323
思路: Python中不需要考虑大整数,需要自己定义一个数组排序规则,直接调用库函数就可以
def cmp(a, b): return int(str(a)+str(b)) - int(str(b)+str(a)) def print_mini(nums): print int(‘‘.join([str(num) for num in sorted(nums, cmp=cmp)]))
面试题34 丑数 LeetCode
要求:只含有2、3、5因子的数是丑数,求第1500个丑数
思路: 按顺序保存已知的丑数,下一个是已知丑数中某三个数乘以2,3,5中的最小值
class Solution(object): def nthUglyNumber(self, n): """ :type n: int :rtype: int """ ugly = [1] t2 = t3 = t5 = 0 while len(ugly) < n: while ugly[t2] * 2 <= ugly[-1]: t2 += 1 while ugly[t3] * 3 <= ugly[-1]: t3 += 1 while ugly[t5] * 5 <= ugly[-1]: t5 += 1 ugly.append(min(ugly[t2]*2, ugly[t3]*3, ugly[t5]*5)) return ugly[-1]
面试题35 第一个只出现一次的字符
要求:求字符串中第一个只出现一次的字符
思路: 使用两个hash,一个记录每个字符穿线的次数,另一个记录每个字符第一次出现的位置
def first_not_repeating_char(string): if not string: return -1 count = {} loc = {} for k, s in enumerate(string): count[s] = count[s] + 1 if count.get(s) else 1 loc[s] = loc[s] if loc.get(s) else k ret = float(‘inf‘) for k in loc.keys(): if count.get(k) == 1 and loc[k] < ret: ret = loc[k] return ret
面试题36 数组中的逆序对
要求:在一个数组中,前面的数字比后面的大,就是一个逆序对,求总数
思路: 归并排序,先把数组依次拆开,然后合并的时候统计逆序对数目,并排序
import copy def get_inverse_pairs(nums): if not nums: return 0 start, end = 0, len(nums) - 1 tmp = copy.deepcopy(nums) return inverse_pairs(tmp, start, end) def inverse_pairs(tmp, start, end): if start == end: # 递归结束条件 return 0 mid = (end - start) / 2 # 分别对左右两边递归求值 left = inverse_pairs(tmp, start, start+mid) right = inverse_pairs(tmp, start+mid+1, end) count = 0 # 本次逆序对数目 l_right, r_right = start + mid, end t = [] while l_right >= start and r_right >= start + mid + 1: if tmp[l_right] > tmp[r_right]: t.append(tmp[l_right]) count += (r_right - mid - start) l_right -= 1 else: t.append(tmp[r_right]) r_right -= 1 while l_right >= start: t.append(tmp[l_right]) l_right -= 1 while r_right >= start+mid+1: t.append(tmp[r_right]) r_right -= 1 tmp[start:end+1] = t[::-1] return count + left + right
面试题37 两个链表的第一个公共结点
思路: 先获取到两个链表的长度,然后长的链表先走多的几步,之后一起遍历
文件thirty_seven.py中包含了设置链表公共结点的代码,可以用来测试
def get_first_common_node(link1, link2): if not link1 or not link2: return None length1 = length2 = 0 move1, move2 = link1, link2 while move1: # 获取链表长度 length1 += 1 move1 = move1.next while move2: length2 += 1 move2 = move2.next while length1 > length2: # 长链表先走多的长度 length1 -= 1 link1 = link1.next while length2 > length1: length2 -= 1 link2 = link2.next while link1: # 链表一起走 if link1 == link2: return link1 link1, link2 = link1.next, link2.next return None
面试题38 数字在排序数组中出现的次数
思路: 使用二分法分别找到数组中第一个和最后一个出现的值的坐标,然后相减
def get_k_counts(nums, k): first = get_first_k(nums, k) last = get_last_k(nums, k) if first < 0 and last < 0: return 0 if first < 0 or last < 0: return 1 return last - first + 1 def get_first_k(nums, k): left, right = 0, len(nums) - 1 while left <= right: mid = (left + right) / 2 if nums[mid] < k: if mid + 1 < len(nums) and nums[mid+1] == k: return mid + 1 left = mid + 1 elif nums[mid] == k: if mid - 1 < 0 or (mid - 1 >= 0 and nums[mid-1] < k): return mid right = mid - 1 else: right = mid - 1 return -1 def get_last_k(nums, k): left, right = 0, len(nums) - 1 while left <= right: mid = (left + right) / 2 if nums[mid] < k: left = mid + 1 elif nums[mid] == k: if mid + 1 == len(nums) or (mid + 1 < len(nums) and nums[mid+1] > k): return mid left = mid + 1 else: if mid - 1 >= 0 and nums[mid-1] == k: return mid - 1 right = mid - 1 return -1
面试题39 二叉树的深度
思路: 分别递归的求左右子树的深度
def get_depth(tree): if not tree: return 0 if not tree.left and not tree.right: return 1 return 1 + max(get_depth(tree.left), get_depth(tree.right))
面试题40 数组中只出现一次的数字
要求:数组中除了两个只出现一次的数字外,其他数字都出现了两遍
思路: 按位异或,在得到的值中找到二进制最后一个1,然后把数组按照该位是0还是1分为两组
def get_only_one_number(nums): if not nums: return None tmp_ret = 0 for n in nums: # 获取两个值的异或结果 tmp_ret ^= n last_one = get_bin(tmp_ret) a_ret, b_ret = 0, 0 for n in nums: if is_one(n, last_one): a_ret ^= n else: b_ret ^= n return [a_ret, b_ret] def get_bin(num): # 得到第一个1 ret = 0 while num & 1 == 0 and ret < 32: num = num >> 1 ret += 1 return ret def is_one(num, t): # 验证t位是不是1 num = num >> t return num & 0x01
面试题41 和为s的两个数字VS和为s的连续正数序列
和为s的两个数字
要求:输入一个递增排序的数组和一个数字s,在数组中查找两个数,使其和为s
思路: 设置头尾两个指针,和大于s,尾指针减小,否砸头指针增加
def sum_to_s(nums, s): head, end = 0, len(nums) - 1 while head < end: if nums[head] + nums[end] == s: return [nums[head], nums[end]] elif nums[head] + nums[end] > s: end -= 1 else: head += 1 return None
和为s的连续整数序列
要求:输入一个正数s, 打印出所有和为s的正整数序列(至少两个数)
思路: 使用两个指针,和比s小,大指针后移,比s大,小指针后移
def sum_to_s(s): a, b = 1, 2 ret = [] while a < s / 2 + 1: if sum(range(a, b+1)) == s: ret.append(range(a, b+1)) a += 1 elif sum(range(a, b+1)) < s: b += 1 else: a += 1 return ret
面试题42 翻转单词顺序与左旋转字符串
翻转单词顺序
要求:翻转一个英文句子中的单词顺序,标点和普通字符一样处理
思路: Python中字符串是不可变对象,不能用书中的方法,可以直接转化成列表然后转回去
def reverse_words(sentence): tmp = sentence.split() return ‘ ‘.join(tmp[::-1]) # 使用join效率更好,+每次都会创建新的字符串
左旋转字符串
思路: 把字符串的前面的若干位移到字符串的后面
def rotate_string(s, n): if not s: return ‘‘ n %= len(s) return s[n:] + s[:n]
面试题43 n个骰子的点数
要求:求出n个骰子朝上一面之和s所有可能值出现的概率
思路:n出现的可能是前面n-1到n-6出现可能的和,设置两个数组,分别保存每一轮
def get_probability(n): if n < 1: return [] data1 = [0] + [1] * 6 + [0] * 6 * (n - 1) data2 = [0] + [0] * 6 * n # 开头多一个0,方便按照习惯从1计数 flag = 0 for v in range(2, n+1): # 控制次数 if flag: for k in range(v, 6*v+1): data1[k] = sum([data2[k-j] for j in range(1, 7) if k > j]) flag = 0 else: for k in range(v, 6*v+1): data2[k] = sum([data1[k-j] for j in range(1, 7) if k > j]) flag = 1 ret = [] total = 6 ** n data = data2[n:] if flag else data1[n:] for v in data: ret.append(v*1.0/total) print data return ret
面试题44 扑克牌的顺子
要求:从扑克牌中随机抽取5张牌,判断是不是顺子,大小王可以当任意值
思路: 使用排序
import random def is_continus(nums, k): data = [random.choice(nums) for _ in range(k)] data.sort() print data zero = data.count(0) small, big = zero, zero + 1 while big < k: if data[small] == data[big]: return False tmp = data[big] - data[small] if tmp > 1: if tmp - 1 > zero: return False else: zero -= tmp - 1 small += 1 big += 1 else: small += 1 big += 1 return True
面试题45 圆圈中最后剩下的数字
要求:0到n-1排成一圈,从0开始每次数m个数删除,求最后剩余的数
思路:当 n > 1 时: f(n,m) = [f(n-1, m)+m]%n,当 n = 1 时: f(n,m)=0,关键是推导出关系表达式
def last_num(n, m): ret = 0 if n == 1: return 0 for i in range(2, n+1): ret = (m + ret) % i return ret
面试题46 求1+2...+n
要求:不能使用乘除、for、while、if、else等
方法一:使用range和sum
方法二:使用reduce
def get_sum1(n): return sum(range(1, n+1)) def get_sum2(n): return reduce(lambda x, y: x+y, range(1, n+1))
面试题47 不用加减乘除做加法
要求:不用加减乘除做加法
方法一:使用位运算,Python中大整数会自动处理,因此对carry需要加个判断
方法二:使用sum
def bit_add(n1, n2): carry = 1 while carry: s = n1 ^ n2 carry = 0xFFFFFFFF & ((n1 & n2) << 1) carry = -(~(carry - 1) & 0xFFFFFFFF) if carry > 0x7FFFFFFF else carry n1 = s n2 = carry return n1 def add(n1, n2): return sum([n1, n2])
面试题48 不能被继承的类
Python中不知道怎么实现不能被继承的类。以后补充代码或者原因。
面试题49 把字符串转化成整数
要求:把字符串转化成整数
测试用例:正负数和0,空字符,包含其他字符
备注:使用raise抛出异常作为非法提示
def str_to_int(string): if not string: # 空字符返回异常 raise Exception(‘string cannot be None‘, string) flag = 0 # 用来表示第一个字符是否为+、- ret = 0 # 结果 for k, s in enumerate(string): if s.isdigit(): # 数字直接运算 val = ord(s) - ord(‘0‘) ret = ret * 10 + val else: if not flag: if s == ‘+‘ and k == 0: # 避免中间出现+、- flag = 1 elif s == ‘-‘ and k == 0: flag = -1 else: raise Exception(‘digit is need‘, string) else: raise Exception(‘digit is need‘, string) if flag and len(string) == 1: # 判断是不是只有+、- raise Exception(‘digit is need‘, string) return ret if flag >= 0 else -ret
面试题50 树中两个结点的最低公共祖先
要求:求普通二叉树中两个结点的最低公共祖先
方法一:先求出两个结点到根结点的路径,然后从路径中找出最后一个公共结点
备注:文件fifty.py中包含该代码的具体测试数据
class Solution(object): def __init__(self, root, node1, node2): self.root = root # 树的根结点 self.node1 = node1 self.node2 = node2 # 需要求的两个结点 @staticmethod def get_path(root, node, ret): """获取结点的路径""" if not root or not node: return False ret.append(root) if root == node: return True left = Solution.get_path(root.left, node, ret) right = Solution.get_path(root.right, node, ret) if left or right: return True ret.pop() def get_last_common_node(self): """获取公共结点""" route1 = [] route2 = [] # 保存结点路径 ret1 = Solution.get_path(self.root, self.node1, route1) ret2 = Solution.get_path(self.root, self.node2, route2) ret = None if ret1 and ret2: # 路径比较 length = len(route1) if len(route1) <= len(route2) else len(route2) index = 0 while index < length: if route1[index] == route2[index]: ret = route1[index] index += 1 return ret
‘ a b ‘.replace(‘ ‘, ‘20%‘)
以上是关于python面试题六: 剑指offer的主要内容,如果未能解决你的问题,请参考以下文章