├── 2017校招真题 ├── n个数里最小的k个.py ├── 下厨房.py ├── 不要二.py ├── 两种排序方法.py ├── 买苹果.py ├── 优雅的点.py ├── 倒置字符串.py ├── 分田地.py ├── 分苹果.py ├── 删除公共字符.py ├── 合唱团.py ├── 回文序列.py ├── 地下迷宫.py ├── 字符串中找出连续最长的数字串.py ├── 小易喜欢的单词.py ├── 幸运的袋子.py ├── 招商银行.py ├── 数列还原.py ├── 数字和为sum的方法数.py ├── 数字游戏.py ├── 数字翻转.py ├── 星际穿越.py ├── 最大奇约数.py ├── 末尾0的个数.py ├── 求和-好未来.py ├── 求和.py ├── 百度.py ├── 素数对.py ├── 统计回文.py ├── 美团.py ├── 藏宝图.py ├── 解救小易.py ├── 计算糖果.py ├── 输入n个整数,输出出现次数大于等于数组长度一半的数。.py ├── 进制转换.py ├── 餐厅.py └── 饥饿的小易.py ├── README.md ├── 剑指offer ├── 不用加减乘除做加法.py ├── 丑数.py ├── 两个合并排序的链表.py ├── 两个栈实现队列.py ├── 两个链表的第一个公共节点.py ├── 二叉搜索树和双向链表.py ├── 二叉搜索树的后序遍历序列.py ├── 二叉搜索树的第k个节点.py ├── 二叉树中和为某一值的路径.py ├── 二叉树的下一个节点.py ├── 二叉树的深度.py ├── 二叉树的镜像.py ├── 二维数组中的查找.py ├── 二进制中1的个数.py ├── 从上往下打印二叉树.py ├── 从尾到头打印链表.py ├── 删除链表中重复的节点.py ├── 剑指offer-python实现.docx ├── 包含min函数的栈.py ├── 反转链表.py ├── 变态青蛙跳.py ├── 和为s的两个数字.py ├── 和为s的连续整数序列.py ├── 圆圈中最后剩下的数.py ├── 坐旋转字符串.py ├── 复杂链表的复制.py ├── 字符串的排列.py ├── 字符流中第一个不重复的字符.py ├── 对称的二叉树.py ├── 平衡二叉树.py ├── 序列化二叉树.py ├── 总结 ├── 扑克片顺子.py ├── 把二叉树打印成多行.py ├── 把字符串转化成整数.py ├── 把数组排成最小的数.py ├── 按之字形顺序打印二叉树.py ├── 数值的整数次方.py ├── 数字在排序数组中出现的次数.py ├── 数据流中的中位数.py ├── 数的子结构.py ├── 数组中出现次数超过一半的数字.py ├── 数组中只出现一次的数字.py ├── 数组中的逆序对.py ├── 数组中重复的数字.py ├── 整数中1出现的次数.py ├── 斐波那契数列.py ├── 旋转数组的最小数字.py ├── 替换空格.py ├── 最小的k个数.py ├── 机器人的运动范围.py ├── 构建乘积数组.py ├── 栈的压入弹出序列.py ├── 正则表达式匹配.py ├── 求1+2+3+...+n.py ├── 滑动窗口的最大值.py ├── 矩形覆盖.py ├── 矩阵中的路径.py ├── 第一个只出现一次的字符.py ├── 翻转单词顺序列.py ├── 表示数值的字符串.py ├── 调整数组顺序使奇数位于偶数前面.py ├── 连续子数组的最大和.py ├── 重建二叉树.py ├── 链表中倒数第k个节点.py ├── 链表中环的入口节点.py ├── 青蛙跳台阶.py └── 顺时针打印矩阵.py ├── 华为机试 ├── 删除字符串中出现次数最少的字符.py ├── 判断两个IP是否属于同一子网.py ├── 单词倒排.py ├── 取近似值.py ├── 句子逆序.py ├── 合唱队.py ├── 合并表记录.py ├── 图片整理.py ├── 坐标移动.py ├── 字串的连接最长路径查找.py ├── 字符个数统计.py ├── 字符串分割.py ├── 字符串加密.py ├── 字符串加密2.py ├── 字符串反转.py ├── 字符串合并处理.py ├── 字符串排序.py ├── 字符串最后一个单词的长度.py ├── 字符串运用-密码截取.py ├── 密码验证合格程序.py ├── 提取不重复的整数.py ├── 数字颠倒.py ├── 数据分类处理.py ├── 整数与IP地址间的转换.py ├── 明明的随机数.py ├── 查找兄弟单词.py ├── 求int型正整数在内存中存储时1的个数.py ├── 求小球落地5次后所经历的路程和第5次反弹的高度.py ├── 汽水瓶.py ├── 称砝码.py ├── 简单密码.py ├── 简单错误记录.py ├── 素数伴侣.py ├── 统计每个月兔子的总数.py ├── 蛇形矩阵.py ├── 计算字符个数.py ├── 识别有效的IP地址和掩码并进行分类统计.py ├── 质数因子.py ├── 购物单.py ├── 输入一行字符,分别统计出包含英文字母、空格、数字和其它字符的个数.py └── 进制转换.py ├── 机试题 ├── 排序.py ├── 生成指定长度的斐波那契数列.py └── 链表.py └── 直通BAT算法题 ├── 二叉树 ├── 1.py ├── 二叉树的前中后序的递归,非递归及Morris遍历.py ├── 二叉树的序列化和反序列化.py ├── 二叉树的按层打印.py └── 判断t1树中是否有与t2树拓扑结构完全相同的子树.py ├── 栈和队列 ├── 两个栈组成一个队列.py ├── 如何仅用递归函数和栈操作逆序一个栈.py ├── 构造数组的MaxTree.py ├── 求最大子矩阵的大小.py ├── 生成窗口最大值数组.py ├── 用一个栈实现另一个栈的排序.py └── 设计一个有getMin功能的栈.py └── 链表问题 ├── 判断一个链表是否为回文结构.py ├── 判断一个链表是否有环,如果有的话返回第一个进环的节点.py ├── 判断两个无环链表是否相交,相交则返回第一个相交节点.py ├── 判断两个有环链表是否相交,相交则返回第一个相交节点.py ├── 向有环的环形链表中插入新节点.py ├── 在单链表中删除指定值的节点.py ├── 复制含有随机指针节点的链表.py ├── 将单向链表按某值划分成左边小,中间相等,右边大的形式.py ├── 将单链表的每K个节点之间逆序.py ├── 打印两个有序链表的公共部分.py └── 节点删除方式.py /2017校招真题/n个数里最小的k个.py: -------------------------------------------------------------------------------- 1 | x = [int(i) for i in input().split()] 2 | k = x[-1] 3 | x.remove(x[-1]) 4 | x.sort() 5 | print(' '.join(list(map(str,x[:k])))) 6 | 7 | 8 | # a = list(map(int, input().split())) 9 | # lists, k = a[:-1], a[-1] 10 | # print(" ".join(list(map(str, sorted(lists)[:k])))) -------------------------------------------------------------------------------- /2017校招真题/下厨房.py: -------------------------------------------------------------------------------- 1 | # 第一个问题就是输入的问题,没说输入多少行 2 | # 第二个问题就是去掉重复字符的问题 3 | 4 | x = [] 5 | while True: 6 | try: 7 | m = input().split() 8 | x.extend(m) 9 | except: 10 | print(len(set(x))) 11 | break 12 | -------------------------------------------------------------------------------- /2017校招真题/不要二.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leeguandong/Interview-code-practice-python/86933f82f3553dfca16055977d7366b106b511bd/2017校招真题/不要二.py -------------------------------------------------------------------------------- /2017校招真题/两种排序方法.py: -------------------------------------------------------------------------------- 1 | x, arr = input(), [] 2 | 3 | for i in range(int(x)): 4 | arr.append(input()) 5 | 6 | length, lex = sorted(arr, key=len), sorted(arr) 7 | 8 | if length == arr and lex == arr: 9 | print('both') 10 | elif length == arr: 11 | print('lengths') 12 | elif lex == arr: 13 | print('lexicographically') 14 | else: 15 | print('none') 16 | -------------------------------------------------------------------------------- /2017校招真题/买苹果.py: -------------------------------------------------------------------------------- 1 | # 这种题目一般都是动态规划或者贪心算法 2 | # 当然可以暴力,我自己也只会暴力 3 | 4 | x = int(input()) 5 | 6 | def getcount(x): 7 | for i in range(x // 6 + 1): 8 | if (x - i * 6) % 8 == 0: 9 | return i + (x - i * 6) // 8 10 | return -1 11 | 12 | print(int(getcount(x))) 13 | -------------------------------------------------------------------------------- /2017校招真题/优雅的点.py: -------------------------------------------------------------------------------- 1 | x = int(input()) 2 | y = int(x ** 0.5) 3 | 4 | count = 0 5 | for i in range(0, y + 1): 6 | for j in range(0, y + 1): 7 | if i ** 2 + j ** 2 == x: 8 | if i == 0 and j == 0: 9 | count += 1 10 | if i == 0 or j == 0: 11 | count += 2 12 | if i != 0 and j != 0: 13 | count += 4 14 | 15 | print(count) 16 | -------------------------------------------------------------------------------- /2017校招真题/倒置字符串.py: -------------------------------------------------------------------------------- 1 | x = input().split() 2 | print(' '.join(list(map(str, x[::-1])))) 3 | -------------------------------------------------------------------------------- /2017校招真题/分田地.py: -------------------------------------------------------------------------------- 1 | # 就是把田地横竖各三刀,分成16块。取16块里面价值的最小值Di。然后求所有划分方法Di构成集合中的最大值 2 | -------------------------------------------------------------------------------- /2017校招真题/分苹果.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 1.先判断数组总和是否可以被n整除,否则没法分均匀。 3 | 2.然后再判断每个牛的苹果与平均值的差,若差不是2的倍数,也无法移动成功 4 | 3.如果前两个条件满足就把比均值多的苹果数减去均值,将其总数除以2, 5 | 就是得到的移动次数了。 6 | ''' 7 | 8 | n = int(input()) 9 | ls = [int(i) for i in input().split()] 10 | 11 | def splitapple(n, ls): 12 | if sum(ls) % n != 0: 13 | return -1 14 | count = 0 15 | avg = sum(ls) // n 16 | 17 | for i in ls: 18 | if (i - avg) % 2 != 0: 19 | return -1 20 | if i > avg: 21 | count += (i - avg) 22 | return (int(count // 2)) 23 | 24 | print(splitapple(n, ls)) 25 | -------------------------------------------------------------------------------- /2017校招真题/删除公共字符.py: -------------------------------------------------------------------------------- 1 | x = input().split() 2 | k = ''.join(list(map(str, input().split()))) 3 | # k = x[-1] 4 | # x.remove(x[-1]) 5 | 6 | res = [] 7 | for i in x: 8 | for j in i: 9 | if j in k: 10 | # i.replace(j, '') 11 | # print(i) 12 | n = i.index(j) 13 | i = i[:n] + i[n + 1:] 14 | res.append(i) 15 | 16 | print(' '.join(list(map(str, res)))) 17 | -------------------------------------------------------------------------------- /2017校招真题/合唱团.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目要求是 n 个学生中选择 k 个,使这 k 个学生的能力值乘积最大,这是一个最优化问题,在优化过程中,提出了相邻 3 | 两个学生的位置编号差不超过 d 的约束。 4 | 5 | 递归或者动态变化 6 | 1.对该问题的分解是关键 7 | 从 n 个学生中,选择 k 个,可以看成是:先从 n 个学生里选择最后1个,然后在剩下的里选择 k-1 个,并且让这1个和 8 | 前一个满足约束条件 9 | 2.数学描述 10 | 记第 k 个人的位置为1,则可以用f[1][k]表示从 n 个人中选择 k 个的方案。 11 | 然后它的子问题,需要从1前面的left个人里面,选择 k-1 个,这里left表示 12 | k-1 个人中最后一个(即第k-1个)人的位置,因此,子问题可以表示成f[left][k-1] 13 | 14 | 在n和k定了之后,需要求解出n个学生选择k个能力乘积的最大值。因为能力值有正 15 | 有负,所以 16 | 当1对应的学生能力值为正时 17 | f[1][k] = max{f[left][k-1] arr[i]}(min{k-1,1-d}<=left<=1-1) 18 | 19 | ''' 20 | 21 | x1 = int(input()) 22 | x2 = [int(i) for i in input().split()] 23 | k, d = map(int, input().split()) 24 | 25 | fmax = [[0 for i in range(x1)] for i in range(k)] 26 | print(fmax) 27 | fmin = [[0 for i in range(x1)] for i in range(k)] 28 | 29 | for kk in range(k): 30 | for i in range(x1): 31 | if kk == 0 or i == 0: 32 | fmax[kk][i] = x2[i] 33 | fmin[kk][i] = x2[i] 34 | else: 35 | M = [] 36 | for t in range(max(i - d, 0), i): 37 | M.extend([fmax[kk - 1][t] * x2[i], fmin[kk - 1][t] * x2[i]]) 38 | fmax[kk][i], fmin[kk][i] = max(M), min(M) 39 | print(max(fmax[k - 1])) 40 | -------------------------------------------------------------------------------- /2017校招真题/回文序列.py: -------------------------------------------------------------------------------- 1 | X = int(input()) 2 | n = [int(i) for i in input().split()] 3 | 4 | def huiwen(n, start, end): 5 | left = n[start] 6 | right = n[end] 7 | time = 0 8 | while start < end: 9 | if left < right: 10 | start += 1 11 | left += n[start] 12 | time += 1 13 | elif left > right: 14 | end -= 1 15 | right += n[right] 16 | time += 1 17 | elif left == right: 18 | start += 1 19 | end -= 1 20 | left = n[left] 21 | right = n[right] 22 | return time 23 | 24 | print(huiwen(n, 0, X - 1)) 25 | -------------------------------------------------------------------------------- /2017校招真题/地下迷宫.py: -------------------------------------------------------------------------------- 1 | # dfs 2 | -------------------------------------------------------------------------------- /2017校招真题/字符串中找出连续最长的数字串.py: -------------------------------------------------------------------------------- 1 | # 在于判断是不是数的这个isnumeric()函数 2 | x = input() 3 | curlen, curstr, maxlen, maxstr = 0, '', 0, '' 4 | 5 | for i, v in enumerate(x): 6 | if v.isnumeric(): 7 | curlen += 1 8 | curstr += v 9 | if curlen > maxlen: 10 | maxlen = curlen 11 | maxstr = curstr 12 | else: 13 | curlen = 0 14 | curstr = '' 15 | print(maxstr) 16 | -------------------------------------------------------------------------------- /2017校招真题/小易喜欢的单词.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leeguandong/Interview-code-practice-python/86933f82f3553dfca16055977d7366b106b511bd/2017校招真题/小易喜欢的单词.py -------------------------------------------------------------------------------- /2017校招真题/幸运的袋子.py: -------------------------------------------------------------------------------- 1 | # x = input() 2 | # y = map(int,input().split()) 3 | # n = 0 4 | # m = 1 5 | # count = 0 6 | # for i in y: 7 | # n += i 8 | # m *= i 9 | # print(n,m) 10 | # if m < n: 11 | # count +=1 12 | # 13 | # print(count) 14 | 15 | ''' 16 | 这个问题是求有重复数字的集合的所有子集的一个扩展 17 | 加了限制条件,这些限制条件恰好可以用来剪枝 18 | 19 | 深度优先搜索 + 剪枝 20 | ''' 21 | n = int(input()) 22 | x = sorted(list(map(int, input().split()))) # 从小到大排序 23 | 24 | # s 为和,p 为积,pos 为初始位置 25 | def dfs(x, pos, s, p): 26 | ans = 0 27 | i = pos 28 | while i < n: 29 | if s + x[i] > p * x[i]: 30 | ans += 1 + dfs(x, i + 1, s + x[i], p * x[i]) 31 | # 第一个测试案例中 1 1 1 就有问题,后面的等于前面的,会存在重复递归的问题 32 | elif x[i] == 1: 33 | ans += dfs(x, i + 1, s + 1, p) 34 | else: 35 | break 36 | while i < n - 1 and x[i] == x[i + 1]: 37 | i += 1 38 | i += 1 39 | return ans 40 | 41 | print(dfs(x, 0, 0, 1)) 42 | -------------------------------------------------------------------------------- /2017校招真题/招商银行.py: -------------------------------------------------------------------------------- 1 | # x1 = raw_input() 2 | # x2 = raw_input() 3 | # 4 | # count = 0 5 | # for i in range(len(x1)): 6 | # for j in range(i, len(x2)): 7 | # if x1[i] == x2[j]: 8 | # continue 9 | # else: 10 | # count += 1 11 | # 12 | # if int(len(x1[0])) - count <= 1: 13 | # print 1 14 | # else: 15 | # print 0 16 | 17 | 18 | x1 = raw_input() 19 | x2 = raw_input().split() 20 | 21 | res = [] 22 | j = 0 23 | k = 0 24 | for i in range(3): 25 | if i == 0: 26 | res.append(x2[0]) 27 | continue 28 | if i % 2 != 0: 29 | x3 = list(x2) 30 | while x3: 31 | if j > len(x2): 32 | break 33 | res.append(x2[j]) 34 | j += 2 35 | x3.pop() 36 | if i % 2 == 0: 37 | x4 = list(x2) 38 | while x4: 39 | if j > len(x2): 40 | break 41 | res.append(x2[k]) 42 | k += 2 43 | x4.pop() 44 | 45 | print res 46 | print sum(int(i) for i in res) - 1 47 | 48 | -------------------------------------------------------------------------------- /2017校招真题/数列还原.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 思路:将 A 中缺失的部分补齐,然后求顺序对数,等于 k 则计数+1. 3 | 为此,先找到 A 缺失的是哪些数字,它们分别在什么位置。 4 | 其次,将这些缺失的数字全排列,分别按位置填充到 A 中, 5 | 计算当前组合的情况下 A 的顺序对数。 6 | 7 | ## 全排列:从 n 个不同元素中任取 m 个元素,按照一定的顺序排列起来, 8 | 叫做从 n 个不同元素中取出 m 个元素的一个排列。当 m=n 时所有的排 9 | 列情况叫做全排列。 10 | ''' 11 | 12 | from itertools import permutations 13 | 14 | # 求 A 中顺序对数 15 | def number(A): 16 | count = 0 17 | for i in range(len(A)): 18 | for j in range(i + 1, len(A)): 19 | if A[i] < A[j]: 20 | count += 1 21 | return count 22 | 23 | n, k = map(int, input().strip().split()) 24 | A = list(map(int, input().strip().split())) 25 | B = list(range(1, n + 1)) 26 | X = list(set(B).difference(set(A))) # B 和 A 的差集,即缺失的数字 27 | Y = list(permutations(X)) # 求 X 的全排列 28 | index = [] 29 | for i in range(n): 30 | if A[i] == 0: 31 | index.append(i) # A 中0所在的位置的索引 32 | m = len(index) 33 | count = 0 34 | 35 | # 往队列中嵌入全排列 36 | for x in Y: 37 | for i in range(m): 38 | A[index[i]] = x[i] 39 | num = number(A) 40 | if num == k: 41 | count += 1 42 | print(count) 43 | -------------------------------------------------------------------------------- /2017校招真题/数字和为sum的方法数.py: -------------------------------------------------------------------------------- 1 | # k, d = map(int, input().split()) 2 | # arr = [int(i) for i in input().split()] 3 | # 4 | # class sum1(): 5 | # def __init__(self): 6 | # self.count = 0 7 | # 8 | # def subset(self, arr, i, d): 9 | # if d == 0: 10 | # self.count += 1 11 | # return self.count 12 | # elif arr[0] == d: 13 | # self.count += 1 14 | # return self.count 15 | # elif arr[i] > d: 16 | # return subset(self, arr, i - 1, d) 17 | # else: 18 | # A = subset(self, arr, i - 1, d) 19 | # B = subset(self, arr, i - 1, d - arr[i]) 20 | # return A or B 21 | # 22 | # no = sum1() 23 | # subset(no, arr, k, d) 24 | 25 | # 递归关系式 26 | # dp[i][j] = dp[i-1][j] + dp[i-1][j-A[i]] 27 | # i表示数组下标,j表示前i个元素的和,dp[i][j]表示前i个元素和为j的方案数 28 | n, m = map(int, input().split()) 29 | a = map(int, input().split()) 30 | 31 | dp = [0 for i in range(m + 1)] 32 | dp[0] = 1 33 | 34 | for i in range(n): 35 | j = m 36 | while j >= a[i]: 37 | dp[j] += dp[j - a[i]] 38 | j -= 1 39 | print(dp[m]) 40 | 41 | -------------------------------------------------------------------------------- /2017校招真题/数字游戏.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 对于从小到大排序的数列arr,前 k 项之和为 sum,则1~sum都可以用前 k 3 | 项表示(取其中的某几个相加) 4 | 如果arr[k+1] <= sum+1,则1~sum + arr[k+1]可以用前 k+1 个数字表示 5 | ''' 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /2017校招真题/数字翻转.py: -------------------------------------------------------------------------------- 1 | # x = input().split() 2 | # 3 | # res = [] 4 | # no = [] 5 | # for i in x: 6 | # no = i[::-1] 7 | # # 321 001 8 | # for j in range(len(no)): 9 | # if no[j] != '0': 10 | # no = no[j:] 11 | # break 12 | # # print(no) 13 | # res.append(no) 14 | # n = str(int(res[0]) + int(res[1])) 15 | # print(n) 16 | # n = n[::-1] 17 | # for j in range(len(n)): 18 | # if n[j] != '0': 19 | # n = n[j:] 20 | # break 21 | # print(n) 22 | 23 | # 731 288 24 | 25 | a = input().split() 26 | print(int(str(int(a[0][::-1]) + int(a[1][::-1]))[::-1])) -------------------------------------------------------------------------------- /2017校招真题/星际穿越.py: -------------------------------------------------------------------------------- 1 | import math 2 | x = int(input()) 3 | 4 | n =( math.sqrt(1+4*x)-1)/2 5 | print(int(n)) -------------------------------------------------------------------------------- /2017校招真题/最大奇约数.py: -------------------------------------------------------------------------------- 1 | # x = int(input()) 2 | # 3 | # def sum(i): 4 | # if i % 2 != 0: 5 | # return i 6 | # elif i % 2 == 0: 7 | # return sum(i / 2) 8 | # 9 | # n = 0 10 | # for i in range(1, x + 1): 11 | # n += sum(i) 12 | # print(int(n)) 13 | 14 | x = int(input()) 15 | 16 | def getsum(n): 17 | if n == 1: 18 | return 1 19 | return n*n/4 + getsum(n/2) if n%2==0 else n + getsum(n-1) 20 | 21 | print(str(getsum(x))) 22 | -------------------------------------------------------------------------------- /2017校招真题/末尾0的个数.py: -------------------------------------------------------------------------------- 1 | x = int(input()) 2 | 3 | n = 1 4 | for i in range(1, x + 1): 5 | n *= i 6 | n = str(n)[::-1] 7 | count = 0 8 | for i in n: 9 | if i != '0': 10 | break 11 | count += 1 12 | print(count) 13 | -------------------------------------------------------------------------------- /2017校招真题/求和-好未来.py: -------------------------------------------------------------------------------- 1 | # n, m = map(int, input().split()) 2 | # 3 | # for i in range(n): 4 | # for j in range(i, n + 1): 5 | # if i + j == m: 6 | # print(i, j) 7 | 8 | # dfs 9 | n, m = list(map(int, input().split())) 10 | li = [] 11 | 12 | def f(n, m, l, k): 13 | if m == 0: 14 | print(' '.join(l)) 15 | for i in range(k, n + 1): 16 | if i > m: 17 | break 18 | l.append(str(i)) 19 | f(n, m - i, l, i + 1) 20 | l.pop() 21 | 22 | f(n, m, li, 1) 23 | -------------------------------------------------------------------------------- /2017校招真题/求和.py: -------------------------------------------------------------------------------- 1 | # arr = {3,34,4,12,5,2} 2 | # S = 9 3 | 4 | import numpy as np 5 | 6 | # def dp_subset(arr, s): 7 | # subset = np.zeros((len(arr), s + 1), dtype=bool) 8 | # subset[:, 0] = True 9 | # subset[0, :] = False 10 | # subset[0, arr[0]] = True 11 | # for i in range(1, len(arr)): 12 | # for s in range(1, s + 1): 13 | # if arr[i] > s: 14 | # subset[i, s] = subset[i - 1, s] 15 | # else: 16 | # A = subset[i - 1, s - arr[i]] 17 | # B = subset[i - 1, s] 18 | # subset[i, s] = A or B 19 | # r, c = subset.shape 20 | # return subset[r - 1, c - 1] 21 | 22 | def rec_subset(arr, i, s): 23 | if s == 0: 24 | return True 25 | elif i == 0: 26 | return arr[0] == s 27 | elif arr[i] > s: 28 | return rec_subset(arr, i - 1, s) 29 | else: 30 | A = rec_subset(arr, i - 1, s - arr[i]) 31 | B = rec_subset(arr, i - 1, s) 32 | return A or B 33 | -------------------------------------------------------------------------------- /2017校招真题/百度.py: -------------------------------------------------------------------------------- 1 | x = input().split() 2 | length = len(x) 3 | 4 | res = [] 5 | y = [] 6 | for i in range(length): 7 | y += str(x[i]) 8 | length1 = len(y) 9 | 10 | y = y + y 11 | # print(y) 12 | 13 | for i in range(length1): 14 | # print(y[i:(i + length1)]) 15 | if y[i:i + length1] not in res: 16 | res.append(y[i:i + length1]) 17 | else: 18 | continue 19 | 20 | print(res) 21 | print(len(res)) 22 | -------------------------------------------------------------------------------- /2017校招真题/素数对.py: -------------------------------------------------------------------------------- 1 | n = [int(i) for i in input().split()] 2 | 3 | arr, res = [], 0 4 | for i in range(2, n[0] + 1): 5 | flag = True 6 | for j in range(2, int(i ** 0.5 + 1)): 7 | if i % j == 0: 8 | flag = False 9 | break 10 | if flag: 11 | arr.append(i) 12 | # print(arr) 13 | 14 | for i in range(len(arr)): 15 | if arr[i] > n[0] / 2: 16 | break 17 | else: 18 | if n[0] - arr[i] in arr: 19 | res += 1 20 | print(res) 21 | -------------------------------------------------------------------------------- /2017校招真题/统计回文.py: -------------------------------------------------------------------------------- 1 | n1 = input() 2 | n2 = input() 3 | n = [] 4 | 5 | def huiwen(s): 6 | return s == s[::-1] 7 | 8 | count = 0 9 | for i in range(len(n1) + 1): 10 | n = n1[:i] + n2 + n1[i:] 11 | if huiwen(n): 12 | count += 1 13 | print(count) 14 | -------------------------------------------------------------------------------- /2017校招真题/美团.py: -------------------------------------------------------------------------------- 1 | # x = int(input()) 2 | # res = [] 3 | # for i in range(x - 1): 4 | # res.append(input().split()) 5 | # # print(res) 6 | # 7 | # for i in range(1, len(res)): 8 | # if res[i - 1][1] == res[i][0]: 9 | # x -= 1 10 | # print(x + 1) 11 | 12 | 13 | k, d = map(int, input().split()) 14 | l = input().split() 15 | 16 | res = [] 17 | for i in range(len(l)): 18 | if l[i] == '0' and l[i + 1] == '1': 19 | res.append(l[i]) 20 | res.append(l[i + 1]) 21 | 22 | # print(res) 23 | if res[:-1] == '1': 24 | for i in range(d): 25 | res[:(-2 - 2 * i)] = '1' 26 | 27 | print(res.count(1)) 28 | -------------------------------------------------------------------------------- /2017校招真题/藏宝图.py: -------------------------------------------------------------------------------- 1 | # 体会一下,真的很好, 贪心 2 | x = input() 3 | y = input() 4 | 5 | for i in x: 6 | if y and i==y[0]: 7 | y =y[1:] 8 | print('No' if y else 'Yes') 9 | -------------------------------------------------------------------------------- /2017校招真题/解救小易.py: -------------------------------------------------------------------------------- 1 | x = input().split() 2 | n1 = [int(i) for i in input().split()] 3 | n2 = [int(i) for i in input().split()] 4 | 5 | res = [] 6 | for i in range(len(n1)): 7 | res.append(n1[i] + n2[i] - 2) 8 | 9 | print(min(res)) 10 | -------------------------------------------------------------------------------- /2017校招真题/计算糖果.py: -------------------------------------------------------------------------------- 1 | n = int(input()) 2 | x = [int(i) for i in input().split()] 3 | 4 | sum = 0 5 | max = x[0] 6 | for i in range(n): 7 | if sum >= 0: 8 | sum += x[i] 9 | else: 10 | sum = x[i] 11 | if sum > max: 12 | max = sum 13 | print(max) 14 | -------------------------------------------------------------------------------- /2017校招真题/输入n个整数,输出出现次数大于等于数组长度一半的数。.py: -------------------------------------------------------------------------------- 1 | x = [int(i) for i in input().split()] 2 | for i in x: 3 | k = x.count(i) 4 | if k * 2 >= len(x): 5 | print(i) 6 | break 7 | -------------------------------------------------------------------------------- /2017校招真题/进制转换.py: -------------------------------------------------------------------------------- 1 | # k, d = map(int, input().split()) 2 | # 3 | # n = 0 4 | # for i in range(): 5 | # n += d ** i 6 | # if n == k: 7 | # print(i) 8 | # if n > k: 9 | # print(-1) 10 | 11 | def baseN(num, b): 12 | res = '' 13 | if num > 0: 14 | while num: 15 | res = '0123456789ABCDEFGHIGKLMNOPQRSTUVWXYZ'[num % b] + res 16 | num = num // b 17 | return res 18 | else: 19 | num = -num 20 | while num: 21 | res = '0123456789ABCDEFGHIGKLMNOPQRSTUVWXYZ'[num % b] + res 22 | num = num // b 23 | return '-' + res 24 | 25 | a, b = map(int, input().split()) 26 | print(baseN(a, b)) 27 | -------------------------------------------------------------------------------- /2017校招真题/餐厅.py: -------------------------------------------------------------------------------- 1 | # 在 m 批客人中选择 n 批上 n 个桌子 2 | n, m = [int(x) for x in input().split()] 3 | # 每个桌子可容纳的最大人数 4 | table = [int(x) for x in input().split()] 5 | # 分别表示第 i 批客人的人数和预计消费金额 6 | cus = [[int(x) for x in input().split()] for i in range(m)] 7 | 8 | # 将桌子按可容纳人数从小到大排列 9 | table.sort() 10 | # 按每批顾客的人数从小到大排序 11 | cus = sorted(cus, key=lambda x: x[0]) 12 | # 总金额 13 | money = 0 14 | 15 | for i in range(n): 16 | # 盛放第 i 个可接受的顾客批 j 17 | temp = [] 18 | # 注意 range 中要用 cus 的 length 时更新 19 | for j in range(len(cus)): 20 | if cus[j][0] > table[i]: 21 | break 22 | temp.append(cus[j]) 23 | # 按消费金额排序 24 | temp = sorted(temp, key=lambda x: x[1]) 25 | if temp: 26 | money += temp[-1][1] 27 | # 此批客人已就坐 28 | cus.remove() 29 | print(money) 30 | -------------------------------------------------------------------------------- /2017校招真题/饥饿的小易.py: -------------------------------------------------------------------------------- 1 | ''' 2 | f(x) = 4x+3, g(x) = 8x+7 3 | 计算得到以下两个规律: 4 | g(f(x)) = f(g(x)) 即 f 和 g 的执行顺序没有影响 5 | f(f(f(x))) = g(g(x)) 即做3次 f 变换等价于做2次 g 变换 6 | 由于规律(1)对于一个可行方案,我们可以调整其变换的顺序。如ffggfggff,我们可以转化成fffffgggg 7 | 由于规律(2),并且为了使执行次数最少,每3个f我们可以转化成2个g,如fffffgggg,可以转化成ffgggggg 8 | 因此一个最优的策略,f的执行次数只能为0,1,2.对于输入的x,我们只需要求x,4*x+3, 9 | (4*x+3)+3的最小执行次数就可以了。 10 | ''' 11 | 12 | 13 | 14 | # x = int(input()) 15 | # y1 = 4 * x + 3 16 | # y2 = 8 * x + 7 17 | # 18 | # if y1 % 1000000007 == 0: 19 | # print(y1 // 1000000007) 20 | # if y2 % 1000000007 == 0: 21 | # print(y2 // 1000000007) 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Interview-code-practice-python 2 | 3 | 这是我为找工作准备的各类面试题,全部使用python实现 4 | 5 | 包括  剑指offer    csdn博客:http://blog.csdn.net/u012193416/article/details/79253398 6 | -------------------------------------------------------------------------------- /剑指offer/不用加减乘除做加法.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。 3 | ''' 4 | 5 | ''' 6 | 思路一:用sum函数,但是特别注意sum()求和里面是个[]列表对象,直接输入num,num2是不行的 7 | 8 | 26ms 9 | 5632k 10 | ''' 11 | 12 | # -*- coding:utf-8 -*- 13 | class Solution: 14 | def Add(self, num1, num2): 15 | # write code here 16 | return sum([num1,num2]) 17 | 18 | ''' 19 | 思路二: 20 | 首先看十进制是如何做的: 5+7=12,三步走 21 | 第一步:相加各位的值,不算进位,得到2。 22 | 第二步:计算进位值,得到10. 如果这一步的进位值为0,那么第一步得到的值就是最终结果。 23 | 24 | 第三步:重复上述两步,只是相加的值变成上述两步的得到的结果2和10,得到12。 25 | 26 | 同样我们可以用三步走的方式计算二进制值相加: 5-101,7-111 第一步:相加各位的值,不算进位,得到010, 27 | 二进制每位相加就相当于各位做异或操作,101^111。 28 | 29 | 第二步:计算进位值,得到1010,相当于各位做与操作得到101,再向左移一位得到1010,(101&111)<<1。 30 | 31 | 第三步重复上述两步, 各位相加 010^1010=1000,进位值为100=(010&1010)<<1。 32 | 继续重复上述两步:1000^100 = 1100,进位值为0,跳出循环,1100为最终结果。 33 | 34 | 超时了 35 | ''' 36 | 37 | # -*- coding:utf-8 -*- 38 | class Solution: 39 | def Add(self, num1, num2): 40 | # write code here 41 | while num2: 42 | # 异或运算相当于只求和不进位 43 | sum = num1 ^ num2 44 | # 与操作,并向左移一位,相当于求进位 45 | carray = (num1 & num2) << 1 46 | num1 = sum 47 | num2 = carray 48 | return num1 -------------------------------------------------------------------------------- /剑指offer/丑数.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:把只包含因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含因子7。 3 | 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。 4 | ''' 5 | 6 | ''' 7 | 思路:按顺序把每个丑数放在数组中,求下一个丑数 8 | 下一个丑数必定由有数组中的某一个丑数A * 2, B * 3, C * 5 的中的最小值得来。 9 | 分析:在数组中必定有一个丑数M2, 在它之前的数 * 2 都小于当前最大丑数, 在它之后的数 * 2都大于当前最大丑数, 10 | 同样有M3, M5 11 | 12 | notes:题目的意思应该是质数因子,因为8的因子有1,2,4,8,显然不符合要求的,但是质数只有2 13 | 36ms 14 | 5732k 15 | ''' 16 | 17 | # -*- coding:utf-8 -*- 18 | class Solution: 19 | def GetUglyNumber_Solution(self, index): 20 | # write code here 21 | if index < 1: 22 | return 0 23 | res = [1] 24 | t2 = t3 = t5 = 0 25 | 26 | nextdex = 1 27 | while nextdex < index: 28 | minNum = min(res[t2] * 2, res[t3] * 3, res[t5] * 5) 29 | res.append(minNum) 30 | 31 | # 前进的步伐还是很小的,没一个数都考虑到了 32 | while res[t2] * 2 <= minNum: 33 | t2 += 1 34 | while res[t3] * 3 <= minNum: 35 | t3 += 1 36 | while res[t5] * 5 <= minNum: 37 | t5 += 1 38 | 39 | nextdex += 1 40 | 41 | return res[nextdex - 1] 42 | -------------------------------------------------------------------------------- /剑指offer/两个合并排序的链表.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。 3 | ''' 4 | 5 | ''' 6 | 方法一:递归版本,注意比较很好理解 7 | 30ms 8 | 5670k 9 | ''' 10 | 11 | # -*- coding:utf-8 -*- 12 | # class ListNode: 13 | # def __init__(self, x): 14 | # self.val = x 15 | # self.next = None 16 | class Solution: 17 | # 返回合并后列表 18 | def Merge(self, pHead1, pHead2): 19 | # write code here 20 | if pHead1 == None: 21 | return pHead2 22 | elif pHead2 == None: 23 | return pHead1 24 | 25 | mergepHead = None 26 | if pHead1.val <= pHead2.val: 27 | mergepHead = pHead1 28 | mergepHead.next = self.Merge(pHead1.next, pHead2) 29 | elif pHead1.val > pHead2.val: 30 | mergepHead = pHead2 31 | mergepHead.next = self.Merge(pHead1, pHead2.next) 32 | 33 | return mergepHead 34 | 35 | ''' 36 | 版本二:非递归版本 37 | 23ms 38 | 5676k 39 | ''' 40 | 41 | # -*- coding:utf-8 -*- 42 | class ListNode: 43 | def __init__(self, x): 44 | self.val = x 45 | self.next = None 46 | 47 | class Solution: 48 | # 返回合并后列表 49 | def Merge(self, pHead1, pHead2): 50 | # write code here 51 | dummy = ListNode(0) 52 | pHead = dummy 53 | 54 | while pHead1 and pHead2: 55 | if pHead1.val >= pHead2.val: 56 | dummy.next = pHead2 57 | pHead2 = pHead2.next 58 | else: 59 | dummy.next = pHead1 60 | pHead1 = pHead1.next 61 | 62 | dummy = dummy.next 63 | if pHead1: 64 | dummy.next = pHead1 65 | elif pHead2: 66 | dummy.next = pHead2 67 | return pHead.next -------------------------------------------------------------------------------- /剑指offer/两个栈实现队列.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。 3 | ''' 4 | 5 | ''' 6 | 这一题还是挺难的,有两个栈stackA、stackB,A是入栈的,B是出栈的,入栈时,直接进入A即可,出栈时,先判断是否有元素, 7 | 如果B没有元素,pop肯定报错,应该先将A中所有的元素压倒B里面,再pop最上面一个元素,如果B中有就直接pop出,就可以, 8 | 这是最优的思路,两个栈实现了先进后出,在一起又实现了队列的先进先出。 9 | 23ms 10 | 5628k 11 | ''' 12 | 13 | # -*- coding:utf-8 -*- 14 | class Solution: 15 | def __init__(self): 16 | self.stackA = [] 17 | self.stackB = [] 18 | 19 | def push(self, node): 20 | # write code here 21 | self.stackA.append(node) 22 | 23 | def pop(self): 24 | # return xx 25 | if self.stackB: 26 | return self.stackB.pop() 27 | elif not self.stackA: 28 | return None 29 | else: 30 | while self.stackA: 31 | self.stackB.append(self.stackA.pop()) 32 | return self.stackB.pop() 33 | 34 | -------------------------------------------------------------------------------- /剑指offer/两个链表的第一个公共节点.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入两个链表,找出它们的第一个公共结点 3 | ''' 4 | 5 | ''' 6 | 思路:共同节点,意味着从共同节点开始之后所有的节点数都是相同的,这是链表,只要有一个共同节点,那么之后所有的指向 7 | 也是重复的。先依次遍历两个链表,记录两个链表的长度m和n,如果 m > n,那么我们就先让长度为m的链表走m-n个结点,然后 8 | 两个链表同时遍历,当遍历到相同的结点的时候停止即可。对于 m < n,同理。 9 | 10 | 32ms 11 | 5632k 12 | ''' 13 | 14 | # -*- coding:utf-8 -*- 15 | # class ListNode: 16 | # def __init__(self, x): 17 | # self.val = x 18 | # self.next = None 19 | class Solution: 20 | def FindFirstCommonNode(self, pHead1, pHead2): 21 | # write code here 22 | Length1 = self.GetLength(pHead1) 23 | Length2 = self.GetLength(pHead2) 24 | LengthDiff = abs(Length1 - Length2) 25 | 26 | if Length1 > Length2: 27 | pHeadLong = pHead1 28 | pHeadShort = pHead2 29 | else: 30 | pHeadLong = pHead2 31 | pHeadShort = pHead1 32 | 33 | for i in range(LengthDiff): 34 | pHeadLong = pHeadLong.next 35 | 36 | while pHeadLong != None and pHeadShort != None and pHeadLong != pHeadShort: 37 | pHeadLong = pHeadLong.next 38 | pHeadShort = pHeadShort.next 39 | 40 | return pHeadLong 41 | 42 | def GetLength(self, pHead): 43 | length = 0 44 | while pHead: 45 | pHead = pHead.next 46 | length += 1 47 | return length 48 | -------------------------------------------------------------------------------- /剑指offer/二叉搜索树和双向链表.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。 3 | 要求不能创建任何新的结点,只能调整树中结点指针的指向。 4 | ''' 5 | 6 | ''' 7 | 思路:由于输入的一个二叉搜索树,其左子树大于右子树的值,这位后面的排序做了准备,因为只需要中序遍历即可,将所有 8 | 的节点保存到一个列表,。对这个list[:-1]进行遍历,每个节点的right设为下一个节点,下一个节点的left设为上一个节点。 9 | 10 | 29ms 11 | 5632k 12 | ''' 13 | 14 | # -*- coding:utf-8 -*- 15 | # class TreeNode: 16 | # def __init__(self, x): 17 | # self.val = x 18 | # self.left = None 19 | # self.right = None 20 | class Solution: 21 | def Convert(self, pRootOfTree): 22 | # write code here 23 | if not pRootOfTree: 24 | return 25 | 26 | self.attr = [] 27 | self.midorder(pRootOfTree) 28 | for i, v in enumerate(self.attr[:-1]): 29 | v.right = self.attr[i + 1] 30 | self.attr[i + 1].left = v 31 | return self.attr[0] 32 | 33 | def midorder(self, root): 34 | if not root: 35 | return 36 | self.midorder(root.left) 37 | self.attr.append(root) 38 | self.midorder(root.right) 39 | 40 | -------------------------------------------------------------------------------- /剑指offer/二叉搜索树的后序遍历序列.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。 3 | 假设输入的数组的任意两个数字都互不相同。 4 | ''' 5 | 6 | ''' 7 | 二叉搜索树即是二叉排序树, 8 | 1. 后序遍历序列的最后一个元素为二叉树的根节点; 9 | 2. 二叉搜索树左子树上所有的结点均小于根结点、右子树所有的结点均大于根结点。 10 | 11 | 算法步骤如下: 12 | 1. 找到根结点; 13 | 2. 遍历序列,找到第一个大于等于根结点的元素i,则i左侧为左子树、i右侧为右子树; 14 | 3. 我们已经知道i左侧所有元素均小于根结点,那么再依次遍历右侧,看是否所有元素均大于根结点;若出现小于根结点的元素,则直接返回false;若右侧全都大于根结点,则: 15 | 4. 分别递归判断左/右子序列是否为后序序列; 16 | 17 | 25ms 18 | 5632k 19 | ''' 20 | 21 | # -*- coding:utf-8 -*- 22 | class Solution: 23 | def VerifySquenceOfBST(self, sequence): 24 | # write code here 25 | if not sequence: 26 | return False 27 | 28 | root = sequence[-1] 29 | 30 | i = 0 31 | for node in sequence[:-1]: 32 | if node > root: 33 | break 34 | i += 1 35 | 36 | for node in sequence[i:-1]: 37 | if node < root: 38 | return False 39 | 40 | left = True 41 | # i>0 意味i =0 或者1 的时候,两个元素在二叉树没有排序之分的,但是3个元素就有了左右子树之分 42 | if i > 0: 43 | left = self.VerifySquenceOfBST(sequence[:i]) 44 | 45 | right = True 46 | # len(sequence)>3才有左右之分的 47 | if i < len(sequence) - 2 and left: 48 | right = self.VerifySquenceOfBST(sequence[i + 1:]) 49 | 50 | return left and right 51 | 52 | 53 | -------------------------------------------------------------------------------- /剑指offer/二叉搜索树的第k个节点.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:给定一颗二叉搜索树,请找出其中的第k大的结点。例如, 5 / \ 3 7 /\ /\ 2 4 6 8 中,按结点数值大小顺序 3 | 第三个结点的值为4。 4 | ''' 5 | 6 | ''' 7 | 思路:二叉搜索树按照中序遍历的顺序打印出来正好就是排序好的顺序。 8 | 所以,按照中序遍历顺序找到第k个结点就是结果。 9 | 10 | 28ms 11 | 5632k 12 | ''' 13 | 14 | # -*- coding:utf-8 -*- 15 | # class TreeNode: 16 | # def __init__(self, x): 17 | # self.val = x 18 | # self.left = None 19 | # self.right = None 20 | 21 | class Solution: 22 | # 返回对应节点TreeNode 23 | def KthNode(self, pRoot, k): 24 | # write code here 25 | global result 26 | result = [] 27 | middle = self.midorder(pRoot) 28 | if k <= 0 or len(middle) < k: 29 | return None 30 | else: 31 | return middle[k - 1] 32 | 33 | def midorder(self, pRoot): 34 | if not pRoot: 35 | return [] 36 | self.midorder(pRoot.left) 37 | result.append(pRoot) 38 | self.midorder(pRoot.right) 39 | return result -------------------------------------------------------------------------------- /剑指offer/二叉树中和为某一值的路径.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。 3 | 路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。 4 | ''' 5 | 6 | ''' 7 | 思路: 8 | 递归先序遍历树, 把结点加入路径。使用列表结构存树结构 9 | 若该结点是叶子结点则比较当前路径和是否等于期待和,叶子节点说明该路径应该截止了 10 | 弹出结点,每一轮递归返回到父结点时,当前路径也应该回退一个结点。 11 | 12 | 25ms 13 | 5670k 14 | ''' 15 | 16 | # -*- coding:utf-8 -*- 17 | # class TreeNode: 18 | # def __init__(self, x): 19 | # self.val = x 20 | # self.left = None 21 | # self.right = None 22 | class Solution: 23 | # 返回二维列表,内部每个列表表示找到的路径 24 | def FindPath(self, root, expectNumber): 25 | # write code here 26 | if not root: 27 | return [] 28 | result = [] 29 | 30 | def FindPath2(root, path, currentNum): 31 | currentNum += root.val 32 | # root使用append转成了列表,因为最后要一个序列,root本身还是树结构 33 | path.append(root) 34 | # 判断是不是到叶子节点了,到叶子节点了就要判断值的和是不是相等 35 | flag = root.left == None and root.right == None 36 | # 返回值是一个等于整数的序列 37 | if currentNum == expectNumber and flag: 38 | onepath = [] 39 | for node in path: 40 | onepath.append(node.val) 41 | result.append(onepath) 42 | 43 | if currentNum < expectNumber: 44 | if root.left: 45 | FindPath2(root.left, path, currentNum) 46 | if root.right: 47 | FindPath2(root.right, path, currentNum) 48 | # 拿到一个正确的路径后要弹出,回到上一次父节点继续递归 49 | path.pop() 50 | 51 | FindPath2(root, [], 0) 52 | return result 53 | -------------------------------------------------------------------------------- /剑指offer/二叉树的下一个节点.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右 3 | 子结点,同时包含指向父结点的指针。 4 | ''' 5 | 6 | ''' 7 | 思路: 8 | (1) 若该节点存在右子树:则下一个节点为右子树最左子节点 9 | (2) 若该节点不存在右子树:这时分两种情况: 10 | 2.1 该节点为父节点的左子节点,则下一个节点为其父节点 11 | 2.2 该节点为父节点的右子节点,则沿着父节点向上遍历,知道找到一个节点的父节点的左子节点为该节点, 12 | 则该节点的父节点下一个节点(如图节点I,沿着父节点一直向上查找找到B(B为其父节点的左子节点), 13 | 则B的父节点A为下一个节点)。 14 | 15 | 34ms 16 | 5632k 17 | ''' 18 | 19 | # -*- coding:utf-8 -*- 20 | # class TreeLinkNode: 21 | # def __init__(self, x): 22 | # self.val = x 23 | # self.left = None 24 | # self.right = None 25 | # self.next = None 26 | class Solution: 27 | def GetNext(self, pNode): 28 | # write code here 29 | if not pNode: 30 | return 31 | # 该节点有右子节点,那么该节点的下一个节点就是有自己节点的最左节点 32 | if pNode.right != None: 33 | pNode = pNode.right 34 | while pNode.left != None: 35 | pNode = pNode.left 36 | return pNode 37 | # 该节点没有右子节点 38 | # 该节点为父节点的左子节点 39 | elif pNode.next != None and pNode.next.left == pNode: 40 | return pNode.next 41 | # 该节点为父节点的右子节点,它的下一个节点就是其父节点作为父节点的左子节点的下一个节点 42 | elif pNode.next != None and pNode.next.right == pNode: 43 | while pNode.next != None and pNode.next.left != pNode: 44 | pNode = pNode.next 45 | return pNode.next 46 | else: 47 | # 节点无父节点,即节点为根节点 48 | return pNode.next 49 | 50 | 51 | -------------------------------------------------------------------------------- /剑指offer/二叉树的深度.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径, 3 | 最长路径的长度为树的深度。 4 | ''' 5 | 6 | ''' 7 | 思路:利用递归实现。如果一棵树只有一个结点,那么它的深度为1。递归的时候无需判断左右子树是否存在,因为如果该节点 8 | 为叶节点,它的左右子树不存在,那么在下一级递归的时候,直接return 0。同时,记得每次递归返回值的时候,深度加一操 9 | 作,因为计算深度是从根节点下面一个节点开始计算的。 10 | 11 | 25ms 12 | 5632k 13 | ''' 14 | 15 | # -*- coding:utf-8 -*- 16 | # class TreeNode: 17 | # def __init__(self, x): 18 | # self.val = x 19 | # self.left = None 20 | # self.right = None 21 | class Solution: 22 | def TreeDepth(self, pRoot): 23 | # write code here 24 | if pRoot == None: 25 | return 0 26 | return max(self.TreeDepth(pRoot.left), self.TreeDepth(pRoot.right)) + 1 27 | -------------------------------------------------------------------------------- /剑指offer/二叉树的镜像.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:操作给定的二叉树,将其变换为源二叉树的镜像。 3 | ''' 4 | 5 | ''' 6 | 递归 7 | 23ms 8 | 5492k 9 | ''' 10 | 11 | # -*- coding:utf-8 -*- 12 | # class TreeNode: 13 | # def __init__(self, x): 14 | # self.val = x 15 | # self.left = None 16 | # self.right = None 17 | class Solution: 18 | # 返回镜像树的根节点 19 | def Mirror(self, root): 20 | # write code here 21 | if not root: 22 | return root 23 | root.left,root.right = root.right,root.left 24 | self.Mirror(root.left) 25 | self.Mirror(root.right) 26 | return root 27 | 28 | 29 | -------------------------------------------------------------------------------- /剑指offer/二维数组中的查找.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。 3 | 请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 4 | ''' 5 | 6 | ''' 7 | 方法一: 循环迭代查找,不是最优 8 | 284ms 9 | 5760k 10 | ''' 11 | 12 | class Solution: 13 | # array 二维列表 14 | def Find(self, target, array): 15 | # write code here 16 | if not array: 17 | return 18 | row = len(array) 19 | col = len(array[0]) 20 | 21 | for i in range(row): 22 | for j in range(col): 23 | if target == array[i][j]: 24 | return True 25 | 26 | return False 27 | 28 | ''' 29 | 方法二:上述方法的时间复杂度是O(n^2),最优化的方式是从左下或者右上开始搜索 30 | 从右上开始搜索,如果数组中的数比该数要大,那么想左移动一位,如果数组中的数比该数小,向下移动一位, 31 | 因为数组本身是从左到右依次增大,从上到下一次增大 32 | 281ms 33 | 5644k 34 | ''' 35 | 36 | class Solution: 37 | # array 二维列表 38 | def Find(self, target, array): 39 | # write code here 40 | raw = len(array) 41 | col = len(array[0]) 42 | 43 | i = 0 44 | j = col - 1 45 | while i < raw and j >= 0: 46 | if array[i][j] > target: 47 | j -= 1 48 | elif array[i][j] < target: 49 | i += 1 50 | else: 51 | return True 52 | return False 53 | -------------------------------------------------------------------------------- /剑指offer/二进制中1的个数.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。 3 | ''' 4 | 5 | ''' 6 | 如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1 7 | 后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。 8 | 举个例子:一个二进制数1100,从右边数起第三位是处于最右边的一个1。减去1后,第三位变成0,它后面的两位0变成了1, 9 | 而前面的1保持不变,因此得到的结果是1011.我们发现减1的结果是把最右边的一个1开始的所有位都取反了。这个时候如果我们 10 | 再把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。如1100&1011=1000.也就是 11 | 说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以进行多少 12 | 次这样的操作。 13 | 14 | 但是负数使用补码表示的,对于负数,最高位为1,而负数在计算机是以补码存在的,往右移,符号位不变,符号位1往右移, 15 | 最终可能会出现全1的情况,导致死循环。与0xffffffff相与,就可以消除负数的影响 16 | 17 | 24ms 18 | 5632k 19 | ''' 20 | 21 | # -*- coding:utf-8 -*- 22 | class Solution: 23 | def NumberOf1(self, n): 24 | # write code here 25 | count = 0 26 | if n<0: 27 | n = n & 0xffffffff 28 | while n: 29 | count += 1 30 | n = n & (n-1) 31 | return count 32 | -------------------------------------------------------------------------------- /剑指offer/从上往下打印二叉树.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:从上往下打印出二叉树的每个节点,同层节点从左至右打印 3 | ''' 4 | 5 | ''' 6 | 广度优先层次遍历,利用一个队列来实现 7 | 层序遍历的基本过程是: 8 | 先根节点入队,然后: 9 | 1.从队列中取出一个元素 10 | 2.访问该元素所指的结点 11 | 3.若该元素所指结点的左、右孩子结点非空,则将其左、右孩子的指针顺序入队 12 | 13 | 利用队列,首先将根节点放入队列中,取队列的首节点,把值存进列表,然后考虑左右指针,把指针放进列表,在存值 14 | 15 | 33ms 16 | 5900k 17 | ''' 18 | 19 | # -*- coding:utf-8 -*- 20 | # class TreeNode: 21 | # def __init__(self, x): 22 | # self.val = x 23 | # self.left = None 24 | # self.right = None 25 | class Solution: 26 | # 返回从上到下每个节点值列表,例:[1,2,3] 27 | def PrintFromTopToBottom(self, root): 28 | # write code here 29 | if not root: 30 | return [] 31 | queue = [] 32 | result = [] 33 | 34 | queue.append(root) 35 | while len(queue) > 0: 36 | node = queue.pop(0) 37 | result.append(node.val) 38 | if node.left: 39 | queue.append(node.left) 40 | if node.right: 41 | queue.append(node.right) 42 | return result -------------------------------------------------------------------------------- /剑指offer/从尾到头打印链表.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入一个链表,从尾到头打印链表每个节点的值 3 | ''' 4 | 5 | ''' 6 | 方法一:使用extend,在尾部插入,其实最关键在于[::-1],只不过输入数据多样化,有可能还是集合,所以转成列表 7 | 这个方法效率应该还可以,先存入vector,再反转vector 8 | 26ms 9 | 5512k 10 | ''' 11 | 12 | # -*- coding:utf-8 -*- 13 | # class ListNode: 14 | # def __init__(self, x): 15 | # self.val = x 16 | # self.next = None 17 | 18 | class Solution: 19 | # 返回从尾部到头部的列表值序列,例如[1,2,3] 20 | def printListFromTailToHead(self, listNode): 21 | # write code here 22 | if not listNode: 23 | return [] 24 | 25 | result = [] 26 | while listNode.next is not None: 27 | result.extend([listNode.val]) 28 | listNode = listNode.next 29 | result.extend([listNode.val]) 30 | 31 | return result[::-1] 32 | 33 | ''' 34 | 方法二: 使用insert直接在头部插入 35 | 26ms 36 | 6336k 37 | ''' 38 | 39 | # -*- coding:utf-8 -*- 40 | # class ListNode: 41 | # def __init__(self, x): 42 | # self.val = x 43 | # self.next = None 44 | 45 | class Solution: 46 | # 返回从尾部到头部的列表值序列,例如[1,2,3] 47 | def printListFromTailToHead(self, listNode): 48 | # write code here 49 | if not listNode: 50 | return [] 51 | 52 | result = [] 53 | head = listNode 54 | 55 | while head: 56 | result.insert(0, head.val) 57 | head = head.next 58 | return result 59 | -------------------------------------------------------------------------------- /剑指offer/删除链表中重复的节点.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 3 | 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5 4 | ''' 5 | 6 | ''' 7 | 思路一:将链表里面所有的数存在一个列表里面,然后把列表里面只出现一次的数提取出来,在新建一个链表放进去 8 | 9 | 28ms 10 | 5632k 11 | ''' 12 | 13 | # -*- coding:utf-8 -*- 14 | class ListNode: 15 | def __init__(self, x): 16 | self.val = x 17 | self.next = None 18 | 19 | class Solution: 20 | def deleteDuplication(self, pHead): 21 | # write code here 22 | res = [] 23 | while pHead: 24 | res.append(pHead.val) 25 | pHead = pHead.next 26 | 27 | # filter函数和map相似,但是filter是返回布尔值去去输入列表进行判断 28 | res = list(filter(lambda c: res.count(c) == 1, res)) 29 | 30 | newlist = ListNode(0) 31 | pre = newlist 32 | for i in res: 33 | node = ListNode(i) 34 | pre.next = node 35 | pre = pre.next 36 | return newlist.next 37 | 38 | ''' 39 | 思路二: 40 | 是有两个循环判断的控制,上一个是主要对应2 - 3 - 4这种情况的,可以很快的把头指针移过来,下面这个循环是对应 41 | 存在相同值的,不断循环找下一个值。 42 | 头指针 43 | PreNode 44 | Head - 1 - 1 - 1 - 2 - 2 - 3 - 4 - 4 - 4 - 5 - 5 - 6 - null 45 | pNode 46 | NextNode 47 | False 48 | pToBeDel 49 | PreNode 50 | 51 | 35ms 52 | 6008k 53 | ''' 54 | 55 | # -*- coding:utf-8 -*- 56 | # class ListNode: 57 | # def __init__(self, x): 58 | # self.val = x 59 | # self.next = None 60 | class Solution: 61 | def deleteDuplication(self, pHead): 62 | # write code here 63 | if pHead == None: 64 | return 65 | preHead = None 66 | pNode = pHead 67 | while pNode != None: 68 | needDelete = False 69 | nextNode = pNode.next 70 | if nextNode != None and nextNode.val == pNode.val: 71 | needDelete = True 72 | if needDelete == False: 73 | preHead = pNode 74 | pNode = pNode.next 75 | else: 76 | nodeVal = pNode.val 77 | pToBeDel = pNode 78 | while pToBeDel != None and pToBeDel.val == nodeVal: 79 | pToBeDel = pToBeDel.next 80 | if preHead == None: 81 | pHead = pToBeDel 82 | pNode = pToBeDel 83 | continue 84 | else: 85 | preHead.next = pToBeDel 86 | pNode = preHead 87 | return pHead 88 | -------------------------------------------------------------------------------- /剑指offer/剑指offer-python实现.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leeguandong/Interview-code-practice-python/86933f82f3553dfca16055977d7366b106b511bd/剑指offer/剑指offer-python实现.docx -------------------------------------------------------------------------------- /剑指offer/包含min函数的栈.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。 3 | ''' 4 | 5 | ''' 6 | 我们可以设计两个栈:Stack和StackMin,一个就是普通的栈,另外一个存储push进来的最小值。 7 | 首先是push操作: 8 | 每次压入的数据newNum都push进Stack中,然后判断StackMin是否为空,如果为空那也把newNum同步压入StackMin里; 9 | 如果不为空,就先比较newNum和StackMin中栈顶元素的大小,如果newNum较大,那就不压入StackMin里,只压入一个最小值 10 | 否则就同步压入StackMin里。弹出时,同步弹出,这是一个栈结构。 11 | 12 | 24ms 13 | 5760k 14 | ''' 15 | 16 | # -*- coding:utf-8 -*- 17 | class Solution: 18 | def __init__(self): 19 | self.stack = [] 20 | self.minstack = [] 21 | 22 | def push(self, node): 23 | # write code here 24 | self.stack.append(node) 25 | if self.minstack == [] or node < self.min(): 26 | self.minstack.append(node) 27 | else: 28 | self.minstack.append(self.min()) 29 | 30 | def pop(self): 31 | # write code here 32 | if self.minstack == [] or self.stack == []: 33 | return None 34 | self.minstack.pop() 35 | self.stack.pop() 36 | 37 | def top(self): 38 | # write code here 39 | return self.stack[-1] 40 | 41 | def min(self): 42 | # write code here 43 | return self.minstack[-1] -------------------------------------------------------------------------------- /剑指offer/反转链表.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入一个链表,反转链表后,输出链表的所有元素。 3 | ''' 4 | 5 | ''' 6 | 这一题还是蛮难的。链表的翻转,例如 1->2->3->4->5 ==> 5->4->3->2->1 7 | tmp = pHead.next 把当前节点的下一个节点保存下来 8 | pHead.next = pre 把前一个节点移到当前节点的下一个节点,因为要翻转节点,pre始终指向要反转节点的首节点 9 | pre = pHead 当前节点向后移一位 10 | pHead = tmp 把之前保存的下一个节点指针再给当前节点接着翻转 11 | 33ms 12 | 6016k 13 | ''' 14 | 15 | # -*- coding:utf-8 -*- 16 | # class ListNode: 17 | # def __init__(self, x): 18 | # self.val = x 19 | # self.next = None 20 | class Solution: 21 | # 返回ListNode 22 | def ReverseList(self, pHead): 23 | # write code here 24 | if not pHead or not pHead.next: 25 | return pHead 26 | pre = None 27 | while pHead: 28 | tmp = pHead.next 29 | pHead.next = pre 30 | pre = pHead 31 | pHead = tmp 32 | return pre 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /剑指offer/变态青蛙跳.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法 3 | ''' 4 | 5 | ''' 6 | 因为n级台阶,第一步有n种跳法:跳1级、跳2级、到跳n级 7 | 跳1级,剩下n-1级,则剩下跳法是f(n-1) 8 | 跳2级,剩下n-2级,则剩下跳法是f(n-2) 9 | 所以f(n)=f(n-1)+f(n-2)+...+f(1) 10 | 因为f(n-1)=f(n-2)+f(n-3)+...+f(1) 11 | 所以f(n)=2*f(n-1) 12 | 然后求解这个无穷级数的和,正确答案应该是:每次至少跳一个,至多跳n个,一共有f(n)=2n-1种跳法 13 | 29ms 14 | 5632k 15 | ''' 16 | 17 | # -*- coding:utf-8 -*- 18 | class Solution: 19 | def jumpFloorII(self, number): 20 | # write code here 21 | return 2**(number-1) -------------------------------------------------------------------------------- /剑指offer/和为s的两个数字.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S, 3 | 输出两个数的乘积最小的 4 | ''' 5 | 6 | ''' 7 | 思路:设定两个指针,一个指向数组的起点,一个指向数组的终点,然后对两个数字求和,如果和大于目标值,则把后一个指针前移, 8 | 如果和小于目标值,则把前一个指针后移。两个指针交汇的时候如果还没找到,就终止操作。 9 | 10 | 37ms 11 | 5628k 12 | ''' 13 | 14 | # -*- coding:utf-8 -*- 15 | class Solution: 16 | def FindNumbersWithSum(self, array, tsum): 17 | # write code here 18 | if array == None or len(array) <= 0 or array[-1] + array[-2] < tsum: 19 | return [] 20 | start = 0 21 | end = len(array) - 1 22 | while start < end: 23 | if array[start] + array[end] < tsum: 24 | start += 1 25 | elif array[start] + array[end] > tsum: 26 | end -= 1 27 | else: 28 | return [array[start], array[end]] 29 | return [] 30 | 31 | 32 | -------------------------------------------------------------------------------- /剑指offer/和为s的连续整数序列.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此, 3 | 他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20, 4 | 21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck! 5 | ''' 6 | 7 | ''' 8 | 思路:设定两个指针,先分别指向数字1和数字2,并设这两个指针为small和big,对small和big求和,如果和大于目标值, 9 | 则从当前和中删除small值,并把small值加一,如果和小于目标值,则把big值加一,再把新的big值加入和中。如果和等于 10 | 目标值,就输出small到big的序列,同时把big加一并加入和中,继续之前的操作。 11 | 12 | 举例看起来更好理解一点,虽然是while循环里面没有做small到big之间的连接加减,但是由于都是从相邻出发,加和都是基于 13 | 1 2 3相邻数基础之上的加和,大了就对第一个数不断减,小了就对最后一个数不断加即可。 14 | 举例: 输入 tsum = 5 15 | 1 2 16 | middle = 3 cursum = 3 17 | 1 < 3: 18 | 3 < 5: 19 | 1 2 3 20 | cursum = 1 + 2 + 3 = 6 21 | 6 > 5: 22 | cursum - small = 6 - 1 = 5 23 | return 2 3 24 | 25 | 30ms 26 | 5620k 27 | ''' 28 | 29 | # -*- coding:utf-8 -*- 30 | class Solution: 31 | def FindContinuousSequence(self, tsum): 32 | # write code here 33 | if tsum < 3: 34 | return [] 35 | small = 1 36 | big = 2 37 | middle = (tsum + 1) // 2 38 | cursum = big + small 39 | output = [] 40 | 41 | while small < middle: 42 | if cursum == tsum: 43 | output.append(list(range(small, big + 1))) 44 | while cursum > tsum and small < middle: 45 | cursum -= small 46 | small += 1 47 | if cursum == tsum: 48 | output.append(list(range(small, big + 1))) 49 | big += 1 50 | cursum += big 51 | return output 52 | -------------------------------------------------------------------------------- /剑指offer/圆圈中最后剩下的数.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了 3 | 一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。 4 | 每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始, 5 | 继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额 6 | 有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1) 7 | ''' 8 | 9 | ''' 10 | 思路:约瑟夫环问题 11 | 递推公式:f[i] = (f[i-1]+m)%i 12 | 详细解释:http://blog.csdn.net/u012505432/article/details/51747181 13 | 14 | 26ms 15 | 5632k 16 | ''' 17 | 18 | # -*- coding:utf-8 -*- 19 | class Solution: 20 | def LastRemaining_Solution(self, n, m): 21 | # write code here 22 | if n < 1 or m < 1: 23 | return -1 24 | temp = 0 25 | for i in range(1, n + 1): 26 | temp = (temp + m) % i 27 | return temp 28 | 29 | -------------------------------------------------------------------------------- /剑指offer/坐旋转字符串.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。 3 | 对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后 4 | 的结果,即“XYZdefabc”。是不是很简单?OK,搞定它 5 | ''' 6 | 7 | ''' 8 | 思路一: 9 | 10 | 29ms 11 | 5760k 12 | ''' 13 | 14 | # -*- coding:utf-8 -*- 15 | class Solution: 16 | def LeftRotateString(self, s, n): 17 | # write code here 18 | return s[n:] + s[:n] 19 | 20 | ''' 21 | 思路二:对原字符串进行扩充两倍,在这个基础上直接从要反转的地方取就可以,相当于前n个字符串翻转了,思想非常好 22 | 23 | 28ms 24 | 5760k 25 | ''' 26 | 27 | # -*- coding:utf-8 -*- 28 | class Solution: 29 | def LeftRotateString(self, s, n): 30 | # write code here 31 | if not s: 32 | return '' 33 | length = len(s) 34 | s += s 35 | return s[n:length + n] 36 | 37 | ''' 38 | 尽量避免使用内置函数 39 | 思路三:首先需要写一个reverse函数,把任何输入的字符串完全翻转。然后根据题目中给出的左旋转字符串的个数n, 40 | 用全字符串长度length减去旋转字符串个数n,求得对于新的字符串应该在哪一位进行旋转,然后分别旋转前[:length-n]子 41 | 串和[length-n:]子串,重新拼接两个子串即可。 42 | 举例: n=2 43 | 1 2 3 4 5 44 | 5 4 3 2 1 整体反转 45 | 3 4 5 1 2 对于5-2=3部分翻转,对于最后2 1再部分翻转 46 | 47 | 28ms 48 | 5760k 49 | ''' 50 | 51 | # -*- coding:utf-8 -*- 52 | class Solution: 53 | def LeftRotateString(self, s, n): 54 | # write code here 55 | if not s or len(s) < n or n < 0: 56 | return '' 57 | s = list(s) 58 | length = len(s) 59 | s = self.Reverse(s) 60 | s1 = self.Reverse(s[:length - n]) 61 | s2 = self.Reverse(s[length - n:]) 62 | result = ''.join(s1) + ''.join(s2) 63 | return result 64 | 65 | def Reverse(self, s): 66 | start = 0 67 | end = len(s) - 1 68 | while start < end: 69 | s[start], s[end] = s[end], s[start] 70 | start += 1 71 | end -= 1 72 | return s 73 | -------------------------------------------------------------------------------- /剑指offer/复杂链表的复制.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点), 3 | 返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空) 4 | ''' 5 | 6 | ''' 7 | 思路:1. 根据旧链表创建新链表,不去管随机的那个指针 8 | 2. 根据旧链表中的随机指针,创建新链表中的随机指针 9 | 3. 从旧链表中拆分得到新链表 10 | 11 | 32ms 12 | 5632k 13 | ''' 14 | 15 | # -*- coding:utf-8 -*- 16 | class RandomListNode: 17 | def __init__(self, x): 18 | self.label = x 19 | self.next = None 20 | self.random = None 21 | class Solution: 22 | # 返回 RandomListNode 23 | def Clone(self, pHead): 24 | if pHead == None: 25 | return None 26 | self.CloneNodes(pHead) 27 | self.ConnectRandomNodes(pHead) 28 | return self.ReconnectNodes(pHead) 29 | # 复制原始链表的每个结点, 将复制的结点链接在其原始结点的后面 30 | def CloneNodes(self, pHead): 31 | pNode = pHead 32 | while pNode: 33 | pCloned = RandomListNode(0) 34 | pCloned.label = pNode.label 35 | pCloned.next = pNode.next 36 | # pCloned.random = None #不需要写这句话, 因为创建新的结点的时候,random自动指向None 37 | 38 | pNode.next = pCloned 39 | pNode = pCloned.next 40 | 41 | # 将复制后的链表中的复制结点的random指针链接到被复制结点random指针的后一个结点 42 | def ConnectRandomNodes(self, pHead): 43 | pNode = pHead 44 | while pNode: 45 | pCloned = pNode.next 46 | if pNode.random != None: 47 | pCloned.random = pNode.random.next 48 | pNode = pCloned.next 49 | 50 | # 拆分链表, 将原始链表的结点组成新的链表, 复制结点组成复制后的链表 51 | def ReconnectNodes(self, pHead): 52 | pNode = pHead 53 | pClonedHead = pClonedNode = pNode.next 54 | pNode.next = pClonedHead.next 55 | pNode = pNode.next 56 | 57 | while pNode: 58 | pClonedNode.next = pNode.next 59 | pClonedNode = pClonedNode.next 60 | pNode.next = pClonedNode.next 61 | pNode = pNode.next 62 | 63 | return pClonedHead 64 | -------------------------------------------------------------------------------- /剑指offer/字符串的排列.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入一个字符串,按字典序打印出该字符串中字符的所有排列。 3 | 例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。 4 | ''' 5 | 6 | ''' 7 | 依次取一个元素,然后依次和之前递归形成的所有子串组合,形成新的字符串。 8 | 33ms 9 | 5632k 10 | ''' 11 | 12 | # -*- coding:utf-8 -*- 13 | class Solution: 14 | def Permutation(self, ss): 15 | # write code here 16 | if not len(ss): 17 | return [] 18 | if len(ss) == 1: 19 | return list(ss) 20 | 21 | charList = list(ss) 22 | charList.sort() 23 | pStr = [] 24 | for i in range(len(charList)): 25 | if i > 0 and charList[i] == charList[i-1]: 26 | continue 27 | temp = self.Permutation(''.join(charList[:i])+''.join(charList[i+1:])) 28 | for j in temp: 29 | pStr.append(charList[i]+j) 30 | return pStr -------------------------------------------------------------------------------- /剑指offer/字符流中第一个不重复的字符.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时, 3 | 第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。 4 | ''' 5 | 6 | ''' 7 | 思路:引入两个辅助存储空间。一个Dict存储当前出现的字符以及字符出现的次数,一个List存储当前出现字符。 8 | 然后每次比较List的第一个字符在Dict中对应的次数,如果为1则输出这个字符,如果不为1则弹出这个字符比较下一个字符。 9 | 10 | 26ms 11 | 5760k 12 | ''' 13 | 14 | # -*- coding:utf-8 -*- 15 | class Solution: 16 | # 返回对应char 17 | def __init__(self): 18 | # 存储当前字符 19 | self.alist = [] 20 | # 存储当前字符及其出现次数,出现大于1次,就设成2次 21 | self.adict = {} 22 | 23 | def FirstAppearingOnce(self): 24 | # write code here 25 | while len(self.alist) > 0 and self.adict[self.alist[0]] == 2: 26 | self.alist.pop(0) 27 | if len(self.alist) == 0: 28 | return '#' 29 | else: 30 | return self.alist[0] 31 | 32 | def Insert(self, char): 33 | # write code here 34 | if char not in self.adict.keys(): 35 | self.adict[char] = 1 36 | self.alist.append(char) 37 | else: 38 | self.adict[char] = 2 39 | -------------------------------------------------------------------------------- /剑指offer/对称的二叉树.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的, 3 | 定义其为对称的。 4 | ''' 5 | 6 | ''' 7 | 思路:二叉树镜像相同是对称的,利用递归做 8 | 9 | 34ms 10 | 6340k 11 | ''' 12 | 13 | # -*- coding:utf-8 -*- 14 | # class TreeNode: 15 | # def __init__(self, x): 16 | # self.val = x 17 | # self.left = None 18 | # self.right = None 19 | class Solution: 20 | def isSymmetrical(self, pRoot): 21 | # write code here 22 | return self.IsSymmetrical(pRoot, pRoot) 23 | 24 | def IsSymmetrical(self, pRoot1, pRoot2): 25 | if pRoot1 == None and pRoot2 == None: 26 | return True 27 | if pRoot1 == None or pRoot2 == None: 28 | return False 29 | if pRoot1.val != pRoot2.val: 30 | return False 31 | return self.IsSymmetrical(pRoot1.left, pRoot2.right) and self.IsSymmetrical(pRoot1.right, pRoot2.left) 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /剑指offer/平衡二叉树.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入一棵二叉树,判断该二叉树是否是平衡二叉树。 3 | ''' 4 | 5 | ''' 6 | 平衡二叉树:平衡二叉搜索树(Balanced Binary Tree)具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值 7 | 不超过1,并且左右两个子树都是一棵平衡二叉树。 8 | 9 | 思路:如果二叉树的每个节点的左子树和右子树的深度不大于1,它就是平衡二叉树。 10 | 先写一个求深度的函数,再对每一个节点判断,看该节点的左子树的深度和右子树的深度的差是否大于1 11 | 12 | 31ms 13 | 5520k 14 | ''' 15 | 16 | # -*- coding:utf-8 -*- 17 | # class TreeNode: 18 | # def __init__(self, x): 19 | # self.val = x 20 | # self.left = None 21 | # self.right = None 22 | class Solution: 23 | def IsBalanced_Solution(self, pRoot): 24 | # write code here 25 | if pRoot == None: 26 | # 返回True是因为这是最后的判断依据,在不断递归中,最后是叶子节点,即终止,如果叶子节点时,依然左右子树之差小于1,那么就是平衡二叉树,返回True 27 | return True 28 | depth1 = self.GetDepth(pRoot.left) 29 | depth2 = self.GetDepth(pRoot.right) 30 | if abs(depth1 - depth2) > 1: 31 | return False 32 | return self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right) 33 | 34 | def GetDepth(self, root): 35 | if not root: 36 | return 0 37 | return max(self.GetDepth(root.left), self.GetDepth(root.right)) + 1 38 | -------------------------------------------------------------------------------- /剑指offer/序列化二叉树.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:请实现两个函数,分别用来序列化和反序列化二叉树 3 | ''' 4 | 5 | ''' 6 | 思路:最终要实现的是二叉树的序列化和反序列化。首先来看二叉树的序列化,二叉树的序列化就是采用前序遍历二叉树输出 7 | 节点,再碰到左子节点或者右子节点为None的时候输出一个特殊字符”#”。对于反序列化,就是针对输入的一个序列构建一棵 8 | 二叉树,我们可以设置一个指针先指向序列的最开始,然后把指针指向位置的数字转化为二叉树的结点,后移一个数字,继续 9 | 转化为左子树和右子树。当遇到当前指向的字符为特殊字符”#”或者指针超出了序列的长度,则返回None,指针后移,继续遍历。 10 | 11 | 26ms 12 | 5632k 13 | ''' 14 | 15 | # -*- coding:utf-8 -*- 16 | class TreeNode: 17 | def __init__(self, x): 18 | self.val = x 19 | self.left = None 20 | self.right = None 21 | 22 | class Solution: 23 | flag = -1 24 | 25 | def Serialize(self, root): 26 | # write code here 27 | if not root: 28 | return '#' 29 | return str(root.val) + ',' + self.Serialize(root.left) + ',' + self.Serialize(root.right) 30 | 31 | def Deserialize(self, s): 32 | # write code here 33 | self.flag += 1 34 | l = s.split(',') 35 | # flag每次加1,从0开始,不能超过字符串长度,否则返回None 36 | if self.flag >= len(s): 37 | return None 38 | 39 | root = None 40 | # 新建一个树对象来反序列化字符串 41 | if l[self.flag] != '#': 42 | # 往树中存值,递归输入s没问题,因为l[self.flag]是不断往后取值的 43 | root = TreeNode(int(l[self.flag])) 44 | root.left = self.Deserialize(s) 45 | root.right = self.Deserialize(s) 46 | return root 47 | 48 | -------------------------------------------------------------------------------- /剑指offer/总结: -------------------------------------------------------------------------------- 1 | 1.数据结构大多数包括: 2 | 顺序表(很少操作)、链表(单双向)、栈(两个栈可以模拟一个队列)、队列(双向队列)、树(二叉树)、堆 3 | 4 | 2.算法主要包括: 5 | 排序、字符串变换、关于树上的操作、遍历等等 -------------------------------------------------------------------------------- /剑指offer/扑克片顺子.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)... 3 | 他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A, 4 | 黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,他想了想,决定大\小 王可以看成任何数字, 5 | 并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。 6 | LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何。为了方便起见, 7 | 你可以认为大小王是0。 8 | ''' 9 | 10 | ''' 11 | 思路:先统计王的数量,再把牌排序,如果后面一个数比前面一个数大于1以上,那么中间的差值就必须用王来补了。 12 | 看王的数量够不够,如果够就返回true,否则返回false。 13 | 14 | 31ms 15 | 5632k 16 | ''' 17 | 18 | # -*- coding:utf-8 -*- 19 | class Solution: 20 | def IsContinuous(self, numbers): 21 | # write code here 22 | if not numbers: 23 | return False 24 | numbers.sort() 25 | zero = numbers.count(0) 26 | 27 | # 里面有numbers[i+1]操作,所以取不到最后一个数 28 | for i, v in enumerate(numbers[:-1]): 29 | if v != 0: 30 | # numbers中不能有两个相同的数字 31 | if numbers[i + 1] == v: 32 | return False 33 | zero = zero - (numbers[i + 1] - v - 1) 34 | if zero < 0: 35 | return False 36 | return True 37 | -------------------------------------------------------------------------------- /剑指offer/把二叉树打印成多行.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。 3 | ''' 4 | 5 | ''' 6 | 思路:两个栈,分二级,第一级存一行的数curStack,第二级存着一行数所对应的left,right的值nextStack,每次结束 7 | 一轮循环,把curStack的值给result,然后再将nodes设成nextStack继续进行循环 8 | 9 | 28ms 10 | 5632k 11 | ''' 12 | 13 | # -*- coding:utf-8 -*- 14 | # class TreeNode: 15 | # def __init__(self, x): 16 | # self.val = x 17 | # self.left = None 18 | # self.right = None 19 | class Solution: 20 | # 返回二维列表[[1,2],[4,5]] 21 | def Print(self, pRoot): 22 | # write code here 23 | if not pRoot: 24 | return [] 25 | result,nodes,right = [],[pRoot],True 26 | while nodes: 27 | curStack,nextStack = [],[] 28 | for node in nodes: 29 | curStack.append(node.val) 30 | if node.left: 31 | nextStack.append(node.left) 32 | if node.right: 33 | nextStack.append(node.right) 34 | result.append(curStack) 35 | nodes = nextStack 36 | return result -------------------------------------------------------------------------------- /剑指offer/把字符串转化成整数.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0 3 | ''' 4 | 5 | ''' 6 | 思路一: 使用int(),但是通过了 7 | 8 | 29ms 9 | 5516k 10 | ''' 11 | 12 | # -*- coding:utf-8 -*- 13 | class Solution: 14 | def StrToInt(self, s): 15 | # write code here 16 | try: 17 | return int(s) 18 | except: 19 | return 0 20 | 21 | ''' 22 | 思路二:就是一些特殊处理,比如 +123,就不合理,123前面不需要+,但是-123就合理,因为这是个负数 23 | 24 | 27ms 25 | 5624k 26 | ''' 27 | 28 | # -*- coding:utf-8 -*- 29 | class Solution: 30 | def StrToInt(self, s): 31 | # write code here 32 | if not s: 33 | return 0 34 | num = [] 35 | numbers = {'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9} 36 | for i in s: 37 | if i in numbers.keys(): 38 | num.append(numbers[i]) 39 | elif i == '+': 40 | continue 41 | elif i == '-': 42 | continue 43 | else: 44 | return 0 45 | ans = 0 46 | for i in num: 47 | ans = ans * 10 + i 48 | if s[0] == '-': 49 | ans = 0 - ans 50 | return ans 51 | 52 | -------------------------------------------------------------------------------- /剑指offer/把数组排成最小的数.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。 3 | 例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。 4 | ''' 5 | 6 | ''' 7 | 将输入数组转成字符串,利用cmp比较mn或者nm的大小,进行从小到大的排序 8 | 9 | notes: 10 | 31ms 11 | 5596k 12 | ''' 13 | 14 | import operator 15 | 16 | # -*- coding:utf-8 -*- 17 | class Solution: 18 | def PrintMinNumber(self, numbers): 19 | # write code here 20 | if not numbers: 21 | return '' 22 | numbers = list(map(str, numbers)) 23 | # 在python3.x中已经没有cmp函数,要是用operator函数进行比较,cmp函数就是比较输入两个字符串之间大小的数字 24 | # cmp(x,y) 函数用于比较2个对象,如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1。 25 | # 是两两对象之间的比较,排序默认是从小到大,在这个函数内部实现的两两排序 26 | numbers.sort(cmp=lambda x, y: operator.eq(x + y, y + x)) 27 | if numbers[0] == '0': 28 | return 0 29 | else: 30 | # ''.join实现了字符串之间的连接 31 | return ''.join(numbers) 32 | -------------------------------------------------------------------------------- /剑指offer/按之字形顺序打印二叉树.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印, 3 | 第三行按照从左到右的顺序打印,其他行以此类推。 4 | ''' 5 | 6 | ''' 7 | 思路一:按之字形顺序打印二叉树需要两个栈。我们在打印某一行节点时,拔下一层的子节点保存到相应的栈里。如果当前打印 8 | 的奇数层,则先保存左子节点再保存右子节点到第一个栈里;如果当前打印的是偶数层,则先保存右子节点再保存左子节点到 9 | 第二个栈里。 10 | 11 | 28ms 12 | 5512k 13 | ''' 14 | 15 | # -*- coding:utf-8 -*- 16 | # class TreeNode: 17 | # def __init__(self, x): 18 | # self.val = x 19 | # self.left = None 20 | # self.right = None 21 | class Solution: 22 | def Print(self, pRoot): 23 | # write code here 24 | if not pRoot: 25 | return [] 26 | result,nodes = [],[pRoot] 27 | right = True 28 | # 处理思路很好的,有一个二级机制,通过nextStack存下一节点的,这节点里面的值通过=nodes再转移到curStack里面 29 | # 但是在nextStack中可以调整顺序的 30 | while nodes: 31 | nextStack,curStack = [],[] 32 | if right: 33 | for node in nodes: 34 | curStack.append(node.val) 35 | if node.left: 36 | nextStack.append(node.left) 37 | if node.right: 38 | nextStack.append(node.right) 39 | else: 40 | for node in nodes: 41 | curStack.append(node.val) 42 | if node.right: 43 | nextStack.append(node.right) 44 | if node.left: 45 | nextStack.append(node.left) 46 | nextStack.reverse() 47 | right = not right 48 | result.append(curStack) 49 | nodes= nextStack 50 | return result 51 | 52 | ''' 53 | 思路二: 转换思路,存储的时候一直从左向右存储,打印的时候根据不同的层一次打印 54 | 55 | 25ms 56 | 5512k 57 | ''' 58 | 59 | # -*- coding:utf-8 -*- 60 | # class TreeNode: 61 | # def __init__(self, x): 62 | # self.val = x 63 | # self.left = None 64 | # self.right = None 65 | class Solution: 66 | def Print(self, pRoot): 67 | # write code here 68 | if not pRoot: 69 | return [] 70 | nodes,result,leftToright = [pRoot],[],True 71 | while nodes: 72 | curStack,nextStack = [],[] 73 | for node in nodes: 74 | curStack.append(node.val) 75 | if node.left: 76 | nextStack.append(node.left) 77 | if node.right: 78 | nextStack.append(node.right) 79 | # 调整的是一级的curStack的顺序了,不是二级的nextStack的顺序 80 | if not leftToright: 81 | curStack.reverse() 82 | if curStack: 83 | result.append(curStack) 84 | nodes = nextStack 85 | leftToright = not leftToright 86 | return result 87 | 88 | 89 | -------------------------------------------------------------------------------- /剑指offer/数值的整数次方.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方 3 | ''' 4 | 5 | ''' 6 | 方法一: 直接这么写通过,0应该不算浮点数的,若只是负数,在python的计算中也没有问题 7 | 24ms 8 | 5632k 9 | ''' 10 | 11 | # -*- coding:utf-8 -*- 12 | class Solution: 13 | def Power(self, base, exponent): 14 | # write code here 15 | return base**exponent 16 | 17 | ''' 18 | 方法二: 19 | 需要注意的地方: 20 | 当指数为负数的时候 21 | 当底数为零切指数为负数的情况 22 | 在判断底数base是不是等于0的时候,不能直接写base==0, 因为计算机内表示小数时有误差,只能判断他们的差的绝对值是不是在一个很小的范围内 23 | 24 | 当n为偶数, a^n = a^(n/2) * a^(n/2) 25 | 当n为奇数, a^n = a^((n-1)/2) * a^((n-1)/2)) * a 26 | 利用右移一位运算代替除以2 27 | 利用位与运算代替了求余运算法%来判断一个数是奇数还是偶数 28 | 优化代码速度 29 | ''' 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /剑指offer/数字在排序数组中出现的次数.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:统计一个数字在排序数组中出现的次数。 3 | ''' 4 | 5 | ''' 6 | 思路一:count函数是顺序查找,最坏时间复杂度是O(n) 7 | 8 | 27ms 9 | 5760k 10 | ''' 11 | 12 | # -*- coding:utf-8 -*- 13 | class Solution: 14 | def GetNumberOfK(self, data, k): 15 | # write code here 16 | return data.count(k) 17 | 18 | ''' 19 | 思路二:看见有序就要想起使用二分法查找,最坏时间复杂度是O(logn) 20 | 21 | 对于一个有序数组,要考虑 1,2,2,2,3,4这种情况,计算k=2在数组中出现的次数,用二分法去找这个数,一个找最前面 22 | 出现的2的下标,一个找最后面2出现的小标,这样前后相减+1即可的到结果。 23 | 24 | 29ms 25 | 5632k 26 | ''' 27 | 28 | # -*- coding:utf-8 -*- 29 | class Solution: 30 | def GetNumberOfK(self, data, k): 31 | # write code here 32 | number = 0 33 | if data != None and len(data) > 0: 34 | length = len(data) 35 | First = self.GetFirst(data, length, k, 0, length - 1) 36 | Last = self.GetLast(data, length, k, 0, length - 1) 37 | if First > -1: 38 | number = Last - First + 1 39 | return number 40 | 41 | def GetFirst(self, data, length, k, start, end): 42 | if start > end: 43 | return -1 44 | middle = (start + end) // 2 45 | if data[middle] == k: 46 | if middle > 0 and data[middle - 1] == k: 47 | end = middle - 1 48 | else: 49 | return middle 50 | elif data[middle] > k: 51 | end = middle - 1 52 | else: 53 | start = middle + 1 54 | return self.GetFirst(data, length, k, start, end) 55 | 56 | def GetLast(self, data, length, k, start, end): 57 | if start > end: 58 | return -1 59 | middle = (start + end) // 2 60 | if data[middle] == k: 61 | if middle < end and data[middle + 1] == k: 62 | start = middle + 1 63 | else: 64 | return middle 65 | elif data[middle] > k: 66 | end = middle - 1 67 | else: 68 | start = middle + 1 69 | return self.GetLast(data, length, k, start, end) 70 | -------------------------------------------------------------------------------- /剑指offer/数据流中的中位数.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。 3 | 如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。 4 | ''' 5 | 6 | ''' 7 | 思路一:常规操作 8 | 9 | 29ms 10 | 5760k 11 | ''' 12 | 13 | # -*- coding:utf-8 -*- 14 | class Solution: 15 | def __init__(self): 16 | self.array = [] 17 | 18 | def Insert(self, num): 19 | # write code here 20 | self.array.append(num) 21 | self.array.sort() 22 | 23 | def GetMedian(self, M): 24 | # write code here 25 | length = len(self.array) 26 | if length % 2 == 1: 27 | return self.array[length // 2] 28 | return (self.array[length // 2] + self.array[length // 2 - 1]) / 2.0 29 | 30 | ''' 31 | 思路二: 32 | 为了保证插入新数据和取中位数的时间效率都高效,这里使用大顶堆+小顶堆的容器,并且满足: 33 | 1、两个堆中的数据数目差不能超过1,这样可以使中位数只会出现在两个堆的交接处; 34 | 2、大顶堆的所有数据都小于小顶堆,这样就满足了排序要求。 35 | 36 | 构建一个最大堆和一个最小堆,分别存储比中位数小的数和大的数。 37 | 当目前两堆总数为偶数的时候,把数字存入最大堆,然后重排最大堆,如果最大堆的堆顶数字大于最小堆堆顶数字, 38 | 则把两个堆顶数字交换,重排两堆,此时两堆数字总数为奇数,直接输出最大堆堆顶数字即为中位数; 39 | 如果当前两堆总数为奇数的时候,把数字存入最小堆,重排最小堆,如果最大堆的堆顶数字大于最小堆堆顶数字, 40 | 则把两个堆顶数字交换,重排两堆,此时两堆数字总数为偶数,取两堆堆顶数字做平均即为中位数 41 | 42 | 最大堆堆顶元素要小于最小堆堆顶的元素,最大堆,堆顶元素最大,从大到小,最小堆堆顶元素最小,从小到大,这样的话, 43 | 最大堆所有元素均小于最小堆了,中位数一定出现在两堆交替之间。 44 | 45 | 27ms 46 | 5632k 47 | ''' 48 | 49 | # -*- coding:utf-8 -*- 50 | class Solution: 51 | def __init__(self): 52 | self.left = [] 53 | self.right = [] 54 | self.count = 0 55 | 56 | def Insert(self, num): 57 | if self.count & 1 == 0: 58 | self.left.append(num) 59 | else: 60 | self.right.append(num) 61 | self.count += 1 62 | 63 | def GetMedian(self, x): 64 | if self.count == 1: 65 | return self.left[0] 66 | self.MaxHeap(self.left) 67 | self.MinHeap(self.right) 68 | if self.left[0] > self.right[0]: 69 | self.left[0], self.right[0] = self.right[0], self.left[0] 70 | self.MaxHeap(self.left) 71 | self.MinHeap(self.right) 72 | if self.count & 1 == 0: 73 | return (self.left[0] + self.right[0]) / 2.0 74 | else: 75 | return self.left[0] 76 | 77 | def MaxHeap(self, alist): 78 | length = len(alist) 79 | if alist == None or length <= 0: 80 | return 81 | if length == 1: 82 | return alist 83 | for i in range(length // 2 - 1, -1, -1): 84 | k = i; 85 | temp = alist[k]; 86 | heap = False 87 | while not heap and 2 * k < length - 1: 88 | index = 2 * k + 1 89 | if index < length - 1: 90 | if alist[index] < alist[index + 1]: index += 1 91 | if temp >= alist[index]: 92 | heap = True 93 | else: 94 | alist[k] = alist[index] 95 | k = index 96 | alist[k] = temp 97 | 98 | def MinHeap(self, alist): 99 | length = len(alist) 100 | if alist == None or length <= 0: 101 | return 102 | if length == 1: 103 | return alist 104 | for i in range(length // 2 - 1, -1, -1): 105 | k = i; 106 | temp = alist[k]; 107 | heap = False 108 | while not heap and 2 * k < length - 1: 109 | index = 2 * k + 1 110 | if index < length - 1: 111 | if alist[index] > alist[index + 1]: index += 1 112 | if temp <= alist[index]: 113 | heap = True 114 | else: 115 | alist[k] = alist[index] 116 | k = index 117 | alist[k] = temp 118 | 119 | -------------------------------------------------------------------------------- /剑指offer/数的子结构.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构) 3 | ''' 4 | 5 | ''' 6 | 分析,两个序列才能确定一个一棵树,所以先用先序遍历,再用字符串进行匹配是不对的,因为的树的结构你确定不了。 7 | 这一题,首先判断根节点是不是相同,不相同是一个递归,把pRoot1的左右子树一次和PRoot2进行判断 8 | 如果根节点相同,那么进入下一个函数,接着判断,左边节点的下一级和左边子树下一级是不是相同,又是一个递归。 9 | 两个递归操作 10 | 29ms 11 | 5632k 12 | ''' 13 | 14 | # -*- coding:utf-8 -*- 15 | # class TreeNode: 16 | # def __init__(self, x): 17 | # self.val = x 18 | # self.left = None 19 | # self.right = None 20 | class Solution: 21 | def HasSubtree(self, pRoot1, pRoot2): 22 | # write code here 23 | result = False 24 | # 判断根节点 25 | if pRoot1 != None and pRoot2 != None: 26 | if pRoot1.val == pRoot2.val: 27 | result = self.same(pRoot1, pRoot2) 28 | if not result: 29 | result = self.HasSubtree(pRoot1.left, pRoot2) 30 | if not result: 31 | result = self.HasSubtree(pRoot1.right, pRoot2) 32 | return result 33 | 34 | def same(self, pRoot1, pRoot2): 35 | if pRoot2 == None: 36 | return True 37 | if pRoot1 == None: 38 | return False 39 | # 这一步不断判断下一个节点,因为是递归操作。 40 | if pRoot1.val != pRoot2.val: 41 | return False 42 | return self.same(pRoot1.left, pRoot2.left) and self.same(pRoot1.right, pRoot2.right) 43 | -------------------------------------------------------------------------------- /剑指offer/数组中出现次数超过一半的数字.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。 3 | 由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。 4 | ''' 5 | 6 | ''' 7 | 思路1:快排,如果该数出现次数超过数组长度的一半,那么,排序之后,他应该位于数组的中间 8 | 9 | 思路2:根据数组的特点,出现次数超过一半的数,他出现的次数比其他数字出现的总和还要多,因此可以最开始保存两个数值: 10 | 数组中的一个数字以及它出现的次数,然后遍历,如果下一个数字等于这个数字,那么次数加一,如果不等,次数减一,当次数 11 | 等于0的时候,在下一个数字的时候重新复制新的数字以及出现的次数置为1,直到进行到最后,然后再验证最后留下的数字是否 12 | 出现次数超过一半,因为可能前面的次数依次抵消掉,最后一个数字就直接是保留下来的数字,但是出现次数不一定超过一半。 13 | 14 | 24ms 15 | 5632k 16 | ''' 17 | 18 | # -*- coding:utf-8 -*- 19 | class Solution: 20 | def MoreThanHalfNum_Solution(self, numbers): 21 | # write code here 22 | # 这个操作就是建立在出现次数超过一半的数,他出现的次数比其他数字出现的总和还要多,所以如果存在这个数,最后count 23 | # 肯定不为0的 24 | count = 1 25 | number = numbers[0] 26 | for i in numbers[1:]: 27 | if number == i: 28 | count += 1 29 | else: 30 | count -= 1 31 | if count == 0: 32 | number = i 33 | count += 1 34 | 35 | sum = 0 36 | for j in numbers: 37 | if j == number: 38 | sum += 1 39 | 40 | return number if sum > len(numbers) // 2 else 0 41 | 42 | -------------------------------------------------------------------------------- /剑指offer/数组中只出现一次的数字.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 3 | ''' 4 | 5 | ''' 6 | 思路一:利用python自带的counter库 7 | 8 | 27ms 9 | 5632k 10 | ''' 11 | 12 | # -*- coding:utf-8 -*- 13 | class Solution: 14 | # 返回[a,b] 其中ab是出现一次的两个数字 15 | def FindNumsAppearOnce(self, array): 16 | # write code here 17 | from collections import Counter 18 | # 返回一个列表,map(f,input),对input进行f操作,第一个参数lambda函数,意思取返回值中的第一个数,因为counter函数返回的是字典, 19 | # counter().most_common返回的是有序的计数字段,去最后两个,顺序是从大到小的。 20 | return list(map(lambda c:c[0],Counter(array).most_common()[-2:])) 21 | 22 | ''' 23 | 思路二:异或运算 24 | ''' 25 | 26 | -------------------------------------------------------------------------------- /剑指offer/数组中的逆序对.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组 3 | 中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007 4 | ''' 5 | 6 | ''' 7 | notes:这一题没法用python做,用python始终是超时的 8 | 9 | 思路一:很巧妙 10 | 在牛客网上运算超时,但是思想很好 11 | 例如: 12 | 0 1 2 3 13 | 2 1 3 4 逆序数:1 14 | copy 1 2 3 4 15 | 1+0+0+0=1 16 | ''' 17 | 18 | # -*- coding:utf-8 -*- 19 | class Solution: 20 | def InversePairs(self, data): 21 | # write code here 22 | copy = [] 23 | count = 0 24 | for i in data: 25 | copy.append(i) 26 | copy.sort() 27 | 28 | for i in range(len(copy)): 29 | count += data.index(copy[i]) 30 | data.remove(copy[i]) 31 | 32 | return count % 10000000007 33 | 34 | ''' 35 | 思路二:这一题核心还是要用归并排序,归并排序能够有效的减少最坏时间复杂度,但是它有额外的开销,以空间换时间 36 | 归并排序,就是把原数据分成两个数组,每次取两个数组中的最小值放入一个新的数组中,直到其中一个数组全部取完 37 | 38 | 不过还是超时 39 | ''' 40 | 41 | # -*- coding:utf-8 -*- 42 | class Solution: 43 | def InversePairs(self, data): 44 | # write code here 45 | length = len(data) 46 | if data == None or length <= 0: 47 | return 0 48 | copy = [0] * length 49 | for i in range(length): 50 | copy[i] = data[i] 51 | 52 | count = self.InversePairsCore(data, copy, 0, length - 1) 53 | return count % 10000000007 54 | 55 | def InversePairsCore(self, data, copy, start, end): 56 | if start == end: 57 | copy[start] = data[start] 58 | return 0 59 | length = (end - start) // 2 60 | left = self.InversePairsCore(copy, data, start, start + length) 61 | right = self.InversePairsCore(copy, data, start + length + 1, end) 62 | 63 | # i初始化为前半段最后一个数字的下标 64 | i = start + length 65 | # j初始化为后半段最后一个数字的下标 66 | j = end 67 | 68 | indexCopy = end 69 | count = 0 70 | # 对两个数组进行对比取值的过程 71 | while i >= start and j >= start + length + 1: 72 | if data[i] > data[j]: 73 | copy[indexCopy] = data[i] 74 | indexCopy -= 1 75 | i -= 1 76 | count += j - start - length 77 | else: 78 | copy[indexCopy] = data[j] 79 | indexCopy -= 1 80 | j -= 1 81 | 82 | # 剩下的一个数组未取完的操作 83 | while i >= start: 84 | copy[indexCopy] = data[i] 85 | indexCopy -= 1 86 | i -= 1 87 | while j >= start + length + 1: 88 | copy[indexCopy] = data[j] 89 | indexCopy -= 1 90 | j -= 1 91 | return left + right + count 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /剑指offer/数组中重复的数字.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。 3 | 也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3}, 4 | 那么对应的输出是第一个重复的数字2。 5 | ''' 6 | 7 | ''' 8 | 应该是在线编辑器的bug 9 | 10 | 思路一: 11 | 12 | 未通过 13 | ''' 14 | 15 | # -*- coding:utf-8 -*- 16 | class Solution: 17 | # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0] 18 | # 函数返回True/False 19 | def duplicate(self, numbers, duplication): 20 | # write code here 21 | if not numbers: 22 | return -1 23 | num = [] 24 | 25 | for i in numbers: 26 | if i in num: 27 | duplication[0] = i 28 | return True 29 | else: 30 | num.append(i) 31 | return False 32 | 33 | ''' 34 | 思路二: 35 | 最简单的方法:我最直接的想法就是构造一个容量为N的辅助数组B,原数组A中每个数对应B中下标,首次命中,B中对应元素+1。如果某次命中时,B中对应的不为0,说明,前边已经有一样数字了,那它就是重复的了。 36 | 举例:A{1,2,3,3,4,5},刚开始B是{0,0,0,0,0,0},开始扫描A。 37 | A[0] = 1  {0,1,0,0,0,0} 38 | A[1] = 2 {0,1,1,0,0,0} 39 | A[2] = 3 {0,1,1,1,0,0} 40 | A[3] = 3 {0,1,1,2,0,0},到这一步,就已经找到了重复数字。 41 | A[4] = 4 {0,1,1,2,1,0} 42 | A[5] = 5 {0,1,1,2,1,1} 43 | 时间复杂度O(n),空间复杂度O(n),算法优点是简单快速,比用set更轻量更快,不打乱原数组顺序。 44 | 45 | 未能通过 46 | ''' 47 | 48 | # -*- coding:utf-8 -*- 49 | class Solution: 50 | # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0] 51 | # 函数返回True/False 52 | def duplicate(self, numbers, duplication): 53 | # write code here 54 | if not numbers: 55 | return False 56 | 57 | length = len(numbers) 58 | assist = [0] * length 59 | for i in numbers: 60 | if assist[numbers[i]] == 0: 61 | assist[numbers[i]] += 1 62 | else: 63 | duplication[0] = numbers[i] 64 | return True 65 | return False 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /剑指offer/整数中1出现的次数.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、 3 | 10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出 4 | 任意非负整数区间中1出现的次数。 5 | ''' 6 | 7 | ''' 8 | 思路1:例:对于824883294,先求0-800000000之间(不包括800000000)的,再求0-24883294之间的。 9 | 如果等于1,如1244444,先求0-1000000之间,再求1000000-1244444,那么只需要加上244444+1,再求0-244444 10 | 之间的1如果大于1,例:0-800000000之间1的个数为8个100000000的1的个数加上100000000,因为从1000000000- 11 | 200000000共有1000000000个数且最高位都为1。对于最后一位数,如果大于1,直接加上1即可。 12 | 13 | 思路2:将1-n全部转换为字符串,只需要统计每个字符串中'1'出现的次数并相加即可 14 | 47ms 15 | 5504k 16 | ''' 17 | 18 | def countDigitOne(self, n): 19 | result = 0 20 | if n < 0: 21 | return 0 22 | length = len(str(n)) 23 | listN = list(str(n)) 24 | for i, v in enumerate(listN): 25 | a = length - i - 1 # a为10的幂 26 | if i == length - 1 and int(v) >= 1: 27 | result += 1 28 | break 29 | if int(v) > 1: 30 | result += int(10 ** a * a / 10) * int(v) + 10 ** a 31 | if int(v) == 1: 32 | result += (int(10 ** a * a / 10) + int("".join(listN[i + 1:])) + 1) 33 | return result 34 | 35 | # -*- coding:utf-8 -*- 36 | class Solution: 37 | def NumberOf1Between1AndN_Solution(self, n): 38 | # write code here 39 | count = 0 40 | for i in range(1,n+1): 41 | for i in str(i): 42 | if i == '1': 43 | count += 1 44 | return count 45 | -------------------------------------------------------------------------------- /剑指offer/斐波那契数列.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目: 3 | 大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项。 4 | n<=39 5 | ''' 6 | 7 | ''' 8 | 第三位是前两位之和,一直迭代的 9 | 25ms 10 | 5632k 11 | ''' 12 | 13 | # -*- coding:utf-8 -*- 14 | class Solution: 15 | def Fibonacci(self, n): 16 | # write code here 17 | res = [0,1] 18 | while len(res) <= n: 19 | res.append(res[-1]+res[-2]) 20 | return res[n] -------------------------------------------------------------------------------- /剑指offer/旋转数组的最小数字.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目: 3 | 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的 4 | 最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。NOTE:给出的所有元素都大于0,若数组大小为0, 5 | 请返回0。 6 | ''' 7 | 8 | ''' 9 | 这一题也不好解,在算法上,考虑数字没有重复的情况的话,使用二分法,有两个指针,第一个指针指向front,第二个指针指向rear, 10 | midIndex是中间数字,只要是旋转数组,那么首位一定大于中间位,所以如果首位大于中间位的话,那么就把指针从首位移到中间 11 | 位,前面数字向后移动,不断迭代,当首位和最后位只差1时,最后维就是最小值。此时最坏时间复杂度是O(logn),但是要考虑数字 12 | 重复的话,情况只可能是首位和末尾和中间重这种[1,0,1,1]只能取其中最小值,逐一排列,对于首位和中间位重的,比如[1,1,0], 13 | 把首位移动到后面去,可以处理,或者中间位和末尾重,比如[1,0,0],也是能处理,其他情况不存在,因为前提要求是旋转数组 14 | 830ms 15 | 5632k 16 | ''' 17 | 18 | # -*- coding:utf-8 -*- 19 | class Solution: 20 | def minNumberInRotateArray(self, rotateArray): 21 | # write code here 22 | if not rotateArray: 23 | return 0 24 | 25 | front, rear = 0, len(rotateArray) - 1 26 | midIndex = 0 27 | while rotateArray[front] >= rotateArray[rear]: 28 | if rear - front == 1: 29 | midIndex = rear 30 | break 31 | midIndex = (front + rear) // 2 32 | if rotateArray[front] == rotateArray[midIndex] and rotateArray[front] == rotateArray[rear]: 33 | return self.minOrder(rotateArray, front, rear) 34 | 35 | if rotateArray[front] <= rotateArray[midIndex]: 36 | front = midIndex 37 | elif rotateArray[rear] >= rotateArray[midIndex]: 38 | rear = midIndex 39 | return rotateArray[midIndex] 40 | 41 | def minOrder(self, array, front, end): 42 | result = array[0] 43 | for i in array[front:end + 1]: 44 | if i < result: 45 | result = i 46 | return result -------------------------------------------------------------------------------- /剑指offer/替换空格.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:请实现一个函数,将一个字符串中的空格替换成“%20”。 3 | 例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。 4 | ''' 5 | 6 | ''' 7 | 方法1: 使用replace 8 | 24ms 9 | 5624k 10 | ''' 11 | class Solution: 12 | # s 源字符串 13 | def replaceSpace(self, s): 14 | # write code here 15 | return s.replace(' ','%20') 16 | 17 | 18 | ''' 19 | 方法二:这一题的关键是替换是从往后往前遍历还是从前往后遍历是不一样的,如果从前往后遍历的话,每一个空格都要移动这个空格后面 20 | 所有的字符串一次,但是如果从后往前遍历的话,每一个字符串只需要移动一次。 21 | ''' 22 | -------------------------------------------------------------------------------- /剑指offer/最小的k个数.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。 3 | ''' 4 | 5 | ''' 6 | 思路1,这一题应用堆排序算法复杂度只有O(nlog k),堆是完全二叉树的一种,最大堆就是最上面的数是最大的 7 | 该方法基于二叉树或者堆来实现,首先把数组前k个数字构建一个最大堆,然后从第k+1个数字开始遍历数组,如果遍历到的 8 | 元素小于堆顶的数字,那么久将换两个数字,重新构造堆,继续遍历,最后剩下的堆就是最小的k个数,时间复杂度O(nlog k)。 9 | 10 | 思路2:排序 11 | ''' 12 | 13 | # -*- coding:utf-8 -*- 14 | class Solution: 15 | def GetLeastNumbers_Solution(self, tinput, k): 16 | # write code here、 17 | import heapq 18 | if tinput == None or len(tinput) < k or len(tinput) <= 0 or k <= 0: 19 | return [] 20 | 21 | # 建立最小堆,最上面那个数是最小的,返回一个列表,这个列表就是从最小值开始的k个数 22 | return heapq.nsmallest(k, tinput) 23 | 24 | 25 | # -*- coding:utf-8 -*- 26 | class Solution: 27 | def GetLeastNumbers_Solution(self, tinput, k): 28 | # write code here、 29 | import heapq 30 | if tinput == None or len(tinput) < k or len(tinput) <= 0 or k <= 0: 31 | return [] 32 | 33 | return sorted(tinput)[:k] 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /剑指offer/机器人的运动范围.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格, 3 | 但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为 4 | 3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子? 5 | ''' 6 | 7 | ''' 8 | 思路:同上一题思路一样,判断条件改成了行坐标和列坐标的数位之和大于k 9 | 10 | 27ms 11 | 5728k 12 | ''' 13 | 14 | # -*- coding:utf-8 -*- 15 | class Solution: 16 | def movingCount(self, threshold, rows, cols): 17 | # write code here 18 | markmatrix = [False] * (rows * cols) 19 | count = self.GetNum(threshold, rows, cols, 0, 0, markmatrix) 20 | return count 21 | 22 | def GetNum(self, threshold, rows, cols, row, col, markmatrix): 23 | count = 0 24 | 25 | if self.GetSum(threshold, rows, cols, row, col, markmatrix): 26 | markmatrix[row * cols + col] = True 27 | count = 1 + self.GetNum(threshold, rows, cols, row - 1, col, markmatrix) + \ 28 | self.GetNum(threshold, rows, cols, row, col - 1, markmatrix) + \ 29 | self.GetNum(threshold, rows, cols, row + 1, col, markmatrix) + \ 30 | self.GetNum(threshold, rows, cols, row, col + 1, markmatrix) 31 | return count 32 | 33 | def GetSum(self, threshold, rows, cols, row, col, markmatrix): 34 | if row >= 0 and row < rows and col >= 0 and col < cols and self.getDigit(row) + self.getDigit( 35 | col) <= threshold and not markmatrix[row * cols + col]: 36 | return True 37 | return False 38 | 39 | def getDigit(self, number): 40 | sumNum = 0 41 | while number > 0: 42 | sumNum += number % 10 43 | number = number // 10 44 | return sumNum 45 | -------------------------------------------------------------------------------- /剑指offer/构建乘积数组.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素 3 | B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法 4 | ''' 5 | 6 | ''' 7 | 思路: 8 | B[0] = A[1] * A[2] * A[3] * A[4] *....*A[n-1] ;(没有A[0]) 9 | B[1 ]= A[0] * A[2] * A[3] * A[4] *....*A[n-1] ;(没有A[1]) 10 | B[2] = A[0] * A[1] * A[3] * A[4] *....*A[n-1] ;(没有A[2]) 11 | 举例: 输入: 1 2 3 4 5 12 | 输出: 120 60 40 30 24 13 | 相当于一个矩形,被省去的那个数字设为1,这样的话,先把上三角的数一行一行撑起来,接着在和下三角的数相乘,节省空间 14 | 15 | 27ms 16 | 5632k 17 | ''' 18 | 19 | # -*- coding:utf-8 -*- 20 | class Solution: 21 | def multiply(self, A): 22 | # write code here 23 | if not A or len(A) < 0: 24 | return 0 25 | length = len(A) 26 | B = [1] * length 27 | # 下三角,从1开始乘的 28 | for i in range(1, length): 29 | B[i] = B[i - 1] * A[i - 1] 30 | temp = 1 31 | # 上三角,接着下三角从大往小乘,节约空间,最后一位设为1,前面只有一位,在于之前计算好的相乘 32 | # 画一个矩形就明白了。 33 | for i in range(length - 2, -1, -1): 34 | temp = temp * A[i + 1] 35 | B[i] *= temp 36 | return B 37 | -------------------------------------------------------------------------------- /剑指offer/栈的压入弹出序列.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字 3 | 均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就 4 | 不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的) 5 | ''' 6 | 7 | ''' 8 | 这题挺难的,比较抽象。可以手写模拟一下。 9 | 三个栈,一个是压栈,一个是出栈,一个是辅助栈,把数据从pushv向stack中压,如果压入数据和popv出栈的栈顶元素一致, 10 | 就从pushv和popv中同时弹出去,不要往stack中压了。等到pushv中元素全弹出来之后,判断stack中出栈元素和popv中出栈 11 | 元素是否一致,当popv中元素全部弹出,就结束,说明是一致的,手写演示一下就懂了。 12 | 13 | 入栈1,2,3,4,5 14 | 出栈4,5,3,2,1 15 | 首先1入辅助栈,此时栈顶1≠4,继续入栈2 16 | 此时栈顶2≠4,继续入栈3 17 | 此时栈顶3≠4,继续入栈4 18 | 此时栈顶4=4,出栈4,弹出序列向后一位,此时为5,,辅助栈里面是1,2,3 19 | 此时栈顶3≠5,继续入栈5 20 | 此时栈顶5=5,出栈5,弹出序列向后一位,此时为3,,辅助栈里面是1,2,3 21 | …. 22 | 依次执行,最后辅助栈为空。如果不为空说明弹出序列不是该栈的弹出顺序。 23 | 24 | 34ms 25 | 6312k 26 | ''' 27 | 28 | # -*- coding:utf-8 -*- 29 | class Solution: 30 | def IsPopOrder(self, pushV, popV): 31 | # write code here 32 | stack = [] 33 | while popV: 34 | 35 | # 如果第一个元素都相同,就直接弹出,压入栈为空还是要比的,一开始为空,是个问题,但是压空了就要比弹出了,第二个elif 36 | if pushV and pushV[0] == popV[0]: 37 | popV.pop(0) 38 | pushV.pop(0) 39 | # 如果stack中最后一个元素和popV中第一个元素相同,这就是压完了之后弹出的过程中进行的比较 40 | elif stack and stack[-1] == popV[0]: 41 | stack.pop() 42 | popV.pop(0) 43 | elif pushV: 44 | stack.append(pushV.pop(0)) 45 | else: 46 | return False 47 | return True 48 | -------------------------------------------------------------------------------- /剑指offer/正则表达式匹配.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的 3 | 字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a" 4 | 和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配 5 | ''' 6 | 7 | ''' 8 | 思路: . 表示可以是任意字符,* 表示前面的字符可以出现任意次,所以在patten中*不可能位于首位的 9 | aaa a.a ab*ac*a(b出现0次,c出现0次,这样就是aaa了) 10 | 11 | 26ms 12 | 5628k 13 | ''' 14 | 15 | # -*- coding:utf-8 -*- 16 | class Solution: 17 | # s, pattern都是字符串 18 | def match(self, s, pattern): 19 | # write code here 20 | # 如果s和pattern匹配, 直接True 21 | if s == pattern: 22 | return True 23 | # 如果pattern为'', 因为s和pattern不相等, 直接False 24 | elif pattern == '': 25 | return False 26 | # 当s为'', 如果pattern为'.', 则返回True 27 | # 当s为'', 如果pattern长度为1且不为'.', 或者pattern第二个字符不是*, 则pattern不可能为空, 返回False 28 | # 若pattern长度不为1, 且第二个字符为*, pattern还有空的可能, 从第三个字符开始迭代 29 | elif s == '': 30 | if pattern == ".": 31 | return False 32 | elif len(pattern) == 1 or pattern[1] != '*': 33 | return False 34 | else: 35 | return self.match(s, pattern[2:]) 36 | 37 | # 如果pattern长度不小于二, 而且pattern的第二个字符不是*的情况下 38 | # 当 pattern[0] 不等于s[0], 且不为 . 的时候, s和pattern必不相等 39 | # 否则, s 和 pattern 都右移一位, 继续比较 40 | if len(pattern) >= 2 and pattern[1] != '*': 41 | if s[0] != pattern[0] and pattern[0] != '.': 42 | return False 43 | else: 44 | return self.match(s[1:], pattern[1:]) 45 | # 如果pattern长度不小于2, 且pattern第二个字符为*的情况下 46 | # 如果s[0]不等于pattern[0], 且pattern[0]不为 . , 那么第一位比较不成功, pattern必须后移两位继续比较后面是否能和s第一位匹配 47 | # 如果s[0]等于pattern[0], 或者pattern[0]为 . , 第一位匹配, 那么会有 48 | # 1. aaa 和 a*a 这种情况, 星号代表了多个a, 因此s需要不断右移一位继续比较 49 | # 2. a 和 a*a 中这情况, 这时候星号代表0个a, 因此s不需要右移, pattern需要右移两位 50 | # 3. abc 和 a*bc 这种情况, 星号代表了1个a, s右移一位, pattern右移两位继续比较 51 | elif len(pattern) >= 2 and pattern[1] == '*': 52 | if s[0] != pattern[0] and pattern[0] != '.': 53 | return self.match(s, pattern[2:]) 54 | else: 55 | return self.match(s[1:], pattern) or self.match(s, pattern[2:]) or self.match(s[1:], pattern[2:]) 56 | # 除去上述pattern不小于2情况, 只剩下pattern等于1的情况, 因此如果pattern为".", 而且s长度为1, 返回True 57 | elif pattern == '.' and len(s) == 1: 58 | return True 59 | return False -------------------------------------------------------------------------------- /剑指offer/求1+2+3+...+n.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。 3 | ''' 4 | 5 | ''' 6 | 思路一:利用了python的特性吧,好想法。 7 | 8 | 29ms 9 | 5632k 10 | ''' 11 | 12 | # -*- coding:utf-8 -*- 13 | class Solution: 14 | def Sum_Solution(self, n): 15 | # write code here 16 | return sum(list(range(1, n + 1))) 17 | 18 | ''' 19 | 思路二:利用两个函数,一个函数充当递归函数的角色,另一个函数处理终止递归的情况。如果对n连续进行两次反运算, 20 | 那么非零的n转换为True,0转换为False。利用这一特性终止递归。注意考虑测试用例为0的情况。 21 | 22 | 34ms 23 | 6140k 24 | ''' 25 | 26 | # -*- coding:utf-8 -*- 27 | class Solution: 28 | def Sum_Solution(self, n): 29 | # write code here 30 | return self.sum(n) 31 | 32 | def sum0(self, n): 33 | return 0 34 | 35 | def sum(self, n): 36 | fun = {False: self.sum0, True: self.sum} 37 | return n + fun[not not n](n - 1) -------------------------------------------------------------------------------- /剑指offer/滑动窗口的最大值.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及 3 | 滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的 4 | 滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, 5 | {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。 6 | ''' 7 | 8 | ''' 9 | 思路一: 10 | 2 3 4 4 第一轮判断 11 | 3 4 2 4 12 | 4 2 6 6 第一轮结束时进入第二个判断条件 13 | 2 6 2 6 14 | 6 2 5 6 15 | 2 5 1 5 16 | 17 | 23ms 18 | 5728k 19 | ''' 20 | 21 | # -*- coding:utf-8 -*- 22 | class Solution: 23 | def maxInWindows(self, num, size): 24 | # write code here 25 | if size <= 0 or len(num) < size: 26 | return [] 27 | length = len(num) 28 | curnum = max(num[:size]) 29 | ans = [curnum] 30 | # 循环次数是length-size,是因为滑窗大小是size,length只能有length-size个滑窗 31 | for i in range(0, length - size): 32 | # 对滑窗内每个数字都进行扫描,直到找到和最大值相等数字,相等表明我的一个滑窗扫描结束,进入下一个滑窗进行扫描,并取最大值 33 | if num[i] == curnum: 34 | curnum = max(num[i + 1:i + 1 + size]) 35 | # 跳过一个滑窗字符为首的一个滑窗,进入一个新的判断滑窗 36 | elif num[i + size] > curnum: 37 | curnum = num[i + size] 38 | ans.append(curnum) 39 | return ans 40 | 41 | ''' 42 | 思路二:用双向队列做,没看懂 43 | 44 | 45 | ''' 46 | 47 | -------------------------------------------------------------------------------- /剑指offer/矩形覆盖.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目: 3 | 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 4 | ''' 5 | 6 | ''' 7 | 依旧是斐波那契数列 8 | 2*n的大矩形,和n个2*1的小矩形 9 | 其中 2*target 为大矩阵的大小 10 | 有以下几种情形: 11 | 1⃣️target <= 0 大矩形为<= 2*0,直接return 1; 12 | 2⃣️target = 1大矩形为2*1,只有一种摆放方法,return1; 13 | 3⃣️target = 2 大矩形为2*2,有两种摆放方法,return2; 14 | 4⃣️target = n 分为两步考虑: 15 | 第一次摆放一块 2*1 的小矩阵,则摆放方法总共为f(target - 1) 16 | √ 17 | √ 18 | 第一次摆放一块1*2的小矩阵,则摆放方法总共为f(target-2) 19 | 因为,摆放了一块1*2的小矩阵(用√√表示),对应下方的1*2(用××表示)摆放方法就确定了,所以为f(targte-2) 20 | √ √ 21 | × × 22 | target >= 3 f(n) = f(target - 1) + f(targte-2) 23 | 24 | 29ms 25 | 5632k 26 | ''' 27 | 28 | # -*- coding:utf-8 -*- 29 | class Solution: 30 | def rectCover(self, number): 31 | # write code here 32 | if number == 0: 33 | return 0 34 | elif number == 1: 35 | return 1 36 | elif number == 2: 37 | return 2 38 | else: 39 | res = [0, 1, 2] 40 | while len(res) <= number: 41 | res.append(res[-1] + res[-2]) 42 | return res[number] 43 | -------------------------------------------------------------------------------- /剑指offer/矩阵中的路径.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个 3 | 格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路 4 | 径不能再进入该格子。 例如 a b c e s f c s a d e e 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含 5 | "abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。 6 | ''' 7 | 8 | ''' 9 | 思路:优化版回溯法 10 | 1.将matrix字符串模拟映射为一个字符矩阵(但并不实际创建一个矩阵) 11 | 2.取一个boolean[matrix.length]标记某个字符是否已经被访问过,用一个布尔矩阵进行是否存在该数值的标记。 12 | 3.如果没找到结果,需要将对应的boolean标记值置回false,返回上一层进行其他分路的查找。 13 | 14 | 36ms 15 | 5697k 16 | ''' 17 | 18 | # -*- coding:utf-8 -*- 19 | class Solution: 20 | def hasPath(self, matrix, rows, cols, path): 21 | # write code here 22 | if not matrix and rows <= 0 and cols <= 0 and path == None: 23 | return False 24 | # 模拟的字符矩阵 25 | markmatrix = [0] * (rows * cols) 26 | pathlength = 0 27 | # 从第一个开始递归,当然第一二个字符可能并不位于字符串之上,所以有这样一个双层循环找起点用的,一旦找到第一个符合的字符串,就开始进入递归, 28 | # 返回的第一个return Ture就直接跳出循环了。 29 | for row in range(rows): 30 | for col in range(cols): 31 | if self.hasPathCore(matrix, rows, cols, row, col, path, pathlength, markmatrix): 32 | return True 33 | return False 34 | 35 | def hasPathCore(self, matrix, rows, cols, row, col, path, pathlength, markmatrix): 36 | # 说明已经找到该路径,可以返回True 37 | if len(path) == pathlength: 38 | return True 39 | 40 | hasPath = False 41 | if row >= 0 and row < rows and col >= 0 and col < cols and matrix[row * cols + col] == path[pathlength] and not \ 42 | markmatrix[row * cols + col]: 43 | pathlength += 1 44 | markmatrix[row * cols + col] = True 45 | # 进行该值上下左右的递归 46 | hasPath = self.hasPathCore(matrix, rows, cols, row - 1, col, path, pathlength, markmatrix) \ 47 | or self.hasPathCore(matrix, rows, cols, row, col - 1, path, pathlength, markmatrix) \ 48 | or self.hasPathCore(matrix, rows, cols, row + 1, col, path, pathlength, markmatrix) \ 49 | or self.hasPathCore(matrix, rows, cols, row, col + 1, path, pathlength, markmatrix) 50 | 51 | # 对标记矩阵进行布尔值标记 52 | if not hasPath: 53 | pathlength -= 1 54 | markmatrix[row * cols + col] = False 55 | return hasPath 56 | -------------------------------------------------------------------------------- /剑指offer/第一个只出现一次的字符.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置 3 | ''' 4 | 5 | ''' 6 | 思路一:先遍历一遍字符串,用一个hash表存放每个出现的字符和字符出现的次数。再遍历一遍字符串,找到hash值等于1的输出即可。 7 | 40ms 8 | 5632k 9 | 10 | 思路二:利用python函数的特性 11 | 32ms 12 | 5632k 13 | ''' 14 | 15 | # -*- coding:utf-8 -*- 16 | class Solution: 17 | def FirstNotRepeatingChar(self, s): 18 | # write code here 19 | if s == None or len(s) <= 0: 20 | return -1 21 | alist = list(s) 22 | blist = {} 23 | for i in alist: 24 | if i not in blist.keys(): 25 | blist[i] = 0 26 | blist[i] += 1 27 | for i in blist: 28 | if blist[i] == 1: 29 | # %d format: a number is required, not str ,i此时返回的是只出现一次的那个字符串是不符合题意的 30 | # return i 31 | return s.index(i) 32 | return -1 33 | 34 | # -*- coding:utf-8 -*- 35 | class Solution: 36 | def FirstNotRepeatingChar(self, s): 37 | # write code here 38 | if s == None or len(s) <= 0: 39 | return -1 40 | for i in s: 41 | if s.count(i) == 1: 42 | return s.index(i) 43 | return -1 44 | -------------------------------------------------------------------------------- /剑指offer/翻转单词顺序列.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容 3 | 颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把 4 | 句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么? 5 | ''' 6 | 7 | ''' 8 | 思路一: 9 | 10 | 26ms 11 | 5632k 12 | ''' 13 | 14 | # -*- coding:utf-8 -*- 15 | class Solution: 16 | def ReverseSentence(self, s): 17 | # write code here 18 | if s == None or len(s) <= 0: 19 | return '' 20 | # 以空格为界,提取单一字符,然后用切片拍一下顺序 21 | return ' '.join(s.split(' ')[::-1]) 22 | 23 | ''' 24 | 思路二:首先需要写一个reverse函数,把任何输入的字符串完全翻转。然后从前往后依次遍历新字符串,如果遇到空格, 25 | 就把空格前的字符串用reverse翻转,添加空格,继续遍历。需要注意的是,如果新字符串结尾不是空格,当遍历到结尾的 26 | 时候,前一个空格到结尾的字符串没有翻转,因此记得跳出遍历后,需要再完成一次翻转操作。 27 | 28 | 举例: 29 | student. a am I 30 | I ma a .tneduts 31 | I pEnd = ' ',首先让空格前面的字符进行翻转,然后 pStart = pEnd 32 | am pStart = ' ',两个指针都向前进到a位,下一次pEnd继续向前进到空格为止,然后ma翻转变成am 33 | a 34 | student. 同理 35 | 36 | 37 | 37ms 38 | 5488k 39 | ''' 40 | 41 | # -*- coding:utf-8 -*- 42 | class Solution: 43 | def ReverseSentence(self, s): 44 | # write code here 45 | if s == None or len(s) <= 0: 46 | return '' 47 | s = list(s) 48 | s = self.Reverse(s) 49 | pStart = 0 50 | pEnd = 0 51 | listTemp = [] 52 | result = '' 53 | 54 | while pEnd < len(s): 55 | if pEnd == len(s) - 1: 56 | listTemp.append(self.Reverse(s[pStart:])) 57 | break 58 | if s[pStart] == ' ': 59 | pStart += 1 60 | pEnd += 1 61 | listTemp.append(' ') 62 | elif s[pEnd] == ' ': 63 | listTemp.append(self.Reverse(s[pStart:pEnd])) 64 | pStart = pEnd 65 | else: 66 | pEnd += 1 67 | for i in listTemp: 68 | result += ''.join(i) 69 | return result 70 | 71 | def Reverse(self, s): 72 | start = 0 73 | end = len(s) - 1 74 | while start < end: 75 | s[start], s[end] = s[end], s[start] 76 | start += 1 77 | end -= 1 78 | return s -------------------------------------------------------------------------------- /剑指offer/表示数值的字符串.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。 3 | 例如,字符串"+100","5e2","-123","3.1416"和"-1E-16"都表示数值。 但是"12e","1a3.14","1.2.3","+-5" 4 | 和"12e+4.3"都不是。 5 | ''' 6 | 7 | ''' 8 | 思路一:利用float强转 9 | 10 | 7ms 11 | 5632k 12 | ''' 13 | 14 | # -*- coding:utf-8 -*- 15 | class Solution: 16 | # s字符串 17 | def isNumeric(self, s): 18 | # write code here 19 | try: 20 | return float(s) 21 | except: 22 | return 0 23 | 24 | ''' 25 | 思路二:正则表达式 26 | 27 | 28ms 28 | 5632k 29 | ''' 30 | 31 | # -*- coding:utf-8 -*- 32 | class Solution: 33 | # s字符串 34 | def isNumeric(self, s): 35 | # write code here 36 | if not s: 37 | return 0 38 | import re 39 | # 正则表达式,*匹配前一个字符出现无限次或0次,?匹配前一个字符出现一次或0次,+匹配前一个字符出现1次 40 | # 或无限次,.表示小数点已经转义了 41 | return re.match(r'^[\+\-]?[0-9]*(\.[0-9]*)?([eE][\+\-]?[0-9]+)?$', s) 42 | 43 | ''' 44 | 思路三:判断s中所有字符串,以e为界,e后面不能出现.或空,否则直接返回False,然后把e前后两部分全部放到 45 | 一个判断函数里面,考虑所有出现的字符串,+-不能出现在首位,字符串里面.出现次数不能超过1 46 | 47 | 28ms 48 | 5632k 49 | ''' 50 | 51 | # -*- coding:utf-8 -*- 52 | class Solution: 53 | # s字符串 54 | def isNumeric(self, s): 55 | # write code here 56 | if not s or len(s) <= 0: 57 | return 0 58 | alist = [i.lower() for i in s] 59 | if 'e' in alist: 60 | index = alist.index('e') 61 | front = alist[:index] 62 | behind = alist[index + 1:] 63 | if '.' in behind or len(behind) == 0: 64 | return False 65 | isfront = self.Digit(front) 66 | isbehind = self.Digit(behind) 67 | return isfront and isbehind 68 | else: 69 | isNum = self.Digit(alist) 70 | return isNum 71 | 72 | def Digit(self, alist): 73 | dotNum = 0 74 | allowNum = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-', '.', 'e'] 75 | for i in range(len(alist)): 76 | if alist[i] not in allowNum: 77 | return False 78 | if alist[i] == '.': 79 | dotNum += 1 80 | if alist[i] in '+-' and i != 0: 81 | return False 82 | if dotNum > 1: 83 | return False 84 | return True 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /剑指offer/调整数组顺序使奇数位于偶数前面.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分, 3 | 所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。 4 | ''' 5 | 6 | ''' 7 | 方法一: 两个数组解 8 | 25ms 9 | 5504k 10 | ''' 11 | 12 | # -*- coding:utf-8 -*- 13 | class Solution: 14 | def reOrderArray(self, array): 15 | # write code here 16 | 17 | res1 = [] 18 | res2 = [] 19 | for i in array: 20 | if i % 2 == 0: 21 | res1.append(i) 22 | else: 23 | res2.append(i) 24 | return res2 + res1 25 | 26 | ''' 27 | 方法二:类似冒泡的思想,相互交换 28 | ''' 29 | -------------------------------------------------------------------------------- /剑指offer/连续子数组的最大和.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常 3 | 需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望 4 | 旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。你会不会被他 5 | 忽悠住?(子向量的长度至少是1) 6 | ''' 7 | 8 | ''' 9 | 对于连续子数组,可以用一个数值来存储当前和,如果当前和小于零,那么在进行到下一个元素的时候,直接把当前和赋值为下 10 | 一个元素,如果当前和大于零,则累加下一个元素,同时用一个maxNum存储最大值并随时更新。也可以利用动态规划解决。 11 | 12 | 29ms 13 | 5624k 14 | ''' 15 | 16 | # -*- coding:utf-8 -*- 17 | class Solution: 18 | def FindGreatestSumOfSubArray(self, array): 19 | # write code here 20 | if array == None or len(array) <= 0: 21 | return 0 22 | 23 | sum = 0 24 | result = array[0] 25 | for i in range(len(array)): 26 | if sum <= 0: 27 | sum = array[i] 28 | else: 29 | sum += array[i] 30 | 31 | if sum > result: 32 | result = sum 33 | 34 | return result 35 | 36 | 37 | -------------------------------------------------------------------------------- /剑指offer/重建二叉树.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目: 3 | 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 4 | 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。 5 | ''' 6 | 7 | ''' 8 | 46ms 9 | 5760k 10 | ''' 11 | 12 | 13 | # -*- coding:utf-8 -*- 14 | class TreeNode: 15 | def __init__(self, x): 16 | self.val = x 17 | self.left = None 18 | self.right = None 19 | 20 | class Solution: 21 | # 返回构造的TreeNode根节点 22 | def reConstructBinaryTree(self, pre, tin): 23 | # write code here 24 | if not pre or not tin: 25 | return None 26 | root = TreeNode(pre[0]) 27 | val = tin.index(pre[0]) 28 | 29 | # 可以动手试一下啊,第一个参数 30 | root.left = self.reConstructBinaryTree(pre[1:val + 1], tin[:val]) 31 | root.right = self.reConstructBinaryTree(pre[val + 1:], tin[val + 1:]) 32 | return root 33 | -------------------------------------------------------------------------------- /剑指offer/链表中倒数第k个节点.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入一个链表,输出该链表中倒数第k个结点。 3 | ''' 4 | 5 | ''' 6 | 使用列表的切片,还是很快的 7 | 24ms 8 | 5632k 9 | ''' 10 | 11 | # -*- coding:utf-8 -*- 12 | # class ListNode: 13 | # def __init__(self, x): 14 | # self.val = x 15 | # self.next = None 16 | 17 | class Solution: 18 | def FindKthToTail(self, head, k): 19 | # write code here 20 | res = [] 21 | while head: 22 | res.append(head) 23 | head = head.next 24 | if k > len(res) or k < 1: 25 | return 26 | return res[-k] -------------------------------------------------------------------------------- /剑指offer/链表中环的入口节点.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:一个链表中包含环,请找出该链表的环的入口结点。 3 | ''' 4 | 5 | ''' 6 | 思路:链表指针区只能指向一个下一个节点,所以如果链表中由环一定是在尾部。 7 | 寻找链表中环的入口结点主要分成三个步骤:首先是设置两个快慢指针,如果快慢指针相遇,则快慢指针必然都在环中; 8 | 然后从相遇的地方设置一个指针向后遍历并记录走的步数,当这个指针重新指到开始的位置的时候,当前对应的步数就是 9 | 环中结点的数量k;然后设置两个指针从链表开始,第一个节点先走k步,然后第二个指针指到链表的开始,两个指针每次 10 | 都向后走一步,两个指针相遇的位置就是链表的入口。 11 | 12 | 程序可以运行,但在牛客网上报错 'NoneType' object has no attribute 'next' 不知道为什么?? 13 | ''' 14 | 15 | # -*- coding:utf-8 -*- 16 | class ListNode: 17 | def __init__(self, x): 18 | self.val = x 19 | self.next = None 20 | 21 | class Solution: 22 | def EntryNodeOfLoop(self, pHead): 23 | # write code here 24 | MeetingNode = self.MeetingNode(pHead) 25 | if not MeetingNode: 26 | return None 27 | NodeOfLoop = 1 28 | FlagNode = MeetingNode 29 | # 从相遇点定义一个指针,指针向后移动到相遇点即为环的节点数NodeOfLoop 30 | while FlagNode.next != MeetingNode: 31 | NodeOfLoop += 1 32 | FlagNode = FlagNode.next 33 | 34 | # 两个指针都位于首位,让其中一个节点向前走环的节点数步,然后第二个指针走,当两个指针相遇时,即为环节点入口 35 | pFast = pHead 36 | pSlow = pHead 37 | for i in range(NodeOfLoop): 38 | pFast = pFast.next 39 | while pSlow != pFast: 40 | pSlow = pSlow.next 41 | pFast = pFast.next 42 | return pFast 43 | 44 | # 定义快慢指针,如果有环,快慢指针一定会相遇 45 | def MeetingNode(self, pHead): 46 | if not pHead: 47 | return None 48 | pSlow = pHead.next 49 | pFast = pSlow.next 50 | while pSlow != pFast: 51 | pSlow = pSlow.next 52 | pFast = pFast.next.next 53 | return pSlow 54 | 55 | node1 = ListNode(1) 56 | node2 = ListNode(2) 57 | node3 = ListNode(3) 58 | node4 = ListNode(4) 59 | node5 = ListNode(5) 60 | node6 = ListNode(6) 61 | 62 | node1.next = node2 63 | node2.next = node3 64 | node3.next = node4 65 | node4.next = node5 66 | node5.next = node6 67 | node6.next = node3 68 | 69 | s = Solution() 70 | print(s.EntryNodeOfLoop(node1).val) 71 | -------------------------------------------------------------------------------- /剑指offer/青蛙跳台阶.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。 3 | ''' 4 | 5 | ''' 6 | 对于本题,前提只有 一次 1阶或者2阶的跳法。 7 | a.如果两种跳法,1阶或者2阶,那么假定第一次跳的是一阶,那么剩下的是n-1个台阶,跳法是f(n-1); 8 | b.假定第一次跳的是2阶,那么剩下的是n-2个台阶,跳法是f(n-2) 9 | c.由a\b假设可以得出总跳法为: f(n) = f(n-1) + f(n-2)  10 | d.然后通过实际的情况可以得出:只有一阶的时候 f(1) = 1 ,只有两阶的时候可以有 f(2) = 2 11 | e.可以发现最终得出的是一个斐波那契数列: 12 |          13 |        | 1, (n=1) 14 | f(n) = | 2, (n=2) 15 |        | f(n-1)+f(n-2) ,(n>2,n为整数) 16 | 17 | 28ms 18 | 5632k 19 | ''' 20 | 21 | # -*- coding:utf-8 -*- 22 | class Solution: 23 | def jumpFloor(self, number): 24 | # write code here 25 | res = [1,2] 26 | while len(res) <= number: 27 | res.append(res[-1]+res[-2]) 28 | if number == 1: 29 | return 1 30 | else: 31 | return res[number-1] -------------------------------------------------------------------------------- /剑指offer/顺时针打印矩阵.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如, 3 | 如果输入如下矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 4 | 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10. 5 | ''' 6 | 7 | ''' 8 | 思路超神: 9 | 可以模拟魔方逆时针旋转的方法,一直做取出第一行的操作 10 | 例如 11 | 1 2 3 12 | 4 5 6 13 | 7 8 9 14 | 输出并删除第一行后,再进行一次逆时针旋转,就变成: 15 | 6 9 16 | 5 8 17 | 4 7 18 | 继续重复上述操作即可 19 | 20 | 24ms 21 | 5632k 22 | ''' 23 | 24 | # -*- coding:utf-8 -*- 25 | class Solution: 26 | # matrix类型为二维列表,需要返回列表 27 | def printMatrix(self, matrix): 28 | # write code here 29 | result = [] 30 | while (matrix): 31 | result += matrix.pop(0) 32 | if not matrix: 33 | break 34 | matrix = self.turn(matrix) 35 | return result 36 | 37 | def turn(self, matrix): 38 | newmat = [] 39 | row = len(matrix) 40 | col = len(matrix[0]) 41 | for i in range(col): 42 | newmat1 = [] 43 | for j in range(row): 44 | newmat1.append(matrix[j][i]) 45 | newmat.append(newmat1) 46 | newmat.reverse() 47 | return newmat 48 | 49 | -------------------------------------------------------------------------------- /华为机试/删除字符串中出现次数最少的字符.py: -------------------------------------------------------------------------------- 1 | # x = input() 2 | # 3 | # res = [] 4 | # for i in x: 5 | # if x.count(i) > 1: 6 | # res.append(i) 7 | # 8 | # print(''.join(res)) 9 | 10 | from collections import defaultdict 11 | while True: 12 | try: 13 | a = input() 14 | dd = defaultdict(int) 15 | for i in a: 16 | dd[i] += 1 17 | for i in dd: 18 | if dd[i] == min(dd.values()): 19 | a = a.replace(i,'') 20 | print(a) 21 | except: 22 | break 23 | 24 | -------------------------------------------------------------------------------- /华为机试/判断两个IP是否属于同一子网.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leeguandong/Interview-code-practice-python/86933f82f3553dfca16055977d7366b106b511bd/华为机试/判断两个IP是否属于同一子网.py -------------------------------------------------------------------------------- /华为机试/单词倒排.py: -------------------------------------------------------------------------------- 1 | x = input().replace('*', ' ').replace('#', ' ').replace('!', ' ').replace('$', ' ').split() 2 | 3 | print(' '.join(x[::-1])) 4 | -------------------------------------------------------------------------------- /华为机试/取近似值.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:写出一个程序,接受一个正浮点数值,输出该数值的近似整数值。如果小数点后数值大于等于5,向上取整; 3 | 小于5,则向下取整。 4 | ''' 5 | 6 | ''' 7 | 思路: 8 | 9 | 32ms 10 | 3436k 11 | ''' 12 | 13 | try: 14 | while True: 15 | a = eval(input()) 16 | if (a - int(a)) >= 0.5: 17 | print(int(a) + 1) 18 | else: 19 | print(int(a)) 20 | except: 21 | pass 22 | -------------------------------------------------------------------------------- /华为机试/句子逆序.py: -------------------------------------------------------------------------------- 1 | x = input().split() 2 | print(' '.join(x[::-1])) 3 | -------------------------------------------------------------------------------- /华为机试/合唱队.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 两遍最长递增子序列,第一遍从左往右,第二遍从右往左,然后把两遍动态 3 | 规划的结果相加,区最大的那个,比如 8 186 186 150 200 160 130 197 200 4 | 第一遍dp的结果是1 1 1 2 2 1 3 4,第二遍dp的结果是3 3 2 3 2 1 1 1, 5 | 那么相加最大是5,所以需要出列的同学的个数是8-5+1 = 4. 6 | 7 | ''' -------------------------------------------------------------------------------- /华为机试/合并表记录.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:数据表记录包含表索引和数值,请对表索引相同的记录进行合并,即将相同索引的数值进行求和运算, 3 | 输出按照key值升序进行输出。 4 | ''' 5 | 6 | ''' 7 | 思路: 8 | 9 | 10 | ''' 11 | 12 | n = input().split() 13 | res = {} 14 | for i in range(int(n[0])): 15 | k, d = map(int, input().split()) 16 | if k in res.keys(): 17 | res[k] = res[k] + d 18 | else: 19 | res[k] = d 20 | 21 | for k, d in res.items(): 22 | print(str(k) + ' ' + str(d)) 23 | -------------------------------------------------------------------------------- /华为机试/图片整理.py: -------------------------------------------------------------------------------- 1 | while True: 2 | try: 3 | x = input() 4 | res = [] 5 | res1 = [] 6 | for i in x: 7 | res.append(ord(i)) 8 | for j in sorted(res): 9 | res1.append(chr(j)) 10 | print(''.join(res1)) 11 | except: 12 | break 13 | -------------------------------------------------------------------------------- /华为机试/坐标移动.py: -------------------------------------------------------------------------------- 1 | while True: 2 | try: 3 | x = input().split(';') 4 | res = [0, 0] 5 | for i in range(len(x)): 6 | if x[i] == '': 7 | continue 8 | # print(x[i]) 9 | # print(x[i][0]) 10 | if x[i][0] == 'A': 11 | # print(''.join(x[i][1:])) 12 | if ''.join(x[i][1:]).isnumeric(): 13 | res[0] -= int(x[i][1:]) 14 | # print(res[0]) 15 | else: 16 | continue 17 | elif x[i][0] == 'D': 18 | if ''.join(x[i][1:]).isnumeric(): 19 | res[0] += int(x[i][1:]) 20 | else: 21 | continue 22 | elif x[i][0] == 'W': 23 | if ''.join(x[i][1:]).isnumeric(): 24 | res[1] += int(x[i][1:]) 25 | else: 26 | continue 27 | elif x[i][0] == 'S': 28 | if ''.join(x[i][1:]).isnumeric(): 29 | res[1] -= int(x[i][1:]) 30 | else: 31 | continue 32 | 33 | print(str(res[0]) + ',' + str(res[1])) 34 | except: 35 | break 36 | 37 | -------------------------------------------------------------------------------- /华为机试/字串的连接最长路径查找.py: -------------------------------------------------------------------------------- 1 | n = input().split() 2 | 3 | res = [] 4 | print(int(n[0])) 5 | for i in range(int(n[0])): 6 | res.append(input().split()) 7 | 8 | res.sort() 9 | # print(res) 10 | 11 | for i in res: 12 | print(''.join(i)) 13 | -------------------------------------------------------------------------------- /华为机试/字符个数统计.py: -------------------------------------------------------------------------------- 1 | result = '' 2 | 3 | for i in input(): 4 | if i not in result: 5 | result += i 6 | print(len(result)) 7 | -------------------------------------------------------------------------------- /华为机试/字符串分割.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:•连续输入字符串,请按长度为8拆分每个字符串后输出到新的字符串数组; 3 | •长度不是8整数倍的字符串请在后面补数字0,空字符串不处理。 4 | ''' 5 | 6 | ''' 7 | 思路: 8 | 9 | 37ms 10 | 3696k 11 | ''' 12 | 13 | str1 = input() 14 | str2 = input() 15 | 16 | def out(str): 17 | a = len(str) % 8 18 | if a != 0: 19 | str = str + ('0' * (8 - a)) 20 | for i in range(len(str) // 8): 21 | print(str[i * 8:8 * (i + 1)]) 22 | 23 | out(str1) 24 | out(str2) 25 | -------------------------------------------------------------------------------- /华为机试/字符串加密.py: -------------------------------------------------------------------------------- 1 | # while True: 2 | # try: 3 | # x = input() 4 | # res = [] 5 | # for i in range(len(x)): 6 | # print(x[i]) 7 | # if x[i].islower(): 8 | # print(x[i]) 9 | # if x[i] == 'z': 10 | # x[i] = 'a' 11 | # else: 12 | # y1 = chr(ord(x[i]) + 1) 13 | # # print(y) 14 | # res.append(y1.upper()) 15 | # # print(res) 16 | # if x[i].isnumeric(): 17 | # if x[i] == '9': 18 | # x[i] = '0' 19 | # else: 20 | # y2 = str(int(x[i]) + 1) 21 | # res.append(y2) 22 | # if x[i].isupper(): 23 | # if x[i] == 'Z': 24 | # x[i] = 'z' 25 | # else: 26 | # y3 = chr(ord(x[i]) - 1) 27 | # res.append(y3.lower()) 28 | # print(''.join(res)) 29 | # 30 | # except: 31 | # break 32 | 33 | while True: 34 | try: 35 | a, b = input(), input() 36 | resA, resB = "", "" 37 | for i in a: 38 | if i.isupper(): 39 | if i != "Z": 40 | resA += chr(ord(i) + 1).lower() 41 | else: 42 | resA += "a" 43 | elif i.islower(): 44 | if i != "z": 45 | resA += chr(ord(i) + 1).upper() 46 | else: 47 | resA += "A" 48 | elif i.isdigit(): 49 | if i != "9": 50 | resA += chr(ord(i) + 1) 51 | else: 52 | resA += "0" 53 | for i in b: 54 | if i.isupper(): 55 | if i != "A": 56 | resB += chr(ord(i) - 1).lower() 57 | else: 58 | resB += "z" 59 | elif i.islower(): 60 | if i != "a": 61 | resB += chr(ord(i) - 1).upper() 62 | else: 63 | resB += "Z" 64 | elif i.isdigit(): 65 | if i != "0": 66 | resB += chr(ord(i) - 1) 67 | else: 68 | resB += "9" 69 | print(resA) 70 | print(resB) 71 | except: 72 | break 73 | -------------------------------------------------------------------------------- /华为机试/字符串加密2.py: -------------------------------------------------------------------------------- 1 | while True: 2 | try: 3 | x = input() 4 | n = input().split() 5 | 6 | res = [] 7 | res1 = [] 8 | Cap = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 9 | 'V', 10 | 'W', 'X', 'Y', 'Z'] 11 | for i in x: 12 | if i not in res: 13 | res.append(i) 14 | else: 15 | continue 16 | for i in res: 17 | res1.append(i.upper()) 18 | 19 | res2 = [] 20 | for i in Cap: 21 | if i not in res1: 22 | res2.append(i) 23 | else: 24 | continue 25 | 26 | res3 = [] 27 | newres = res1 + res2 28 | # print(newres) 29 | 30 | for i in ''.join(n): 31 | if i.isupper(): 32 | if i in Cap: 33 | res3.append(newres[Cap.index(i)]) 34 | if i.islower(): 35 | if i.upper() in Cap: 36 | res3.append(newres[Cap.index(i.upper())].lower()) 37 | 38 | print(''.join(res3)) 39 | except: 40 | break 41 | -------------------------------------------------------------------------------- /华为机试/字符串反转.py: -------------------------------------------------------------------------------- 1 | print(input()[::-1]) 2 | -------------------------------------------------------------------------------- /华为机试/字符串合并处理.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 将输入的两个字符串合并,要求是下标为奇数的字符和下标为偶数的字符分别从小到大 3 | 排序。 4 | ''' 5 | 6 | while True: 7 | try: 8 | dic = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'] 9 | 10 | # s是输入的合并后的字符串 11 | s = input().replace(' ', '') 12 | 13 | # ss为最终返回的字符串 14 | ss = '' 15 | 16 | # 字符串的奇数子串和偶数子串 17 | odd, even = '', '' 18 | # 经过下面的循环,提取奇数和偶数的子串 19 | for i, v in enumerate(s): 20 | if i % 2 == 0: 21 | even += v 22 | else: 23 | odd += v 24 | # 奇数与偶数部分排序 25 | odd = ''.join(sorted(odd)) 26 | even = ''.join(sorted(even)) 27 | 28 | # 如果字符串在0123456789abcdef范围内,对其做变换,否则不做任何处理 29 | for i in range(len(even)): 30 | if even[i] in '0123456789abcdefABCDEF': 31 | ss += dic[int(bin(dic.index(even[i].upper())).replace("0b", "").rjust(4, "0")[::-1], 2)] 32 | else: 33 | ss += even[i] 34 | # 注意偶数串可能比奇数串长一个字符,所以要判断一下 35 | if len(odd) != i: 36 | if len(odd) != i: 37 | ss += dic[int(bin(dic.index(odd[i].upper())).replace('0b', '').rjust(4, '0')[::-1], 2)] 38 | else: 39 | ss += odd[i] 40 | print(ss) 41 | except: 42 | break 43 | -------------------------------------------------------------------------------- /华为机试/字符串排序.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 编写一个程序,将输入字符串中的字符按如下规则排序。 3 | 规则 1 :英文字母从 A 到 Z 排列,不区分大小写。 4 | 如,输入: Type 输出: epTy 5 | 规则 2 :同一个英文字母的大小写同时存在时,按照输入顺序排列。 6 | 如,输入: BabA 输出: aABb 7 | 规则 3 :非英文字母的其它字符保持原来的位置。 8 | 如,输入: By?e 输出: Be?y 9 | ''' 10 | 11 | while True: 12 | try: 13 | a = input() 14 | # res 是最终返回的字符串的列表形式,char 是提取的英文字母 15 | res, char = [False] * len(a), [] 16 | # 经过这个循环,把相应的非英文字母及其位置存储到 res 中,并且把英文字母提取出来 17 | for i, v in enumerate(a): 18 | if v.isalpha(): 19 | char.append(v) 20 | else: 21 | res[i] = v 22 | # 使用 lambda 表示式排序 23 | char.sort(key=lambda c: c.lower()) 24 | # 将 char 中对应的字符填到 res 中 25 | for i, v in enumerate(res): 26 | if not v: 27 | res[i] = char[0] 28 | char.pop(0) 29 | print(''.join(res)) 30 | except: 31 | break 32 | -------------------------------------------------------------------------------- /华为机试/字符串最后一个单词的长度.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:计算字符串最后一个单词的长度,单词以空格隔开。 3 | ''' 4 | 5 | ''' 6 | 思路:split() 空格为界,字符串转列表 7 | 8 | 38ms 9 | 3824k 10 | ''' 11 | 12 | a = input().split() 13 | if len(a) > 1: 14 | print(len(a[-1])) 15 | else: 16 | print(len(a[0])) 17 | -------------------------------------------------------------------------------- /华为机试/字符串运用-密码截取.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Catcher是MCA国的情报员,他工作时发现敌国会用一些对称的密码进行通信,比如像这些ABBA,ABA,A,123321,但是他们有时会在开始或结束时 3 | 加入一些无关的字符以防止别国破解。比如进行下列变化 ABBA->12ABBA,ABA->ABAKK,123321->51233214 。因为截获的串太长了,而且存在多 4 | 种可能的情况(abaaab可看作是aba,或baaab的加密形式),Cathcer的工作量实在是太大了,他只能向电脑高手求助,你能帮Catcher找出最长的 5 | 有效密码串吗? 6 | ''' 7 | # x = input().split() 8 | # 9 | # def longest(x): 10 | # maximum = '' 11 | # temp = '' 12 | # for index in range(len(x)): 13 | # if len(maximum) >= len(x) - index: 14 | # break 15 | # for index2 in range(index + len(maximum), len(x) + 1): 16 | # fw = x[index:index2] 17 | # bw = fw[::-1] 18 | # if len(temp) > len(maximum): 19 | # maximum = temp 20 | # return maximum 21 | # 22 | # print(longest(x)) 23 | 24 | 25 | ''' 26 | 动态规划 27 | true j=i 28 | dp[j][i] = str[i] == str[j] i-j=1 29 | str[i] == str[j] && dp[j+1][i-1] i-j>1 30 | ''' 31 | 32 | def longestpalindrome(s): 33 | if s == s[::-1]: 34 | return len(s) 35 | maxlen = 0 36 | for i in range(len(s)): 37 | if i - maxlen >= 1 and s[i - maxlen - 1:i + 1] == s[i - maxlen - 1:i + 1][::-1]: 38 | maxlen += 2 39 | print(s[i - maxlen - 1:i + 1], maxlen) 40 | continue 41 | if i - maxlen >= 0 and s[i - maxlen:i + 1] == s[i - maxlen:i + 1][::-1]: 42 | maxlen += 1 43 | print(s[i - maxlen - 1:i + 1], maxlen) 44 | return maxlen 45 | 46 | while True: 47 | try: 48 | a = input() 49 | if a: 50 | print(longestpalindrome(a)) 51 | except: 52 | break 53 | -------------------------------------------------------------------------------- /华为机试/密码验证合格程序.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 1.长度超过8位 3 | 2.包括大小写字母.数字.其它符号,以上四种至少三种 4 | 3.不能有相同长度超2的子串重复 5 | 说明:长度超过2的子串 6 | ''' 7 | 8 | # import re, sys 9 | # 10 | # for i in sys.stdin.readlines(): 11 | # print("OK" if len(i.strip()) > 8 and sum( 12 | # [1 if re.search(r"[A-Z]", i.strip()) else 0, 1 if re.search(r"[a-z]", i.strip()) else 0, 13 | # 1 if re.search(r"[0-9]", i.strip()) else 0, 1 if re.search(r"[^0-9a-zA-Z]", i.strip()) else 0]) > 2 and sum( 14 | # map(lambda c: i.strip().count(i.strip()[c:c + 3]) > 1, range(1, len(i.strip()) - 3))) == 0 else "NG") 15 | 16 | # 略微思考会发现,只需要判断长度为3的子串是否出现即可。因为假设子串长度为4的出现,则一定包括了长度为3的子串。同时需要注意, 17 | # 本题说的子串指包括了部分子串重叠的情况, 18 | # 例如Qw11111*ed这个是不能通过的。再就是需要注意,判断子串的时候只需要判断到len(str)-3就行了。 19 | 20 | import sys 21 | 22 | try: 23 | # 大小写,字母, 24 | def panchar(sss): 25 | standard = [0] * 4 26 | for i in sss: 27 | # print(i) 28 | # 0 29 | # 2 30 | # 1 31 | # A 32 | # b 33 | # print(len(sss)) 34 | # 数字 35 | if i.isdigit(): 36 | standard[0] = 1 37 | # print(i.isdigit()) 38 | # 小写 39 | if i.islower(): 40 | standard[1] = 1 41 | # 大写 42 | if i.isupper(): 43 | standard[2] = 1 44 | # 全都是字母,数字,空格 45 | if not i.isalpha() and not i.isdigit() and not i.isspace(): 46 | standard[3] = 1 47 | if sum(standard) >= 3: 48 | return False 49 | return True 50 | 51 | # 不能有相同长度超 2 的字串重复 52 | def zichuan(sss): 53 | for i in range(len(sss) - 3): 54 | zichuan_1 = sss[i: i + 3] 55 | zichuan_2 = sss[i + 1::] 56 | if zichuan_1 in zichuan_2: 57 | return True 58 | return False 59 | 60 | result = [] 61 | while True: 62 | line = sys.stdin.readline().strip() 63 | if line == '': 64 | break 65 | if len(line) <= 8: 66 | result.append('NG') 67 | # 大小写字母.数字.其它符号 68 | elif panchar(line): 69 | result.append('NG') 70 | elif zichuan(line): 71 | result.append('NG') 72 | else: 73 | result.append('OK') 74 | for i in result: 75 | print(i) 76 | except: 77 | pass 78 | 79 | 80 | # # 循环输入,try catch 81 | # while True: 82 | # try: 83 | # x = input().split() 84 | # 85 | # 86 | # except: 87 | # pass 88 | -------------------------------------------------------------------------------- /华为机试/提取不重复的整数.py: -------------------------------------------------------------------------------- 1 | result = '' 2 | 3 | for i in input()[::-1]: 4 | if i not in result: 5 | result += i 6 | print(result) 7 | -------------------------------------------------------------------------------- /华为机试/数字颠倒.py: -------------------------------------------------------------------------------- 1 | print(input()[::-1]) 2 | -------------------------------------------------------------------------------- /华为机试/数据分类处理.py: -------------------------------------------------------------------------------- 1 | while True: 2 | try: 3 | a = input().split()[1:] 4 | b = map(str, sorted(map(int, set(input().split()[1:])))) 5 | totalNum = 0 6 | res = '' 7 | for num in b: 8 | singleRes, count = '', 0 9 | for i, v in enumerate(a): 10 | if num in v: 11 | singleRes += str(i) + '' + '' 12 | totalNum += 2 13 | count += 1 14 | if count: 15 | singleRes = num + '' + str(count) + '' + singleRes 16 | totalNum += 2 17 | res += singleRes 18 | print((str(totalNum) + '' + res).rstrip()) 19 | except: 20 | break 21 | -------------------------------------------------------------------------------- /华为机试/整数与IP地址间的转换.py: -------------------------------------------------------------------------------- 1 | while True: 2 | try: 3 | print(sum([256 ** j * int(i) for j, i in enumerate(input().split('.')[::-1])])) 4 | b = int(input()) 5 | print('.'.join([str(b // (256 ** i) % 256) for i in range(3, -1, -1)])) 6 | except: 7 | break 8 | -------------------------------------------------------------------------------- /华为机试/明明的随机数.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的 3 | 随机整数(N≤1000),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。 4 | 然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。 5 | Input Param 6 | n 输入随机数的个数 7 | inputArray n个随机整数组成的数组 8 | Return Value 9 | OutputArray 输出处理后的随机整数 10 | 11 | 注:测试用例保证输入参数的正确性,答题者无需验证。测试用例不止一组。 12 | ''' 13 | 14 | ''' 15 | 思路:set可以去重,sort排序 16 | 17 | 42ms 18 | 3428k 19 | ''' 20 | 21 | while True: 22 | try: 23 | n = int(input()) 24 | l = [] 25 | for _ in range(n): 26 | l.append(int(input())) 27 | l = sorted(set(l)) 28 | for i in l: 29 | print(i) 30 | except: 31 | break 32 | -------------------------------------------------------------------------------- /华为机试/查找兄弟单词.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 字典顺序: 3 | 两个单词(字母按照自左向右顺序),先以第一个字母作为排序的基准,如果第一个字母相同, 4 | 就用第二个字母为基准,如果第二个字母相同就以第三个字母为基准。依次类推,如果 5 | 到某个字母不相同,字母顺序在前的那个单词顺序在前。如果短单词是长单词从首字母开始 6 | 连续的一部分,短单词顺序在前。 7 | ''' 8 | 9 | # while True: 10 | # try: 11 | # x = input().split() 12 | # from collections import defaultdict 13 | # 14 | # dd = defaultdict(list) 15 | # res = [] 16 | # 17 | # for i in range(1, int(x[0]) + 1): 18 | # # print(x[i]) 19 | # dd[''.join(sorted(x[i]))].append(x[i]) 20 | # # print(dd) 21 | # for key, value in dd.items(): 22 | # if key == ''.join(sorted(x[-2])): 23 | # res.append(value) 24 | # # print(len(value) - 1) 25 | # # print(value[int(x[-1])]) 26 | # 27 | # for i in res: 28 | # for j in i: 29 | # if ''.join(j) == x[-2]: 30 | # res[0].remove(j) 31 | # 32 | # # print(res) 33 | # if res == []: 34 | # print(0) 35 | # else: 36 | # print(len(res[0])) 37 | # print(res[0][int(x[-1]) - 1]) 38 | # 39 | # except: 40 | # break 41 | 42 | 43 | from collections import defaultdict 44 | 45 | while True: 46 | try: 47 | dd = defaultdict(list) 48 | a = input().split() 49 | words, lookup, num, brothers = a[1:1 + int(a[0])], a[-2], int(a[-1]), [] 50 | for i in words: 51 | dd[''.join(sorted(i))].append(i) 52 | for i in dd[''.join(sorted(lookup))]: 53 | if i != lookup: 54 | brothers.append(i) 55 | 56 | print(len(brothers)) 57 | if brothers and num <= len(brothers): 58 | print(sorted(brothers)[num - 1]) 59 | except: 60 | break 61 | -------------------------------------------------------------------------------- /华为机试/求int型正整数在内存中存储时1的个数.py: -------------------------------------------------------------------------------- 1 | x = input().split() 2 | 3 | x = bin(int(x[0])) 4 | print(x.count('1')) 5 | -------------------------------------------------------------------------------- /华为机试/求小球落地5次后所经历的路程和第5次反弹的高度.py: -------------------------------------------------------------------------------- 1 | while True: 2 | try: 3 | x = input() 4 | number = int(x) 5 | print(2.875 * number) 6 | print(0.03125 * number) 7 | except: 8 | break 9 | -------------------------------------------------------------------------------- /华为机试/汽水瓶.py: -------------------------------------------------------------------------------- 1 | # 每两个汽水瓶换一个,所以除以 2 就可以了 2 | 3 | while True: 4 | try: 5 | a = int(input()) 6 | if a != 0: 7 | print(a // 2) 8 | except: 9 | break 10 | -------------------------------------------------------------------------------- /华为机试/称砝码.py: -------------------------------------------------------------------------------- 1 | def fama(n, weight, nums): 2 | res = set() 3 | for i in range(nums[0] + 1): 4 | res.add(i * weight[0]) 5 | for i in range(1, n): 6 | tmp = list(res) 7 | for j in range(1, nums[i] + 1): 8 | for wt in tmp: 9 | res.add(wt + j * weight[i]) 10 | return len(res) 11 | 12 | while True: 13 | try: 14 | n = int(input()) 15 | weight = [int(i) for i in input().split()] 16 | nums = [int(i) for i in input().split()] 17 | print(fama(n, weight, nums)) 18 | except: 19 | break 20 | 21 | -------------------------------------------------------------------------------- /华为机试/简单密码.py: -------------------------------------------------------------------------------- 1 | x = input().split() 2 | 3 | def mima(s): 4 | if s in 'Z': 5 | s = 'a' 6 | elif s.isupper(): 7 | s = chr(ord(s.lower()) + 1) 8 | elif s in 'abc': 9 | s = '2' 10 | elif s in 'def': 11 | s = '3' 12 | elif s in 'ghi': 13 | s = '4' 14 | elif s in 'jkl': 15 | s = '5' 16 | elif s in 'mno': 17 | s = '6' 18 | elif s in 'pqrs': 19 | s = '7' 20 | elif s in 'tuv': 21 | s = '8' 22 | elif s in 'wxyz': 23 | s = '9' 24 | elif s in '0': 25 | s = '0' 26 | return s 27 | 28 | res = [] 29 | for i in range(len(x[0])): 30 | res.append(mima(x[0][i])) 31 | 32 | print(''.join(res)) 33 | -------------------------------------------------------------------------------- /华为机试/简单错误记录.py: -------------------------------------------------------------------------------- 1 | # while True: 2 | # x = input().split() 3 | # y = x[0].index('\\') 4 | # print(y) 5 | # count = x[y[-1]:] 6 | # if count >= 16: 7 | # count = count[-16:] 8 | # print(count) 9 | 10 | error = dict() 11 | filelist = [] 12 | while True: 13 | try: 14 | record = ''.join(''.join(input().split('\\')[-1].split())) 15 | filename = record.split() 16 | if len(filename[0]) >= 16: 17 | filename[0] = filename[0][-16:] 18 | record = ''.join(filename) 19 | if record not in error.keys(): 20 | error[record] = 1 21 | filelist.append(record) 22 | else: 23 | error[record] += 1 24 | except: 25 | break 26 | key = filelist[-8:] 27 | for each in key: 28 | print(''.join(each.split()), error[each]) 29 | -------------------------------------------------------------------------------- /华为机试/素数伴侣.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leeguandong/Interview-code-practice-python/86933f82f3553dfca16055977d7366b106b511bd/华为机试/素数伴侣.py -------------------------------------------------------------------------------- /华为机试/统计每个月兔子的总数.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 有一只兔子,从出生后第3个月起每个月都生一只兔子,小兔子长到第三个月后每个月又生一只兔子,假如兔子都不死,问每个月的兔子总数为多少? 3 | 4 | ''' 5 | 6 | while True: 7 | try: 8 | x = [int(i) for i in input().split()] 9 | 10 | res = [1, 2] 11 | 12 | for i in range(x[0] - 3): 13 | res.append(res[-1] + res[-2]) 14 | 15 | # print(res) 16 | print(res[-1]) 17 | except: 18 | break 19 | -------------------------------------------------------------------------------- /华为机试/蛇形矩阵.py: -------------------------------------------------------------------------------- 1 | # while True: 2 | # try: 3 | # n = input() 4 | # start = 0 5 | # for i in range(n): 6 | # start += i 7 | # count = start 8 | # for j in range(i + 2, n + 2): 9 | # print(count + 1) 10 | # count += j 11 | # 12 | # except: 13 | # break 14 | 15 | def minusOne(num): 16 | return num - 1 17 | 18 | while True: 19 | try: 20 | lineNum = int(input()) 21 | temp = [] 22 | for i in range(2, lineNum + 2): 23 | temp.append(sum(range(i))) 24 | for j in range(lineNum): 25 | print(' '.join(map(str, temp))) 26 | temp = list(map(minusOne, temp[1:])) 27 | except Exception: 28 | break 29 | -------------------------------------------------------------------------------- /华为机试/计算字符个数.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:写出一个程序,接受一个有字母和数字以及空格组成的字符串,和一个字符, 3 | 然后输出输入字符串中含有该字符的个数。不区分大小写。 4 | ''' 5 | 6 | ''' 7 | 思路: 8 | 9 | 36ms 10 | 3552k 11 | ''' 12 | 13 | a = input().lower() 14 | b = input().lower() 15 | print(a.count(b)) 16 | -------------------------------------------------------------------------------- /华为机试/识别有效的IP地址和掩码并进行分类统计.py: -------------------------------------------------------------------------------- 1 | ''' 2 | A B C D E IP地址错误会错误掩码 私有IP 3 | 4 | 判断子网掩码是否有效 5 | 1.通过判断是否为 255.255.255.255 ,如果是,错误加1, 6 | 2.判断子网掩码是否正确。根据子网掩码二进制规律(开头为连续的1,然后为0),我们 7 | 将子网掩码按位取反,然后加1,得到的新二进制维,然而我们通过判断二进制中1的个数来 8 | 判断是否为合法的子网掩码。 9 | 10 | 判断ABCDE地址 11 | ''' 12 | 13 | -------------------------------------------------------------------------------- /华为机试/质数因子.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:功能:输入一个正整数,按照从小到大的顺序输出它的所有质数的因子(如180的质数因子为2 2 3 3 5 ) 3 | 最后一个数后面也要有空格 4 | 5 | 详细描述: 6 | 函数接口说明: 7 | public String getResult(long ulDataInput) 8 | 输入参数: 9 | long ulDataInput:输入的正整数 10 | 返回值: 11 | String 12 | 13 | ''' 14 | 15 | ''' 16 | 把输入的数进行因式分解,只不过分解的数必须是质数 17 | 思路:对于一个数来说,比如180,从2开始遍历,如果能被2整除,那么180/=2,并且输出2,之后再拿90重复上述操作 18 | 直到变成1为止 19 | 20 | 45ms 21 | 3560k 22 | ''' 23 | 24 | n, res = int(input()), [] 25 | for i in range(2, n // 2 + 1): 26 | while n % i == 0: 27 | res.append(i) 28 | n = n / i 29 | print(" ".join(map(str, res)) + " " if res else str(n) + " ") 30 | -------------------------------------------------------------------------------- /华为机试/购物单.py: -------------------------------------------------------------------------------- 1 | N_m = input().split() 2 | N = int(N_m[0]) 3 | m = int(N_m[1]) 4 | 5 | v = [] 6 | p = [] 7 | q = [] 8 | 9 | for i in range(m): 10 | vpq = input().split() 11 | v.append(int(vpq[0])) 12 | p.append(int(vpq[1])) 13 | q.append(int(vpq[2])) 14 | 15 | def max_fun(N, m, v, p, q): 16 | res = [[0] * (N - 1) for _ in range(m + 1)] 17 | # 商品 18 | for i in range(1, m + 1): 19 | # 价格 20 | for j in range(10, N + 1, 10): 21 | # 为主件时 22 | if q[i - 1] == 0: 23 | if v[i - 1] <= j: 24 | res[i][j] = max(res[i - 1][j], res[i - 1][j - v[i - 1]] + v[i - 1] * p[i - 1]) 25 | # 为配件时 26 | elif v[i - 1] + v[q[i - 1]] <= j: 27 | res[i][j] = max(res[i - 1][j], res[i - 1][j - v[i - 1] - v[q[i - 1]]] + v[i - 1] * p[i - 1] + v[ 28 | q[i - 1] * p[q[i - 1]]]) 29 | print(res[m][int(N / 10) * 10]) 30 | 31 | max_fun(N, m, v, p, q) 32 | 33 | res[m] -------------------------------------------------------------------------------- /华为机试/输入一行字符,分别统计出包含英文字母、空格、数字和其它字符的个数.py: -------------------------------------------------------------------------------- 1 | while True: 2 | try: 3 | x = input() 4 | 5 | count1 = 0 6 | count2 = 0 7 | count3 = 0 8 | count4 = 0 9 | for i in x: 10 | if i.isalpha(): 11 | count1 += 1 12 | elif i.isspace(): 13 | count2 += 1 14 | elif i.isnumeric(): 15 | count3 += 1 16 | else: 17 | count4 += 1 18 | print(count1) 19 | print(count2) 20 | print(count3) 21 | print(count4) 22 | except: 23 | break 24 | -------------------------------------------------------------------------------- /华为机试/进制转换.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 题目:写出一个程序,接受一个十六进制的数值字符串,输出该数值的十进制字符串。(多组同时输入 ) 3 | ''' 4 | 5 | ''' 6 | 思路一: 用 int(x,[base]) 将一个数字或 base 类型的字符串转换成整数。 缺省 base ,按十进制算 7 | 8 | 36ms 9 | 3448k 10 | ''' 11 | 12 | while True: 13 | try: 14 | print(int(input(), 16)) 15 | except: 16 | break 17 | 18 | ''' 19 | 思路二: 用 eval(source[, globals[, locals]]) ,将字符串转掉,变成一个数字,以十进制打印出来 20 | 21 | 35ms 22 | 3564k 23 | ''' 24 | 25 | while True: 26 | try: 27 | n = input() 28 | n = eval(n) 29 | print(n) 30 | except: 31 | break 32 | -------------------------------------------------------------------------------- /机试题/排序.py: -------------------------------------------------------------------------------- 1 | # https://blog.csdn.net/u012193416/article/details/78790448 2 | # # 冒泡排序 3 | # # 时间复杂度 O(n**2) 空间复杂度 O(1) 4 | # x = [int(i) for i in input().split(',')] 5 | # 6 | # # print(x) 7 | # 8 | # def mpsort(x): 9 | # n = len(x) 10 | # # print(n) 11 | # for i in range(n - 1): 12 | # for j in range(0, n - i - 1): 13 | # # print(x[j]) 14 | # if x[j] > x[j + 1]: 15 | # x[j], x[j + 1] = x[j + 1], x[j] 16 | # return x 17 | # 18 | # print(mpsort(x)) 19 | 20 | # # 选择排序 21 | # # 时间复杂度 O(n**2) 空间复杂度 O(1) 22 | # x = [int(i) for i in input().split(',')] 23 | # 24 | # def xzsort(x): 25 | # n = len(x) 26 | # for i in range(n - 1): 27 | # min = i 28 | # for j in range(i + 1, n): 29 | # if x[j] < x[min]: 30 | # min = j 31 | # x[i], x[min] = x[min], x[i] 32 | # return x 33 | # 34 | # print(xzsort(x)) 35 | 36 | # # 插入排序 37 | # # 时间复杂度 O(n**2) 空间复杂度 O(1) 38 | # x = [int(i) for i in input().split(',')] 39 | # 40 | # def crsort(x): 41 | # n = len(x) 42 | # for i in range(1, n): 43 | # j = i 44 | # while j > 0: 45 | # if x[j] < x[j - 1]: 46 | # x[j], x[j - 1] = x[j - 1], x[j] 47 | # j -= 1 48 | # else: 49 | # break 50 | # return x 51 | # 52 | # print(crsort(x)) 53 | 54 | # # 希尔排序 55 | # # 时间复杂度 O(nlogn)-O(n**2) 空间复杂度 O(1) 56 | # x = [int(i) for i in input().split(',')] 57 | # 58 | # def shellsort(x): 59 | # n = len(x) 60 | # gap = n // 2 61 | # 62 | # while gap > 0: 63 | # for i in range(gap, n): 64 | # j = i 65 | # while j > 0: 66 | # if x[j] < x[j - gap]: 67 | # x[j], x[j - gap] = x[j - gap], x[j] 68 | # j -= gap 69 | # else: 70 | # break 71 | # gap //= 2 72 | # return x 73 | # 74 | # print(shellsort(x)) 75 | 76 | # # 快速排序 77 | # # 时间复杂度 O(nlogn) 空间复杂度 O(logn)-O(n) 78 | # x = [int(i) for i in input().split(',')] 79 | # 80 | # def kpsort(x, first, last): 81 | # font = first 82 | # end = last 83 | # middle = x[first] 84 | # 85 | # if first >= last: 86 | # return 87 | # 88 | # while font < end: 89 | # while font < end and x[font] <= middle: 90 | # font += 1 91 | # x[end] = x[font] 92 | # 93 | # while font < end and x[end] > middle: 94 | # end -= 1 95 | # x[font] = x[end] 96 | # 97 | # x[font] = middle 98 | # 99 | # kpsort(x, first, font - 1) 100 | # kpsort(x, font + 1, last) 101 | 102 | # 归并排序 103 | # 时间复杂度 O(nlogn) 空间复杂度 O(N) 104 | x = [int(i) for i in input().split(',')] 105 | 106 | def gbsort(x): 107 | length = len(x) 108 | if length <= 1: 109 | return x 110 | mid = length // 2 111 | 112 | left = gbsort(x[:mid]) 113 | right = gbsort(x[mid:]) 114 | 115 | left_point, right_pointer = 0, 0 116 | result = [] 117 | 118 | while left_point < len(left) and right_pointer < len(right): 119 | if left[left_point] <= right[right_pointer]: 120 | result.append(left[left_point]) 121 | left_point += 1 122 | else: 123 | result.append(right_pointer) 124 | right_pointer += 1 125 | 126 | result += left[left_point:] 127 | result += right[right_pointer] 128 | 129 | return result 130 | 131 | print(gbsort(x)) 132 | -------------------------------------------------------------------------------- /机试题/生成指定长度的斐波那契数列.py: -------------------------------------------------------------------------------- 1 | def fibs(x): 2 | result = [0,1] 3 | for index in range(x-2): 4 | result.append(result[-1]+result[-2]) 5 | return result 6 | 7 | num = int(input('Enter a number')) 8 | print(fibs(num)) 9 | 10 | -------------------------------------------------------------------------------- /机试题/链表.py: -------------------------------------------------------------------------------- 1 | class Node(object): 2 | def __init__(self, elem): 3 | self.elem = elem 4 | self.next = None 5 | 6 | class SingleLink(object): 7 | def __init__(self, node=None): 8 | self.__node = node 9 | 10 | def is_empty(self): 11 | return self.__node == None 12 | 13 | def length(self): 14 | cur = self.__node 15 | cout = 0 16 | while cur != None: 17 | cout += 1 18 | cur = cur.next 19 | print(cout) 20 | 21 | def travel(self): 22 | cur = self.__node 23 | while cur != None: 24 | print(cur.elem) 25 | cur = cur.next 26 | 27 | def add(self, item): 28 | node = Node(item) 29 | node.next = self.__node 30 | self.__node = node 31 | 32 | def append(self, item): 33 | node = Node(item) 34 | cur = self.__node 35 | if self.is_empty(): 36 | self.__node = node 37 | else: 38 | while cur.next != None: 39 | cur = cur.next 40 | cur.next = node 41 | 42 | def insert(self, pos, item): 43 | if pos <= 0: 44 | self.add(item) 45 | elif pos > self.length(): 46 | self.append(item) 47 | else: 48 | cur = self.__node 49 | count = 0 50 | while count < (pos-1): 51 | count += 1 52 | cur = cur.next 53 | node = Node(item) 54 | node.next = cur.next 55 | cur.next = node 56 | 57 | def remove(self,item): 58 | cur = self.__node 59 | pre = None 60 | while cur !=None: 61 | if cur.elem == item: 62 | if cur == self.__node: 63 | self.__node = cur.next 64 | else: 65 | pre.next = cur.next 66 | break 67 | else: 68 | pre = cur 69 | cur = cur.next 70 | 71 | def search(self,item): 72 | cur = self.__node 73 | while cur !=None: 74 | if cur.elem == item: 75 | return True 76 | else: 77 | cur = cur.next 78 | return False 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /直通BAT算法题/二叉树/1.py: -------------------------------------------------------------------------------- 1 | # x = input().split() 2 | # y = input().split() 3 | # z = input().split() 4 | # 5 | # res = [] 6 | # for i in x: 7 | # for j in y: 8 | # for k in z: 9 | # n = i.replace(j, k) 10 | # res.append(n) 11 | # 12 | # print(" ".join(res)) 13 | 14 | # res = [] 15 | # x = input() 16 | # for i in range(len(x)-1): 17 | # # print(i) 18 | # if int(x[i]) % 3 == 0 or int(x[i]) == 0: 19 | # res.append(x[i]) 20 | # elif int(x[i] + x[i + 1]) % 3 == 0: 21 | # res.append(x[i] + x[i + 1]) 22 | # print(len(res)) 23 | 24 | # x = input() 25 | # y = input() 26 | # y = set(y) 27 | # y = list(y) 28 | # m = (int(y[0]) * int((x[0] + x[1]))) / int(x[0]) 29 | # print("%.2f" % m) 30 | 31 | x = input() 32 | res1 = [] 33 | m = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 34 | for i in range(len(x)): 35 | if x[i] == 0: 36 | res1.append(i) 37 | for i in res1: 38 | for j in range(len(m)): 39 | if j == i: 40 | m.remove(m[j]) 41 | print(m) -------------------------------------------------------------------------------- /直通BAT算法题/二叉树/二叉树的前中后序的递归,非递归及Morris遍历.py: -------------------------------------------------------------------------------- 1 | class TreeNode(object): 2 | def __init__(self, x): 3 | self.val = x 4 | self.left = None 5 | self.right = None 6 | 7 | # def create_tree(root): 8 | # element = input("Enter a key: ") 9 | # if element == '#': 10 | # root = None 11 | # else: 12 | # root = TreeNode(element) 13 | # print(root) 14 | # root.left = create_tree(root.left) 15 | # print(1) 16 | # root.right = create_tree(root.right) 17 | # print(2) 18 | # return root 19 | # 20 | # print(create_tree([None])) 21 | 22 | class Tree(): 23 | def __init__(self): 24 | self.root = None 25 | 26 | def add(self, item): 27 | node = TreeNode(item) 28 | if self.root == None: 29 | self.root = node 30 | return 31 | queue = [self.root] 32 | 33 | while queue: 34 | cur = queue.pop(0) 35 | if cur.left == None: 36 | cur.left = node 37 | return 38 | else: 39 | queue.append(cur.left) 40 | 41 | if cur.right == None: 42 | cur.right = node 43 | return 44 | else: 45 | queue.append(cur.right) 46 | 47 | # 广度遍历 48 | def breadth_travel(self): 49 | if self.root == None: 50 | return 51 | queue = [self.root] 52 | while queue: 53 | cur = queue.pop(0) 54 | print(cur.val, end='') 55 | if cur.left != None: 56 | queue.append(cur.left) 57 | if cur.right != None: 58 | queue.append(cur.right) 59 | 60 | # 深度遍历 61 | # 先序 62 | def preorder(self, node): 63 | if node == None: 64 | return 65 | print(node.val, end='') 66 | self.preorder(node.left) 67 | self.preorder(node.right) 68 | 69 | # 中序 70 | def middleorder(self, node): 71 | if node == None: 72 | return 73 | self.middleorder(node.left) 74 | print(node.val, end='') 75 | self.middleorder(node.right) 76 | 77 | def postorder(self, node): 78 | if node == None: 79 | return 80 | self.postorder(node.right) 81 | self.postorder(node.left) 82 | print(node.val, end='') 83 | 84 | if __name__ == "__main__": 85 | tree = Tree() 86 | tree.add(0) 87 | tree.add(1) 88 | tree.add(2) 89 | tree.add(3) 90 | tree.add(4) 91 | tree.add(5) 92 | tree.add(6) 93 | tree.add(7) 94 | tree.add(8) 95 | tree.add(9) 96 | tree.breadth_travel() 97 | tree.preorder(tree.root) 98 | tree.middleorder(tree.root) 99 | tree.postorder(tree.root) 100 | -------------------------------------------------------------------------------- /直通BAT算法题/二叉树/二叉树的序列化和反序列化.py: -------------------------------------------------------------------------------- 1 | # 先序 2 | class Tree(): 3 | def __init__(self, val=None): 4 | self.val = val 5 | self.left = None 6 | self.right = None 7 | 8 | def preorder(root): 9 | if not root: 10 | return '#!' 11 | res = root.val + ['!'] 12 | res += preorder(root.left) 13 | res += preorder(root.right) 14 | return res 15 | 16 | tree = Tree([1]) 17 | print(preorder(tree)) 18 | 19 | # 反序列化(先序) 20 | def recoByPreString(prestr): 21 | def reconpreorder(values): 22 | key = values.pop(0) 23 | if key == "#": 24 | return None 25 | root = Tree(key) 26 | root.left = reconpreorder(values) 27 | root.right = reconpreorder(values) 28 | return root 29 | 30 | values = prestr.split('!') 31 | return reconpreorder(values) 32 | -------------------------------------------------------------------------------- /直通BAT算法题/二叉树/二叉树的按层打印.py: -------------------------------------------------------------------------------- 1 | class Tree(): 2 | def __init__(self, val=None): 3 | self.val = val 4 | self.left = None 5 | self.right = None 6 | 7 | def printlayer(root): 8 | last = root 9 | queue = [] 10 | queue.append(root) 11 | while queue: 12 | root = queue.pop(0) 13 | print(root.val, end='') 14 | if root.left: 15 | nlast = root.left 16 | queue.append(root.left) 17 | if root.right: 18 | nlast = root.right 19 | queue.append(root.right) 20 | if root == last and queue: 21 | last = nlast 22 | -------------------------------------------------------------------------------- /直通BAT算法题/二叉树/判断t1树中是否有与t2树拓扑结构完全相同的子树.py: -------------------------------------------------------------------------------- 1 | class Tree(): 2 | def __init__(self, val=None): 3 | self.val = val 4 | self.left = None 5 | self.right = None 6 | 7 | def Top(t1, t2): 8 | def issubTosub(t1, t2): 9 | if not t1 and not t2: 10 | return True 11 | if t1.val != t2.val: 12 | return False 13 | return issubTosub(t1.left, t2.left) and issubTosub(t1.right, t2.right) 14 | 15 | if not t1 or not t2: 16 | return False 17 | return Top(t1, t2) or Top(t1.left, t2) or Top(t1.right, t2) 18 | -------------------------------------------------------------------------------- /直通BAT算法题/栈和队列/两个栈组成一个队列.py: -------------------------------------------------------------------------------- 1 | class TwostackQueue(): 2 | def __init__(self): 3 | self.stackpush = [] 4 | self.stackpop = [] 5 | 6 | def add(self,Newnum): 7 | self.stackpush.append(Newnum) 8 | 9 | def push(self): 10 | while self.stackpush: 11 | self.stackpop.append(self.stackpush.pop()) 12 | return self.stackpop.pop() 13 | 14 | queue = TwostackQueue() 15 | queue.add([1,2,3]) 16 | print(queue.push()) 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /直通BAT算法题/栈和队列/如何仅用递归函数和栈操作逆序一个栈.py: -------------------------------------------------------------------------------- 1 | def recur(stack): 2 | def getandremove(stack): 3 | result = stack.pop() 4 | if len(stack) == 0: 5 | return result 6 | else: 7 | i = getandremove(stack) 8 | stack.append(result) 9 | return i 10 | 11 | if len(stack) == 0: 12 | return 13 | i = getandremove(stack) 14 | recur(stack) 15 | stack.append(i) 16 | return stack 17 | 18 | print(recur([1,2,3,4])) 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /直通BAT算法题/栈和队列/构造数组的MaxTree.py: -------------------------------------------------------------------------------- 1 | # 每一棵树的父节点是他左边第一个比他大的数和他右边第一个比他大的数中较小的那个值 2 | # 如果这个数是整个树中的最大值,那么他就作为整个数的头结点出现 3 | 4 | class Node(): 5 | def __init__(self, value): 6 | self.value = value 7 | self.left = None 8 | self.right = None 9 | 10 | def getMaxtree(self, arr): 11 | narr = [Node(arr[i]) for i in range(len(arr))] 12 | lBigMap = {} 13 | rBigMap = {} 14 | stack = [] 15 | 16 | # 对输入的元素进行判断,输入元素大于栈顶元素,那么栈顶元素弹出直到小于输入元素 17 | for i in range(len(narr)): 18 | curNode = narr[i] 19 | while stack and stack[-1].value < curNode.value: 20 | cur = stack.pop() 21 | lBigMap[cur] = stack[-1] if stack else None 22 | rBigMap[cur] = curNode 23 | stack.append(curNode) 24 | 25 | # 上面的循环条件是两个,但是实际上最后还是会剩下来栈里面的几个元素 26 | while stack: 27 | cur = stack.pop() 28 | lBigMap[cur] = stack[-1] if stack else None 29 | rBigMap[cur] = None 30 | 31 | head = None 32 | for i in range(len(narr)): 33 | curNode = narr[i] 34 | left = lBigMap[curNode] 35 | right = rBigMap[curNode] 36 | if left == None and right == None: 37 | head = curNode 38 | elif left == None: 39 | if right.left == None: 40 | right.left = curNode 41 | else: 42 | right.right = curNode 43 | elif right == None: 44 | if left.left == None: 45 | left.left = curNode 46 | else: 47 | left.right = curNode 48 | else: 49 | parent = left if left.value < right.value else right 50 | if parent.left == None: 51 | parent.left = curNode 52 | else: 53 | parent.right = curNode 54 | return head 55 | 56 | node = Node(None) 57 | print(node.getMaxtree([3, 1, 2])) 58 | -------------------------------------------------------------------------------- /直通BAT算法题/栈和队列/求最大子矩阵的大小.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leeguandong/Interview-code-practice-python/86933f82f3553dfca16055977d7366b106b511bd/直通BAT算法题/栈和队列/求最大子矩阵的大小.py -------------------------------------------------------------------------------- /直通BAT算法题/栈和队列/生成窗口最大值数组.py: -------------------------------------------------------------------------------- 1 | # 双端队列 2 | # 队列存的是数组的下标 3 | 4 | def getwindows(arr, w): 5 | deque = [] 6 | res = [] 7 | 8 | for i in range(len(arr)): 9 | while deque and arr[deque[-1]] <= arr[i]: 10 | deque.pop() 11 | deque.append(i) 12 | if deque[0] <= i - w: 13 | deque.pop(0) 14 | if i - w + 1 >= 0: 15 | res.append(arr[deque[0]]) 16 | return res 17 | 18 | print(getwindows([4, 3, 5, 4, 3, 3, 6, 7], 3)) 19 | -------------------------------------------------------------------------------- /直通BAT算法题/栈和队列/用一个栈实现另一个栈的排序.py: -------------------------------------------------------------------------------- 1 | # class so(): 2 | # def __init__(self): 3 | # self.stack = [] 4 | # self.help = [] 5 | # 6 | # def add(self, Newnum): 7 | # self.stack.append(Newnum) 8 | # 9 | # def sor(self): 10 | # while self.stack: 11 | # num = self.stack.pop() 12 | # if self.help == [] or num > self.help[-1]: 13 | # self.help.append(num) 14 | # else: 15 | # while num < self.help[-1]: 16 | # self.stack.append(self.help.pop()) 17 | # self.help.append(num) 18 | # 19 | # return self.help 20 | 21 | def sor(stack): 22 | help = [] 23 | while stack: 24 | cur = stack.pop() 25 | while len(help) != 0 and help[-1] < cur: 26 | stack.append(help.pop()) 27 | help.append(cur) 28 | 29 | while help: 30 | stack.append(help.pop()) 31 | 32 | return stack 33 | 34 | print(sor([3,2,5,4,1])) 35 | -------------------------------------------------------------------------------- /直通BAT算法题/栈和队列/设计一个有getMin功能的栈.py: -------------------------------------------------------------------------------- 1 | class Newstack(): 2 | def __init__(self): 3 | self.stackData = [] 4 | self.stackMin = [] 5 | 6 | def push(self, newNum): 7 | self.stackData.append(newNum) 8 | if self.stackMin == [] or newNum <= self.getMin(): 9 | self.stackMin.append(newNum) 10 | 11 | def getMin(self): 12 | if len(self.stackMin) == 0: 13 | return [] 14 | return self.stackMin[-1] 15 | 16 | def pop(self): 17 | value = self.stackData.pop() 18 | if self.getMin() == value: 19 | self.stackMin.pop() 20 | return value 21 | 22 | s = Newstack() 23 | print(s.push(1)) 24 | print(s.pop()) 25 | print(s.push(2)) 26 | print(s.push(3)) 27 | print(s.getMin()) 28 | print(s.push(1)) 29 | -------------------------------------------------------------------------------- /直通BAT算法题/链表问题/判断一个链表是否为回文结构.py: -------------------------------------------------------------------------------- 1 | def huiwen(arr): 2 | if arr == None or len(arr) < 2: 3 | return arr 4 | stack = [] 5 | cur = arr 6 | while cur != None: 7 | stack.append(cur.val) 8 | cur = cur.next 9 | while stack: 10 | if stack.pop().val != arr.val: 11 | return False 12 | arr = arr.next 13 | return True 14 | -------------------------------------------------------------------------------- /直通BAT算法题/链表问题/判断一个链表是否有环,如果有的话返回第一个进环的节点.py: -------------------------------------------------------------------------------- 1 | class Node(): 2 | def __init__(self, val=None): 3 | self.val = val 4 | self.next = None 5 | 6 | def getloopmeet(head): 7 | fast = head.next 8 | slow = head.next.next 9 | while fast != slow: 10 | if fast != None or slow != None: 11 | return None 12 | fast = fast.next.next 13 | slow = slow.next 14 | fast = head 15 | while fast != slow: 16 | fast = fast.next 17 | slow = slow.fast 18 | return fast 19 | -------------------------------------------------------------------------------- /直通BAT算法题/链表问题/判断两个无环链表是否相交,相交则返回第一个相交节点.py: -------------------------------------------------------------------------------- 1 | class Node(): 2 | def __init__(self, val=None): 3 | self.val = val 4 | self.next = None 5 | 6 | def Loop(head1, head2): 7 | n1 = 0 8 | n2 = 0 9 | cur1 = head1 10 | cur2 = head2 11 | while cur1 != None: 12 | n1 += 1 13 | cur1 = cur1.next 14 | print(n1) 15 | while cur2 != None: 16 | n2 += 1 17 | cur2 = cur2.next 18 | print(n2) 19 | 20 | n = abs(n1 - n2) 21 | print(n) 22 | cur1 = head1 23 | cur2 = head2 24 | if n1 > n2: 25 | while n > 0: 26 | cur1 = cur1.next 27 | else: 28 | while n > 0: 29 | cur2 = cur2.next 30 | 31 | while cur1 != cur2: 32 | cur1 = cur1.next 33 | cur2 = cur2.next 34 | return cur1 35 | 36 | # node1 = Node([1, 2, 3]) 37 | # node2 = Node([2, 3]) 38 | # print(Loop(node1, node2)) 39 | -------------------------------------------------------------------------------- /直通BAT算法题/链表问题/判断两个有环链表是否相交,相交则返回第一个相交节点.py: -------------------------------------------------------------------------------- 1 | # 在环外面就相交,或者在环上相交(可能在同一个交点上,可能不在同一个交点上) 2 | 3 | def bothLoop(head1, node1, head2, node2): 4 | if head1 == None or head2 == None: 5 | return None 6 | if node1 == node2: 7 | cur1 = head1 8 | cur2 = head2 9 | n = 0 10 | while cur1 != node1: 11 | n += 1 12 | cur1 = cur1.next 13 | while cur2 != node2: 14 | n -= 1 15 | cur2 = cur2.next 16 | if cur1 != cur2: 17 | return None 18 | cur1 = head1 if n >= 0 else head2 19 | cur2 = head1 if cur1 == head2 else head2 20 | n = abs(n) 21 | while n != 0: 22 | n -= 1 23 | cur1 = cur1.next 24 | while cur1 != cur2: 25 | cur1 = cur1.next 26 | cur2 = cur2.next 27 | return cur1 28 | else: 29 | cur1 = node1.next 30 | while cur1 != node1: 31 | if cur1 == node2: 32 | return node1 33 | cur = cur1.next 34 | return None 35 | 36 | def noLoop(head1, head2): 37 | if head1 == None or head2 == None: 38 | return None 39 | cur1 = head1 40 | cur2 = head2 41 | n = 0 42 | while cur1.next != None: 43 | n += 1 44 | cur1 = cur1.next 45 | while cur2.next != None: 46 | n -= 1 47 | cur2 = cur2.next 48 | if cur1 != cur2: 49 | return None 50 | cur1 = head1 if n >= 0 else head2 51 | cur2 = head1 if cur1 == head2 else head2 52 | n = abs(n) 53 | while n != 0: 54 | cur1 = cur1.next 55 | n -= 1 56 | while cur1 != cur2: 57 | cur1 = cur1.next 58 | cur2 = cur2.next 59 | return cur1 60 | 61 | def getLoopNode(head): 62 | if head == None or head.next == None or head.next.next == None: 63 | return None 64 | slow = head.next 65 | fast = head.next.next 66 | while slow != fast: 67 | if fast.next == None or fast.next.next == None: 68 | return None 69 | slow = slow.next 70 | fast = fast.next.next 71 | fast = head 72 | while slow != fast: 73 | slow = slow.next 74 | fast = fast.next 75 | return slow 76 | 77 | class Node: 78 | def __init__(self, val=None): 79 | self.val = val 80 | self.next = None 81 | 82 | def getIntersectNode(head1, head2): 83 | if head1 == None or head2 == None: 84 | return None 85 | # 判断环的入口在哪里 86 | node1 = getLoopNode(head1) 87 | node2 = getLoopNode(head2) 88 | if node1 == None and node2 == None: 89 | return noLoop(head1, head2) 90 | # 在环之前就相等,node1 = node2,在环中相等, 91 | if node1 != None and node2 != None: 92 | return bothLoop(head1, node1, head2, node2) 93 | return None 94 | -------------------------------------------------------------------------------- /直通BAT算法题/链表问题/向有环的环形链表中插入新节点.py: -------------------------------------------------------------------------------- 1 | # 指针给的是节点值 2 | class Node(): 3 | def __init__(self, value=None): 4 | self.value = value 5 | self.next = None 6 | 7 | def insertnum(head, num): 8 | node = Node(num) 9 | if head == None: 10 | node.next = node 11 | return node 12 | node = head 13 | pre = node 14 | cur = node.next 15 | while cur != head: 16 | if pre.value > num and cur.value <= num: 17 | break 18 | pre = pre.next 19 | cur = cur.next 20 | # num 小于节点值,pre只跑到最后一个节点,node跑道头结点 21 | pre.next = node 22 | node.next = cur 23 | # 是按顺序来的,返回的是 head 或者 node ,是有顺序决定的 24 | return head if head.value < num else node 25 | 26 | node = Node() 27 | node.insertnum([[1, 2, 3], 5]) 28 | -------------------------------------------------------------------------------- /直通BAT算法题/链表问题/在单链表中删除指定值的节点.py: -------------------------------------------------------------------------------- 1 | def remove(head, num): 2 | if head == None: 3 | return None 4 | stack = [] 5 | while head != None: 6 | if head.val != num: 7 | stack.append(head) 8 | head = head.next 9 | while stack: 10 | # 这是一个链接操作 11 | stack[-1].next = head 12 | head = stack.pop() 13 | return head 14 | -------------------------------------------------------------------------------- /直通BAT算法题/链表问题/复制含有随机指针节点的链表.py: -------------------------------------------------------------------------------- 1 | class RandNode: 2 | def __init__(self, data): 3 | self.val = data 4 | self.next = None 5 | self.rand = None 6 | 7 | def copyListWithRand(head): 8 | if head == None: 9 | return None 10 | map = {} 11 | cur = head 12 | while cur != None: 13 | map[cur] = RandNode(cur.val) 14 | cur = cur.next 15 | cur = head 16 | while cur != None: 17 | map[cur].next = None if cur.next == None else map[cur.next] 18 | map[cur].next = None if cur.ramd == None else map[cur.rand] 19 | cur = cur.next 20 | return map[head] 21 | -------------------------------------------------------------------------------- /直通BAT算法题/链表问题/将单向链表按某值划分成左边小,中间相等,右边大的形式.py: -------------------------------------------------------------------------------- 1 | # 将所有的节点放置到一个数组中,对这个数组进行partition调整(快排调整过程),再将每个数组中每个节点串起来即可。 2 | # 快排-递归 3 | 4 | def list(head, pivot): 5 | def partition(nodeArr, pivot): 6 | left = - 1 7 | right = len(nodeArr) 8 | index = 0 9 | while index < right: 10 | if nodeArr[index].val < pivot: 11 | left += 1 12 | nodeArr[left], nodeArr[index] = nodeArr[index], nodeArr[left] 13 | index += 1 14 | elif nodeArr[index].val == pivot: 15 | index += 1 16 | else: 17 | right -= 1 18 | nodeArr[index], nodeArr[right] = nodeArr[right], nodeArr[index] 19 | 20 | if head == None or head.next == None: 21 | return head 22 | cur = head 23 | n = 0 24 | while cur != None: 25 | n += 1 26 | cur = cur.next 27 | nodeArr = [] 28 | cur = head 29 | while cur != None: 30 | nodeArr.append(cur) 31 | cur = cur.next 32 | partition(nodeArr, pivot) 33 | for i in range(n - 1): 34 | nodeArr[i].next = nodeArr[i + 1] 35 | nodeArr[-1].next = None 36 | return nodeArr[0] 37 | -------------------------------------------------------------------------------- /直通BAT算法题/链表问题/将单链表的每K个节点之间逆序.py: -------------------------------------------------------------------------------- 1 | # 每隔 k 个就逆序,用栈结构 2 | 3 | def reverseNode(head, k): 4 | def reverse(stack, pre, next): 5 | while stack: 6 | cur = stack.pop() 7 | if pre != None: 8 | cur = cur.next 9 | pre = cur 10 | # pre.next = next 11 | return pre 12 | 13 | if head == None or head.next == None or k < 2: 14 | return head 15 | stack = [] 16 | cur = head 17 | newHaed = head 18 | pre = None 19 | while cur != None: 20 | next = cur.next 21 | stack.append(cur) 22 | if len(stack) == k: 23 | pre = reverse(stack, pre, next) 24 | newHead = cur if newHaed == head else newHaed 25 | cur = next 26 | return newHaed 27 | -------------------------------------------------------------------------------- /直通BAT算法题/链表问题/打印两个有序链表的公共部分.py: -------------------------------------------------------------------------------- 1 | class Node(): 2 | def __init__(self, val=None): 3 | self.val = val 4 | self.next = None 5 | 6 | def compare(head1, head2): 7 | if head1 == None or head2 == None: 8 | return [] 9 | 10 | res = [] 11 | while head1 != None and head2 != None: 12 | if head1.val > head2.val: 13 | head2 = head2.next 14 | elif head1.val < head2.val: 15 | head1 = head1.next 16 | else: 17 | print(head1) 18 | res.append(head1) 19 | head1 = head1.next 20 | head2 = head2.next 21 | return res 22 | 23 | node = Node([1, 3, 4, 7]) 24 | node1 = Node([2, 3, 5, 7, 9]) 25 | print(compare(node, node1)) 26 | -------------------------------------------------------------------------------- /直通BAT算法题/链表问题/节点删除方式.py: -------------------------------------------------------------------------------- 1 | # 链表里删元素,但是不知道元素的头结点和链表本身结构 2 | def dele(node): 3 | if node == None: 4 | return None 5 | next = node.next 6 | if next == None: 7 | return [] 8 | node.val = next.val 9 | node.next = next.next 10 | --------------------------------------------------------------------------------