剑指offer 手刷python 汇总整理版本~
文章目录
- 0.递归&脑力
- 斐波那契数列
- 数值的n次方
- 二分法和牛顿迭代法求平方根
- 丑数
- 正则表达式匹配
- [LeetCode#42. Trapping Rain Water 收集雨水](https://www.cnblogs.com/grandyang/p/4402392.html)
- [LeetCode 84. Largest Rectangle in Histogram 直方图中最大的矩形](https://www.cnblogs.com/grandyang/p/4322653.html)
- leetcode:买卖股票的最佳时机(python)
- 1.数组运算
- 调整数组顺序使奇数位于偶数前面
- 二分查找(九章算法)
- [ 旋转数组的最小数字](https://www.nowcoder.com/practice/9f3231a991af4f55b95579b44b7a01ba?tpId=13&tqId=11159&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking)
- [ LeetCode-旋转数组查找]( https://leetcode-cn.com/problems/search-in-rotated-sorted-array/)
- 和为S的连续正数序列
- 数字在排序数组中出现的次数
- 数组中只出现一次的数字
- 和为S的两个数字
- 第一个只出现一次的字符
- 数组中的逆序对
- 连续子数组的最大和
- 最小的K个数
- 第K大的数
- 数组中出现次数超过一半的数字
- 把数组排成最小的数
- 数组中重复的数字
- 构造乘积数组
- 二维数组中的查找
- 扑克牌顺子
- 孩子们的游戏
- 剪绳子
- 1.1排序算法类
- 快速排序
- 堆排序
- **[归并排序](https://www.jiuzhang.com/solution/merge-sort/#tag-lang-python)**
- 桶排序
- 计数排序
- 2.位运算
- 二进制中1的个数
- 求1+2+3+..+n
- 不用加减乘除做加法
- 从1到n整数中1出现的次数
- 3.字符串
- 翻转单词顺序列
- 左旋转字符串
- 把字符串转换成整数
- 判断一个字符串是否表示数值
- 字符串的排列
- 替换空格
- 字符流中第一个不重复的字符
- 最长回文子串
- 最长公共子串
- [实现 Trie(前缀树) · Implement Trie](https://www.nowcoder.com/questionTerminal/a55a584bc0ca4a83a272680174be113b)
- KMP算法
- 大数乘法
- 4.链表
- 链表中环的入口结点
- 翻转链表
- 链表中倒数第k个结点
- 合并两个排序的链表
- 复杂链表的复制
- 两个链表的第一个公共结点
- 5.二叉树
- 二叉树的镜像(Symmetric Tree)
- [二叉树的先序、中序、后续遍历 递归和非递归](https://www.cnblogs.com/icekx/p/9127569.html)
- 平衡二叉树的判断
- 二叉树的深度
- 二叉树的下一个结点
- 对称的二叉树
- 将二叉树按照层级转化为链表
- 把二叉树打印成多行
- 之字形打印二叉树
- 序列化和反序列化二叉树
- 二叉平衡树中的第k小数
- 重建二叉树
- 二叉搜索树与双向链表
- 判断树B是否是树A的子结构
- 二叉树中和为某一值的路径
- 二叉搜索树的后序遍历序列
- 最近公共祖先
- 6.复杂数据结构
- 顺时针打印矩阵
- 数据流中的中位数
- 滑动窗口的最大值
- 用两个栈实现队列
- 包含min函数的栈
- 栈的压入、弹出序列
- 矩阵中的路径
- 机器人的运动范围
0.递归&脑力
python实现单例模式
#使用python 实现单例模式
#单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。#1.__new__ 是什么
# __new__方法接受的参数虽然也是和__init__一样,但__init__是在类实例创建之后调用,而 __new__方法正是创建这个类实例的方法。
# __new__ 方法必须返回值,__init__方法不需要返回值。class Human(object):def __new__(cls, *agrs, **kwargs):a = object.__new__(cls, *agrs, **kwargs)print('__new__')print(a)return a # __new__ 方法必须返回值,__init__方法不需要返回值。def __init__(self, name='lisi'):print('__init__')print(self)self.name = namedef getName(self):print(self.name)hu = Human() #不能传参数
hu.getName()
#可以发现: __new__方法的调用是发生在__init__之前的
# __new__
# <__main__.Human object at 0x00000000021FF5F8>
# __init__
# <__main__.Human object at 0x00000000021FF5F8>
# lisi# 对于int这种 不可变的对象,我们只有重载它的__new__方法才能起到自定义的作用, 而 __init__ 方法是不起作用的。
class PositiveInteger(int):def __new__(cls, value):return super(PositiveInteger, cls).__new__(cls, abs(value))poi = PositiveInteger(-3)
print(poi) # 3#使用__new__ 实现单例模式
class Singlton(object):_instance = Nonedef __new__(cls, *args, **kwargs):if not cls._instance:cls._instance = super(Singlton, cls).__new__(cls, *args, **kwargs)return cls._instanceclass myClass(Singlton):passa = myClass()
b = myClass()
print(a is b ) #True
print(a == b) #True
print(id(a), id(b)) # 40345672 40345672# 装饰器: 它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,装饰器的返回值也是一个函数/类对象。装饰器的作用就是为已经存在的对象添加额外的功能
#初始的函数
def myFunc(): #需要增加功能的函数print('myFunc call')def deco(func): # 将函数作为参数def wrapper():print('before func') #假设为增加的功能 1func()print('afther func')# 增加的功能2 return wrapper myFunc = deco(myFunc)
myFunc() #直接调用原来的函数
# before func
# myFunc call
# afther func@deco # 语法糖
def myFunc2(): #对函数进行功能扩展print('this is my Function2')
myFunc2() #@ 相当于省略了myFunc2 = deco(myFunc2)#-----对带有参数的函数进行功能扩展-----
def deco2(func):def wrapper(a, b):print('before func ')res = func(a, b)print('afther func')return resreturn wrapper @deco2
def func2(a, b):print('res is %d'%(a+b))return a+b res = func2(2, 5)
print(res)#-----对参数不确定数的函数进行功能扩展-----
def deco3(func):def wrapper(*args, **kwargs):print('before func')res = func(*args, **kwargs)print('afther func ')return res return wrapper @deco3
def func3(a, b, c, d):res = a+b+c+dprint('sum is %d'%(res))return res
func3(1, 2, 3, 4)@deco3
def func4(a, b, c):res = a + b + c print('sum is %d'%(res))return res
func4(1, 2, 3)#-----使用装饰器实现单例模式-----def singleton(cls, *args, **kwargs):instance = {}def getInstance():if cls not in instance:instance[cls] = cls(*args, **kwargs)return instance[cls]return getInstance@singleton
class myClass2(object):a = 1 a = myClass2()
b = myClass2()
print(a is b)
print(a == b)
斐波那契数列
# -*- coding:utf-8 -*-
class Solution:def Fibonacci(self, n):if n == 0:return 0if n==1 or n==2:return 1memories = [1,1]for i in range(n-2):memories.append(memories[-1]+memories[-2])return memories[-1]def fib_loop_for(n):a, b = 0, 1for _ in range(n):a, b = b, a + breturn adef fib_loop_while(n):a, b = 1, 1while n > 0:a, b = b, a + bn -= 1return a
跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
dp[n]=dp[n−1]+dp[n−2]dp[n]=dp[n−1]+dp[n−2]
# -*- coding:utf-8 -*-
class Solution:def jumpFloor(self, number):# write code here'''n = 1 : 1 n = 2 : 1+1 = 2n = 3 : dp[n-2]+dp[n-1]'''if number == 1 or number == 2:return numberdp = [1,2]for i in range(number-2):dp.append(dp[-1]+dp[-2])return dp[-1]123456789101112131415
class Solution:def jumpFloorII(self, number):# write code hereif number == 1 or number == 2:return numberret = sum_ = 3for i in range(number-2):ret = sum_+1sum_+=retreturn ret 12345678910
# -*- coding:utf-8 -*-
class Solution:def rectCover(self, number):# write code hereif number<=2:return numberdp = [1,2]for i in range(number-2):dp.append(dp[-1]+dp[-2])return dp[-1]
数值的n次方
# -*- coding:utf-8 -*-
class Solution:def Power(self, base, exponent):# write code hereif exponent ==0:return 1if exponent ==1:return baseans,pos=1,1if exponent <0:pos=-1exponent = - exponentif exponent %2 ==0: # 偶数ans = self.Power(base,exponent//2)*self.Power(base,exponent//2)else: # 奇数ans = base * self.Power(base,exponent//2)*self.Power(base,exponent//2)return ans if pos==1 else 1.0/ans
二分法和牛顿迭代法求平方根
# https://www.jiuzhang.com/problem/sqrtx-ii/#tag-lang-python
class Solution:"""@param: x: a double@return: the square root of x"""def sqrt(self, x):if x >= 1:start, end = 1, xelse:start, end = x, 1while end - start > 1e-10:mid = (start + end) / 2if mid * mid < x:start = midelse:end = midreturn start##二分法,下面这个不太对,要x>=1 才行
import math
from math import sqrtdef sqrt_binary(num):x=sqrt(num)y=num/2.0low=0.0up=num*1.0count=1while abs(y-x)>0.00000001:print count,ycount+=1 if (y*y>num):up=yy=low+(y-low)/2else:low=yy=up-(up-y)/2return yprint(sqrt_binary(5))
## 牛顿法 二次方
## https://zhuanlan.zhihu.com/p/111598542
def sqrt_newton(num):x=sqrt(num)y=num/2.0count=1while abs(y-x)>0.00000001:print count,ycount+=1y=((y*1.0)+(1.0*num)/y)/2.0000return yprint(sqrt_newton(5))
print(sqrt(5))### 牛顿法 三次方
def cube_newton(num):x=num/3.0y=0count=1while abs(x-y)>0.00000001:print count,xcount+=1y=xx=(2.0/3.0)*x+(num*1.0)/(x*x*3.0)return xprint(cube_newton(27))
丑数
# -*- coding:utf-8 -*-
class Solution:def GetUglyNumber_Solution(self, index):# write code hereif index == 0:return 0# 1作为特殊数直接保存baselist = [1]min2 = min3 = min5 = 0curnum = 1while curnum < index:minnum = min(baselist[min2] * 2, baselist[min3] * 3, baselist[min5] * 5)baselist.append(minnum)# 找到第一个乘以2的结果大于当前最大丑数M的数字,也就是T2while baselist[min2] * 2 <= minnum:min2 += 1# 找到第一个乘以3的结果大于当前最大丑数M的数字,也就是T3while baselist[min3] * 3 <= minnum:min3 += 1# 找到第一个乘以5的结果大于当前最大丑数M的数字,也就是T5while baselist[min5] * 5 <= minnum:min5 += 1curnum += 1return baselist[-1]
正则表达式匹配
# -*- coding:utf-8 -*-
class Solution:# s, pattern都是字符串def __init__(self):self.dic = {}def match(self, s, p):# write code hereif (s,p) in self.dic:return self.dic[(s,p)]if p == '':return s==''if len(p)==1 or p[1]!='*':self.dic[(s[1:],p[1:])] = self.match(s[1:],p[1:])return len(s)>0 and (p[0]=='.' or p[0]==s[0]) and self.dic[(s[1:],p[1:])]while(len(s) and (p[0]=='.' or p[0]==s[0])):self.dic[(s,p[2:])] = self.match(s,p[2:])if self.match(s[:],p[2:]):return Trues = s[1:]self.dic[(s,p[2:])] = self.match(s,p[2:])return self.dic[(s,p[2:])]
LeetCode#42. Trapping Rain Water 收集雨水
Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
Class Solution:def trap_Water(nums):if not nums:return res,mx,n = 0,0,len(nums)dp=[]for i in range(n): # 当前节点左边最大值mxdp[i] = mxmx = max(mx,nums[i])mx=0for i in range(n-1,0,-1):# 当前节点右边最大值mxdp[i] = min(mx,dp[i])mx = max(mx,nums[i])if dp[i] - nums[i] >0:# 如果当前节点小于左边和右边的较小的那个,就可以存储了,res += dp[i] - nums[i]return respublic class Solution {public int trap(int[] height) {int res = 0, mx = 0, n = height.length;int[] dp = new int[n];for (int i = 0; i < n; ++i) {dp[i] = mx;mx = Math.max(mx, height[i]);}mx = 0;for (int i = n - 1; i >= 0; --i) {dp[i] = Math.min(dp[i], mx);mx = Math.max(mx, height[i]);if (dp[i] - height[i] > 0) res += dp[i] - height[i];}return res;}
}
LeetCode 84. Largest Rectangle in Histogram 直方图中最大的矩形
Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3]
.
The largest rectangle is shown in the shaded area, which has area = 10
unit.
For example,
Given height = [2,1,5,6,2,3]
,
return 10
.
//就是遍历数组,每找到一个局部峰值(只要当前的数字大于后面的一个数字,那么当前数字就看作一个局部峰值,跟前面的数字大小无关),然后向前遍历所有的值,算出共同的矩形面积,每次对比保留最大值。
// Pruning optimize
class Solution {public:int largestRectangleArea(vector<int> &height) {int res = 0;for (int i = 0; i < height.size(); ++i) {if (i + 1 < height.size() && height[i] <= height[i + 1]) {continue;}//找到局部峰值int minH = height[i];// 局部峰值往前计算所有的值,得到最大的面积for (int j = i; j >= 0; --j) {minH = min(minH, height[j]);int area = minH * (i - j + 1);res = max(res, area);}}return res;}
};
leetcode:买卖股票的最佳时机(python)
https://www.cnblogs.com/guohai-stronger/p/11837218.html
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
示例 2:
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。
#我们可以设置两个变量,一个变量表示当前的最小价格,一个变量表示当前的最大利润。遍历这个#数组,先更新目前为止的最小价格,然后再将当前的价格减去当前的最小价格(利润),以此为根#据更新最大利润。遍历完数组,返回最大利润即可。
class Solution:def maxProfit(self, prices: List[int]) -> int:minPrice = float("inf")maxProfit = 0if len(prices) == 0:return 0for num in prices:if num < minPrice:minPrice = numif num - minPrice > maxProfit:maxProfit = num - minPricereturn maxProfit#DP如何做??
https://www.cnblogs.com/guohai-stronger/p/11837218.html
1.数组运算
调整数组顺序使奇数位于偶数前面
# -*- coding:utf-8 -*-
class Solution:def reOrderArray(self, array):def isOdd(a):return (a & 1) == 1answer = [i for i in array if isOdd(i)]answer.extend([i for i in array if not isOdd(i)])return answer# -*- coding:utf-8 -*-
class Solution:def reOrderArray(self, array):return sorted(array, key = lambda x: x % 2 == 0)
二分查找(九章算法)
题目:给定一个排好序的证书数组nums,和一个整数target,寻找target在nums中任何一个/第一次出现/最后一次出现的位置,不存在return-1。
思路:基本上看到时间复杂度要求O(logN)基本就是要用二分法,二分法的本质是保留有解的一半。
class Solution:# @param nums: The integer array# @param target: Target number to find# @return the first position of target in nums, position start from 0 def binarySearch(self, nums, target):if not nums:return -1start, end = 0, len(nums) - 1# 用 start + 1 < end 而不是 start < end 的目的是为了避免死循环# 在 first position of target 的情况下不会出现死循环# 但是在 last position of target 的情况下会出现死循环# 样例:nums=[1,1] target = 1# 为了统一模板,我们就都采用 start + 1 < end,就保证不会出现死循环while start + 1 < end:# python 没有 overflow 的问题,直接 // 2 就可以了# java和C++ 最好写成 mid = start + (end - start) / 2# 防止在 start = 2^31 - 1, end = 2^31 - 1 的情况下出现加法 overflowmid = (start + end) // 2# > , =, < 的逻辑先分开写,然后在看看 = 的情况是否能合并到其他分支里if nums[mid] < target:# 写作 start = mid + 1 也是正确的# 只是可以偷懒不写,因为不写也没问题,不会影响时间复杂度# 不写的好处是,万一你不小心写成了 mid - 1 你就错了start = midelif nums[mid] == target:end = midelse: # 写作 end = mid - 1 也是正确的# 只是可以偷懒不写,因为不写也没问题,不会影响时间复杂度# 不写的好处是,万一你不小心写成了 mid + 1 你就错了end = mid# 因为上面的循环退出条件是 start + 1 < end# 因此这里循环结束的时候,start 和 end 的关系是相邻关系(1和2,3和4这种)# 因此需要再单独判断 start 和 end 这两个数谁是我们要的答案# 如果是找 first position of target 就先看 start,否则就先看 endif nums[start] == target:return startif nums[end] == target:return endreturn -1
class Solution:"""@param nums: the array of integers@param target: @return: the starting and ending position"""def searchRange(self, nums, target):# Write your code here.if not nums:return [-1, -1]first_index = self.binarySearch(nums, target, True)if first_index == -1:return [-1, -1]last_index = self.binarySearch(nums, target, False)return [first_index, last_index]def binarySearch(self, nums, target, isFindFirst):start, end = 0, len(nums) - 1 while start + 1 < end:mid = (start + end) // 2 if target > nums[mid]:start = midelif target < nums[mid]:end = midelse:if isFindFirst:end = midelse:start = midif isFindFirst:if nums[start] == target:return start if nums[end] == target:return end return -1else:if nums[end] == target:return endif nums[start] == target:return startreturn -1
旋转数组的最小数字
# -*- coding:utf-8 -*-
class Solution:def minNumberInRotateArray(self, rotateArray):# write code hereif rotateArray == []:return 0_len = len(rotateArray)left = 0right = _len - 1while left <= right:mid = int((left + right) >> 1)if rotateArray[mid]<rotateArray[mid-1]:return rotateArray[mid]if rotateArray[mid] >= rotateArray[right]:# 说明在【mid,right】之间left = mid + 1else:# 说明在【left,mid】之间right = mid - 1return rotateArray[mid]# -*- coding:utf-8 -*-
class Solution:def minNumberInRotateArray(self, nums):# write code hereif not nums:return -1start, end = 0, len(nums) - 1while start + 1 < end:mid = (start + end) // 2if nums[mid] > nums[end]:start = midelse:end = midreturn min(nums[start], nums[end])
LeetCode-旋转数组查找
https://www.cnblogs.com/flix/p/12788975.html
Copy输入: nums = [4,5,6,7,0,1,2], target = 0
输出: 4输入: nums = [4,5,6,7,0,1,2], target = 3
输出: -1
- 计算mid=(left+right)/2或者mid=left+(right-left)/2,两种方法的结果是一样的,后一种可以防止溢出;
- 如果nums[mid]==target,则说明找到了target,返回mid即可;
- 如果nums[left]<=nums[mid],则说明左侧区间[left, mid]范围内的数组是单调递增的:
- 如果nums[left]<=target<nums[mid],则说明target则[left, mid-1]之间,将right更新为mid-1;(这里用的是target<nums[mid]不是target<=nums[mid],因为nums[mid]肯定不等于target,等于的话就直接返回了)
- 否则,说明target在[mid+1, right]之间,将left更新为mid+1;
- 否则,则说明右侧区间[mid, right]是单调递增的:
- 如果nums[mid]<target<=nums[right],则说明target在[mid+1, right]之间,则将left更新为mid+1;
- 否则,说明target在[left, mid-1]之间,将right更新为mid-1.
class Solution {public:int search(vector<int>& nums, int target) {int left = 0;int right = nums.size()-1;while(left<=right){int mid = left+(right-left)/2;if(nums[mid]==target) return mid;else if(nums[mid]>=nums[left]){ // mid 在左边,注意是 >=,不是 >if(nums[left]<=target && target<nums[mid]) right = mid-1;else left = mid+1;}else if(nums[mid]<nums[left]){ // mid 在右边if(nums[mid]<target && target<=nums[right]) left = mid+1;else right = mid-1;}}return -1;}
};
和为S的连续正数序列
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
思考:
S%奇数0 或者S%偶数偶数/2 就说明有这个连续序列,但是注意是正数序列,可能会出现越界情况
####滑动窗口法 https://blog.csdn.net/gui951753/article/details/92416352
# -*- coding:utf-8 -*-
class Solution:def FindContinuousSequence(self, tsum):"""使用滑动窗口的方法来解决,设定一个动态的窗口,p_low指向窗口头部,p_high指向窗口尾部,窗口之间的值,为目标值。如果目标值为tsum,那就是其中一个解。否则移动窗口。:param tsum:"""#错误判断处理,如果小于3的话 无解if tsum < 3:return []#设定初始的滑动窗口大小p_low = 1p_high = 2ans = []while p_low < p_high:#计算滑动窗口现在圈中的大小cur_sum = sum(range(p_low,p_high+1))if cur_sum == tsum:#找到一组解,并记录到ans数组中。ans.append(range(p_low,p_high+1))#移动滑动窗口,并寻找下一组解。p_high = p_high + 1elif cur_sum < tsum:p_high = p_high + 1else :p_low = p_low + 1return ansif __name__ == '__main__':s = Solution()print s.FindContinuousSequence(100)
######3
class Solution:def FindContinuousSequence(self, tsum):# write code herek = 2ret = []for k in range(2,tsum):if k%2==1 and tsum%k==0:tmp = []mid = tsum/kif mid-k/2>0:for i in range(mid-k/2,mid+k/2+1):tmp.append(i)ret.append(tmp[:])elif k%2==0 and (tsum%k)*2==k:mid = tsum/ktmp = []if mid-k/2+1>0:for i in range(mid-k/2+1,mid+k/2+1):tmp.append(i)ret.append(tmp[:])ret.sort()return ret
数字在排序数组中出现的次数
数字在排序数组中出现的次数
思考:原来是可以用hash做的,但是因为是排序数组,所以可以用二分查找
# -*- coding:utf-8 -*-
class Solution:def GetNumberOfK(self, data, k):# write code herestart = 0end = len(data)-1while(start<=end):mid = (start+end)/2if data[mid]==k:cnt = 0tmp = midwhile(tmp>=0 and data[tmp]==k):cnt+=1tmp-=1tmp = mid+1while(tmp<len(data) and data[tmp]==k):cnt+=1tmp+=1return cntelif data[mid]>k:end = mid-1else:start = mid+1return 0
数组中只出现一次的数字
class Solution:# 返回[a,b] 其中ab是出现一次的两个数字def FindNumsAppearOnce(self, array):# write code hereans,a1,a2,flag= 0,0,0,1for num in array:ans = ans ^ numwhile(ans):if ans%2 == 0:ans = ans >>1 flag = flag <<1else:breakfor num in array:if num & flag:a1 = a1 ^ numelse:a2 = a2 ^ numreturn a1,a2
和为S的两个数字
输入一个递增排序的数组和一个数字S,在数组中查找两个数,是的他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
hash
# -*- coding:utf-8 -*-
class Solution:def FindNumbersWithSum(self, array, tsum):# write code herememorys= {}ret = []for num in array:if tsum-num in memorys:if ret == []:ret = [tsum-num,num]elif ret and ret[0]*ret[1]>(tsum-num)*num:ret = [tsum-num,num]else:memorys[num] = 1return ret
第一个只出现一次的字符
# -*- coding:utf-8 -*-
class Solution:def FirstNotRepeatingChar(self, s):# write code hereif s=='':return -1ret = [0,-1]chars = {}for i,c in enumerate(s):if c in chars:chars[c][0] = chars[c][0] +1else:chars[c] =[1,i]for k,v in chars.items():if v[0] ==1:if ret[1] ==-1:ret = velif v[1] <= ret[1]:ret = vreturn ret[1]
数组中的逆序对
import bisect
class Solution:def InversePairs(self, data):data.reverse()L = []ret = 0for d in data:pos = bisect.bisect_left(L,d)L.insert(pos,d)ret+= posret = ret % 1000000007return ret % 1000000007def InversePairs(self, data):sortData = sorted(data)count = 0for i in sortData:pos = data.index(i)count += posdata.pop(pos)return count
连续子数组的最大和
可以用动态规划的思想来分析这个问题。如果用函数f(i)表示以第i个数字结尾的子数组的最大和,那么我们需要求出max[f(i)],其中0 <= i < n。我们可用如下边归公式求f(i):
class Solution:def FindGreatestSumOfSubArray(self, array):# write code hereif len(array)==1:return array[0]cur = pos = array[0]for i in range(1,len(array)):pos = max(pos+array[i],array[i])cur = max(cur,pos)return cur
#返回下标
class Solution:def get_max(self,nums):if not nums:return if len(nums)==1:return nums[0],0,1cur=[nums[0],0,1]pos=[nums[0],0,1]for i in range(1,len(nums)):if pos[0]+nums[i] > nums[i]:pos[0] = pos[0]+nums[i]pos[2] = ielse:pos = [nums[i],i,i+1]if cur[0] < pos:cur = posreturn cur[0],cur[1],cur[2]
####返回下标
class Solution:"""@param: A: An integer array@return: A list of integers includes the index of the first number and the index of the last number"""def continuousSubarraySum(self, A):n = len(A)# max_sum维护全局最大连续子数组和# sum维护当前最大连续子数组和,即当前元素必选的最大和max_sum, sum = A[0], 0# first, last表示全局最大连续子数组的左右端点# bg表示当前连续子数组的左端点first = last = 0bg = 0;for i in range(n):if sum >= 0:sum += A[i]else:bg = isum = A[i]if max_sum < sum:max_sum = sumfirst = bglast = ireturn [first,last]
最小的K个数
import heapq
class Solution:def GetLeastNumbers_Solution(self, tinput, k):# write code hereheaps = []ret = []for num in tinput:heapq.heappush(heaps,num)if k>len(heaps):return []for i in range(k):ret.append(heapq.heappop(heaps))return ret
第K大的数
class Solution:# @param k & A a integer and an array# @return ans a integerdef kthLargestElement(self, k, A):if not A or k < 1 or k > len(A):return Nonereturn self.partition(A, 0, len(A) - 1, len(A) - k)def partition(self, nums, start, end, k):"""During the process, it's guaranteed start <= k <= end"""if start == end:return nums[k]left, right = start, endpivot = nums[(start + end) // 2]while left <= right:while left <= right and nums[left] < pivot:left += 1while left <= right and nums[right] > pivot:right -= 1if left <= right:nums[left], nums[right] = nums[right], nums[left]left, right = left + 1, right - 1# left is not bigger than rightif k <= right:return self.partition(nums, start, right, k)if k >= left:return self.partition(nums, left, end, k)return nums[k]
数组中出现次数超过一半的数字
# -*- coding:utf-8 -*-
class Solution:def MoreThanHalfNum_Solution(self, numbers):# write code hereif numbers == []:return 0val,cnt = None,0for num in numbers:if cnt==0:val,cnt = num,1elif val == num:cnt+=1else:cnt-=1return val if numbers.count(val)*2>len(numbers) else 0
把数组排成最小的数
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
str 化
链接:https://www.nowcoder.com/questionTerminal/8fecd3f8ba334add803bf2a06af1b993
来源:牛客网
# -*- coding:utf-8 -*-
class Solution:def PrintMinNumber(self, numbers):# write code hereif not numbers:return ""numbers = list(map(str,numbers))numbers.sort(cmp=lambda x,y:cmp(x+y,y+x))return '0' if numbers[0]=='0' else ''.join(numbers)
数组中重复的数字
如果数组中有重复的数字,函数返回true,否则返回false。
如果数组中有重复的数字,把重复的数字放到参数duplication[0]中。(ps:duplication已经初始化,可以直接赋值使用。)
# -*- coding:utf-8 -*-
class Solution:# 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]# 函数返回True/Falsedef duplicate(self, numbers, duplication):# write code heredup = dict()for num in numbers:if num not in dup:dup[num] = Trueelse:duplication[0]=numreturn True
构造乘积数组
B[i]=A[0]A[1]…A[i-1]*A[i+1]…*A[n-1]
思考:分为下三角和上三角DP计算B
下三角
上三角(从最后往前)
class Solution:def multiply(self, A):# write code heresize = len(A)B = [1]*sizefor i in range(1,size):B[i] = B[i-1]*A[i-1]tmp = 1for i in range(size-2,-1,-1):tmp = tmp*A[i+1]B[i] = B[i]*tmpreturn B
二维数组中的查找
# -*- coding:utf-8 -*-
class Solution:# array 二维列表def Find(self, target, array):# write code hereif len(array)==0 or len(array[0])==0:return Falsei = 0j = len(array[0])-1while(i<len(array) and j>=0):if array[i][j]==target:return Trueelif array[i][j]>target:j-=1else:i+=1return False
扑克牌顺子
class Solution:def IsContinuous(self, numbers):# write code hereif not numbers:return 0numbers.sort()zeros = numbers.count(0)for i, v in enumerate(numbers[:-1]):if v!=0:if numbers[i+1]==v:return Falsezeros -= (numbers[i+1]-numbers[i]-1)if zeros<0:return Falsereturn True
孩子们的游戏
为了讨论方便,先把问题稍微改变一下,并不影响原意:
我们知道第一个人(编号一定是(m-1)) 出列之后,剩下的n-1个人组成了一个新的约瑟夫环(以编号为k=m mod n的人开始):
k, k+1, k+2, … n-2,n-1,0,1,2,… k-2
并且从k开始报0。
我们把他们的编号做一下转换:
k --> 0
k+1 --> 1
k+2 --> 2
...
...
k-2 --> n-2
变换后就完完全全成为了(n-1)个人报数的子问题,假如我们知道这个子问题的解:例如x是最终的胜利者,那么根据上面这个表把这个x变回去不刚好就是n个人情况的解吗?!!变回去的公式很简单,相信大家都可以推出来:x’=(x+k) mod n
如何知道(n-1)个人报数的问题的解?对,只要知道(n-2)个人的解就行了。(n-2)个人的解呢?当然是先求(n-3)的情况 —- 这显然就是一个倒推问题!好了,思路出来了,下面写递推公式:
令f表示i个人玩游戏报m退出最后胜利者的编号,最后的结果自然是f[n]
递推公式
让f[i]为i个人玩游戏报m退出最后的胜利者的编号,最后的结果自然是f[n]
f[1] = 0;
f[i] = (f[i - 1] + m) mod i;
有了这个公式,我们要做的就是从1-n顺序算出f的数值,最后结果是f[n]。
# 正经思路
# -*- coding:utf-8 -*-
class Solution:def LastRemaining_Solution(self, n, m):# write code hereif n<1: return -1final,start = -1,0cnt = [i for i in range(n)]while cnt:k = (start+m-1)%nfinal = cnt.pop(k)n-=1start = kreturn final # 数学思路
class Solution{def LastRemaining_Solution(self,n,m):if n <1 : return -1ans=0;for i in range(1,n+1):ans = (ans + m) %ireturn ans
}
#include<cstdio>
int main(){int n,m;while(scanf("%d %d",&n,&m)==2&&n&&m){int ans = 0;for(int i = 1;i <= n;++i){ans = (ans + m) % i;}printf("总人数:%d 每次出列的人喊的号数:%d 最后一个出列的人的序号:%d\n",n,m,ans+1);}return 0;
}
剪绳子
class Solution():def maxProfuctAfterCutting(self,length):if length < 2:return 0if length == 2:return 1if length == 3:return 2products = [0,1,2,3]for i in range(4,length+1):max = 0for j in range(1,i//2+1):# 思路:每次求解值时将其他小于需要求解的长度是都列出来放在一个数组里# 如:求长度为5,最优解数组里必须得有长度为1,2,3,4的最优解值# 注:此处使用列表保存最优解数组是为了性能优化,虽然递归求解也能解出,但会造成大量重复执行temp = products[j] * products[i-j]if temp>max:max = tempproducts.append(max)return products[length]
1.1排序算法类
快速排序
class Solution:# @param {int[]} A an integer array# @return nothingdef sortIntegers2(self, A):# Write your code hereself.quickSort(A, 0, len(A) - 1)def quickSort(self, A, start, end):if start >= end:returnleft, right = start, end# key point 1: pivot is the value, not the indexpivot = A[(start + end) // 2]# key point 2: every time you compare left & right, it should be # left <= right not left < rightwhile left <= right:while left <= right and A[left] < pivot:left += 1while left <= right and A[right] > pivot:right -= 1if left <= right:A[left], A[right] = A[right], A[left]left += 1right -= 1self.quickSort(A, start, right)self.quickSort(A, left, end)####方法2
https://www.cnblogs.com/pungchur/p/12103465.htmlimport random
def quick_sort(li, left, right):if left < right: # 待排序的区域至少有两个元素mid = partition(li, left, right)quick_sort(li, left, mid - 1)quick_sort(li, mid + 1, right)# partition分区
def partition(li, left, right):tmp = li[left]while left < right:while left < right and li[right] >= tmp:right -= 1li[left] = li[right]while left < right and li[left] <= tmp:left += 1li[right] = li[left]li[left] = tmpreturn leftli = list(range(100))
random.shuffle(li)quick_sort(li, 0, len(li) - 1)
print(li)
堆排序
https://www.cnblogs.com/pungchur/p/12103465.htmlimport random
def sift(li, low, high):# li表示树, low表示树根, high表示树最后一个节点的位置tmp = li[low]i = lowj = 2 * i + 1 # 初识j指向空位的左孩子# i指向空位,j指向两个孩子while j <= high: # 循环退出的第二种情况: j>high,说明空位i是叶子节点if j + 1 <= high and li[j] < li[j + 1]: # 如果右孩子存在并且比左孩子大,指向右孩子j += 1if li[j] > tmp:li[i] = li[j]i = jj = 2 * i + 1else: # 循环退出的第一种情况:j位置的值比tmp小,说明两个孩子都比tmp小breakli[i] = tmpdef heap_sort(li):n = len(li)# 1. 构造堆for low in range(n // 2 - 1, -1, -1):sift(li, low, n - 1)# 2. 挨个出数for high in range(n - 1, -1, -1):li[0], li[high] = li[high], li[0] # 退出 棋子sift(li, 0, high - 1)li = list(range(100))
random.shuffle(li)
heap_sort(li)
print(li)
归并排序
https://www.jiuzhang.com/solution/merge-sort/#tag-lang-python
class Solution:# @param {int[]} A an integer array# @return nothingdef sortIntegers2(self, A):# Write your code heretemp = [0 for _ in range(len(A))]self.merge_sort(0, len(A) - 1, A, temp)def merge_sort(self, start, end, A, temp):if start >= end:returnmid = (start + end) // 2self.merge_sort(start, mid , A, temp)self.merge_sort(mid + 1, end, A, temp)self.merge(start, mid, end, A, temp)def merge(self, start, mid, end, A, temp):left, right = start, mid + 1index = startwhile left <= mid and right <= end:if A[left] < A[right]:temp[index] = A[left]left += 1else:temp[index] = A[right];right += 1index += 1while left <= mid:temp[index] = A[left]left += 1index += 1while right <= end:temp[index] = A[right]right += 1index += 1for index in range(start, end + 1):A[index] = temp[index]
桶排序
计数排序
2.位运算
二进制中1的个数
思考:python没有无符号移动,需要处理下;python的int是不会溢出的,达到界限后会自己转为long,所以很麻烦。
# -*- coding:utf-8 -*-
class Solution:def NumberOf1(self, n):# write code hereans = 0if n<0:n = n & 0xffffffffwhile n:ans += n & 1n >>= 1return ans
求1+2+3+…+n
# -*- coding:utf-8 -*-
class Solution:
# def Sum_Solution(self, n):
# # write code here
# if n ==1:
# return n
# else:
# return n+self.Sum_Solution(n-1)def Sum_Solution(self, n):# write code hereif n == 1:return nreturn n*(n+1)/2
不用加减乘除做加法
思考:不计进位的和为 a^b,进位就是 a&b;python是用的补码来存的,不过python补码有一些问题;
https://blog.csdn.net/qq_16949707/article/details/106399430
# -*- coding:utf-8 -*-
class Solution:def Add(self, num1, num2):xorNum = num1 ^ num2andNum = num1 & num2 << 1while andNum:tmp1 = xorNum ^ andNumtmp2 = (xorNum & andNum) << 1tmp1 = tmp1 & 0xFFFFFFFFxorNum = tmp1andNum = tmp2return xorNum if xorNum <= 0x7FFFFFFF else ~(-1 & xorNum ^ 0xffffffff)
从1到n整数中1出现的次数
设N = abcde ,其中abcde分别为十进制中各位上的数字。
如果要计算百位上1出现的次数,它要受到3方面的影响:百位上的数字,百位以下(低位)的数字,百位以上(高位)的数字。
① 如果百位上数字为0,百位上可能出现1的次数由更高位决定。比如:12013,则可以知道百位出现1的情况可能是:100199,11001199,21002199,,…,1110011199,一共1200个。可以看出是由更高位数字(12)决定,并且等于更高位数字(12)乘以 当前位数(100)。
② 如果百位上数字为1,百位上可能出现1的次数不仅受更高位影响还受低位影响。比如:12113,则可以知道百位受高位影响出现的情况是:100199,11001199,21002199,,…,1110011199,一共1200个。和上面情况一样,并且等于更高位数字(12)乘以 当前位数(100)。但同时它还受低位影响,百位出现1的情况是:12100~12113,一共114个,等于低位数字(113)+1。
③ 如果百位上数字大于1(29),则百位上出现1的情况仅由更高位决定,比如12213,则百位出现1的情况是:100199,11001199,21002199,…,1110011199,1210012199,一共有1300个,并且等于更高位数字+1(12+1)乘以当前位数(100)。
——参考牛客网@藍裙子的百合魂
# -*- coding:utf-8 -*-
class Solution:def NumberOf1Between1AndN_Solution(self, n):# write code hereif n<1: return 0if n==1: return 1last,ans,pos = 0,0,1 # pos来记录位,ans来记录当前1的个数,last来记录前面的数(右边的数)while(n):num = n%10n = n/10ans += pos*nif num>1:ans+=poselif num==1:ans+=(last+1)last = last+num*pospos*=10return ans
3.字符串
翻转单词顺序列
# -*- coding:utf-8 -*-
class Solution:def ReverseSentence(self, s):# write code hereret = s.split(" ")ret.reverse()return ' '.join(ret)
左旋转字符串
对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。
思考:需要先K= K%len(S)
# -*- coding:utf-8 -*-
class Solution:def LeftRotateString(self, s, n):# write code hereif s == '':return sn = n%len(s)return s[n:]+s[0:n]
把字符串转换成整数
将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为0或者字符串不是一个合法的数值则返回0
思考:如果有正负号,需要在数字之前,出现其他字符或者字符串为空都非法返回0
class Solution:def StrToInt(self, s):# write code hereflag = True # 是否出现过 + - 符号pos = 1 # 正负号ret = None # 返回值if s=='':return 0for i in s:if i=='+' or i=='-':if flag:pos = -1 if i=='-' else 1flag = Falseelse:return 0elif i>='0' and i<='9':flag = Falseif ret == None:ret = int(i)else:ret = ret*10+int(i)else:return 0return pos*ret if ret else 0
判断一个字符串是否表示数值
# -*- coding:utf-8 -*-
class Solution:# s字符串def isNumeric(self, s):# write code hereINVALID=0; SPACE=1; SIGN=2; DIGIT=3; DOT=4; EXPONENT=5;#0invalid,1space,2sign,3digit,4dot,5exponent,6num_inputstransitionTable=[[-1, 0, 3, 1, 2, -1], #0 no input or just spaces [-1, 8, -1, 1, 4, 5], #1 input is digits [-1, -1, -1, 4, -1, -1], #2 no digits in front just Dot [-1, -1, -1, 1, 2, -1], #3 sign [-1, 8, -1, 4, -1, 5], #4 digits and dot in front [-1, -1, 6, 7, -1, -1], #5 input 'e' or 'E' [-1, -1, -1, 7, -1, -1], #6 after 'e' input sign [-1, 8, -1, 7, -1, -1], #7 after 'e' input digits [-1, 8, -1, -1, -1, -1]] #8 after valid input input spacestate=0; i=0while i<len(s):inputtype = INVALIDif s[i]==' ': inputtype=SPACEelif s[i]=='-' or s[i]=='+': inputtype=SIGNelif s[i] in '0123456789': inputtype=DIGITelif s[i]=='.': inputtype=DOTelif s[i]=='e' or s[i]=='E': inputtype=EXPONENTstate=transitionTable[state][inputtype]if state==-1: return Falseelse: i+=1return state == 1 or state == 4 or state == 7 or state == 8
字符串的排列
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则按字典序打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
#https://www.jiuzhang.com/problem/permutations/#tag-lang-python
class Solution:"""@param: nums: A list of integers.@return: A list of permutations."""def permute(self, nums):if not nums:return [[]]permutations = []self.dfs(nums, [], set(), permutations)return permutationsdef dfs(self, nums, permutation, visited, permutations):if len(nums) == len(permutation):permutations.append(list(permutation))returnfor num in nums:if num in visited:continuepermutation.append(num)visited.add(num)self.dfs(nums, permutation, visited, permutations)visited.remove(num)permutation.pop()# subsets
# https://www.jiuzhang.com/problem/subsets/#tag-lang-python
class Solution:"""@param nums: A set of numbers@return: A list of lists"""def subsets(self, nums):res = []# 排序nums.sort()# dfs搜索self.dfs(nums, 0, [], res)return resdef dfs(self, nums, k, subset, res):# 当前组合存入resres.append(subset[:])# 为subset新增一位元素for i in range(k, len(nums)):subset.append(nums[i])# 下一层搜索self.dfs(nums, i + 1, subset, res)# 回溯del subset[-1]
替换空格
# -*- coding:utf-8 -*-
import re
class Solution:# s 源字符串def replaceSpace(self, s):# write code herereturn re.sub(" ","%20",s)
字符流中第一个不重复的字符
# -*- coding:utf-8 -*-
class Solution:# 返回对应chardef __init__(self):self.memory = dict() ## 次数self.queue = [] ## 第几个def FirstAppearingOnce(self):# write code herewhile len(self.queue) and self.memory[self.queue[0]]>1:self.queue.pop(0)return self.queue[0] if len(self.queue) else '#'def Insert(self, char):# write code hereif char not in self.memory:self.memory[char]=0self.memory[char]+=1if self.memory[char]==1:self.queue.append(char)
最长回文子串
对于一个字符串,请设计一个高效算法,计算其中最长回文子串的长度。
# https://www.jiuzhang.com/problem/longest-palindromic-substring/#tag-lang-python
# 方法一
class Solution:"""@param s: input string@return: the longest palindromic substring"""def longestPalindrome(self, s):length = len(s)max_len, result = 0, ""for start in range(length):for end in range(start, length):new_len = end - start + 1# 小优化if new_len <= max_len:continueif self.is_palindrome(s[start : end + 1]):max_len = new_lenresult = s[start : end + 1]return result# 判断是否回文def is_palindrome(self, s):length = len(s)for i in range(length // 2):if s[i] != s[length - i - 1]:return Falsereturn True### 方法二
class Solution:"""@param s: input string@return: the longest palindromic substring"""def longestPalindrome(self, s):if not s:return ""n = len(s)is_palindrome = [[False] * n for _ in range(n)]for i in range(n):is_palindrome[i][i] = Truefor i in range(1, n):is_palindrome[i][i - 1] = Truelongest, start, end = 1, 0, 0for length in range(1, n):for i in range(n - length):j = i + lengthis_palindrome[i][j] = s[i] == s[j] and is_palindrome[i + 1][j - 1]if is_palindrome[i][j] and length + 1 > longest:longest = length + 1start, end = i, jreturn s[start:end + 1]# 比较好的DP
https://www.jianshu.com/p/a7741619dd58public String longestPalindrome(String s) {if (s.isEmpty()) {return s;}int n = s.length();boolean[][] dp = new boolean[n][n];int left = 0;int right = 0;for (int i = n - 2; i >= 0; i--) {dp[i][i] = true;for (int j = i + 1; j < n; j++) {dp[i][j] = s.charAt(i) == s.charAt(j) &&( j-i<3||dp[i+1][j-1]);//小于3是因为aba一定是回文if(dp[i][j]&&right-left<j-i){left=i;right=j;}}}return s.substring(left,right+1);}
最长公共子串
问题:有两个字符串str和str2,求出两个字符串中最长公共子串长度。
比如:str=acbcbcef,str2=abcbced,则str和str2的最长公共子串为bcbce,最长公共子串长度为5。
2、比较二维矩阵中每个点对应行列字符中否相等,相等的话值设置为1,否则设置为0。
从上图可以看到,str1和str2共有5个公共子串,但最长的公共子串长度为5。
# https://www.jiuzhang.com/problem/longest-common-substring/
# 滚动数组
# https://blog.csdn.net/qq_25800311/article/details/81607168
# 连续的公共字符串
class Solution:"""@param A: A string@param B: A string@return: the length of the longest common substring."""def longestCommonSubstring(self, A, B):# write your code herem, n = len(A), len(B)dp = [ [ 0 for _ in range(n+1) ] for _ in range(2) ]maxLen = 0for i in range(1, m+1):for j in range(1, n+1):if A[i-1] == B[j-1]:dp[i%2][j] = dp[(i-1)%2][j-1] + 1maxLen = max(maxLen, dp[i%2][j])else:dp[i%2][j] = 0return maxLen### 最长公共子序列
### 不连续的公共字符串
# https://blog.csdn.net/littlethunder/article/details/25637173
def lcs(a,b):lena=len(a)lenb=len(b)c=[[0 for i in range(lenb+1)] for j in range(lena+1)]flag=[[0 for i in range(lenb+1)] for j in range(lena+1)]for i in range(lena):for j in range(lenb):if a[i]==b[j]:c[i+1][j+1]=c[i][j]+1flag[i+1][j+1]='ok'elif c[i+1][j]>c[i][j+1]:c[i+1][j+1]=c[i+1][j]flag[i+1][j+1]='left'else:c[i+1][j+1]=c[i][j+1]flag[i+1][j+1]='up'return c,flagdef printLcs(flag,a,i,j):if i==0 or j==0:returnif flag[i][j]=='ok':printLcs(flag,a,i-1,j-1)print(a[i-1],end='')elif flag[i][j]=='left':printLcs(flag,a,i,j-1)else:printLcs(flag,a,i-1,j)a='ABCBDAB'
b='BDCABA'
c,flag=lcs(a,b)
for i in c:print(i)
print('')
for j in flag:print(j)
print('')
printLcs(flag,a,len(a),len(b))
实现 Trie(前缀树) · Implement Trie
- 题目要求实现一个Trie,包含插入、查找和查找前缀三个方法。
- Trie树也称字典树,因为其效率很高,所以在在字符串查找、前缀匹配等中应用很广泛,其高效率是以空间为代价的。
- 原理:利用串构建一个字典树,这个字典树保存了串的公共前缀信息,因此可以降低查询操作的复杂度。
- 定义结点Node里包含一个isWord(表示这个结点是否是一个单词的结尾)和一个大小为26的next。
我们从root开始,依次往下查找a,p,p,l,e:如果在结点n的下一个字母里没有找到我们想要的字母ch,我们就增加新结点到结点n的next[],式子next[ch-‘a’]=new Node()。
查找一个前缀和查找一个单词的区别就是,当我们想要查找的前缀找到最后一位,不需要判断是否是完整的单词,直接返回True即可。如果不能全部找到则返回False。
- 空间复杂度:字典树每个节点都需要用一个大小为26的数组来存储子节点的指针,所以空间复杂度较高。
- 时间复杂度:假设所有插入字符串长度之和为n,构建字典树的时间复杂度为O(n);假设要查找的所有字符串长度之和为k,查找的时间复杂度为O(k)。因此时间复杂度为O(n+k)
# https://www.jiuzhang.com/problem/implement-trie/#tag-lang-python
class TrieNode:def __init__(self):self.children = {}self.is_word = Falseclass Trie:def __init__(self):self.root = TrieNode()"""@param: word: a word@return: nothing"""def insert(self, word):node = self.rootfor c in word:if c not in node.children:node.children[c] = TrieNode()node = node.children[c]node.is_word = True"""return the node in the trie if exists """def find(self, word):node = self.rootfor c in word:node = node.children.get(c)if node is None:return Nonereturn node"""@param: word: A string@return: if the word is in the trie."""def search(self, word):node = self.find(word)return node is not None and node.is_word"""@param: prefix: A string@return: if there is any word in the trie that starts with the given prefix."""def startsWith(self, prefix):return self.find(prefix) is not None
KMP算法
https://blog.csdn.net/bjweimengshu/article/details/104528964/
def same_start_end(s):"""最长前后缀相同的字符位数"""n = len(s) #整个字符串长度j = 0 # 前缀匹配指向i = 1 # 后缀匹配指向result_list=[0]*nwhile i < n:if j == 0 and s[j] != s[i]: # 比较不相等并且此时比较的已经是第一个字符了result_list[i] = 0 # 值为0i += 1 # 向后移动elif s[j] != s[i] and j != 0: #比较不相等,将j值设置为j前一位的result_list中的值,为了在之前匹配到的子串中找到最长相同前后缀j = result_list[j-1]elif s[j] == s[i]: #相等则继续比较result_list[i] = j+1j = j+1i = i+1return result_listdef kmp(s,p):"""kmp算法,s是字符串,p是模式字符串,返回值为匹配到的第一个字符串的第一个字符的索引,没匹配到返回-1"""s_length = len(s)p_length = len(p)i = 0 # 指向sj = 0 # 指向pnext = same_start_end(p)while i < s_length:if s[i] == p[j]: # 对应字符相同i += 1j += 1if j >= p_length: # 完全匹配return i-p_lengthelif s[i] != p[j]: # 不相同if j == 0: # 与模式比较的是模式的第一个字符i += 1else: # 取模式当前字符之前最长相同前后缀的前缀的后一个字符继续比较j = next[j]if i == s_length: # 没有找到完全匹配的子串return -1
大数乘法
以字符串的形式读入两个数字,编写一个函数计算它们的乘积,以字符串形式返回。
(字符串长度不大于10000,保证字符串仅由’0’~'9’这10种字符组成)
"11","99"
"1089"
11*99=1089
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# @param s string字符串 第一个整数
# @param t string字符串 第二个整数
# @return string字符串
#
class Solution:def solve(self, s, t):s = list(map(int, list(s)))s.reverse()# 把个位数放到index =0 开始的地方t = list(map(int, list(t)))t.reverse()# 把个位数放到index =0 开始的地方ans = [0]*(len(s)+len(t))for i in range(0, len(s)):for j in range(0, len(t)):ans[i+j] += s[i]*t[j]carry = 0for i in range(0, len(ans)):ans[i] += carrycarry = int(ans[i]/10)ans[i] = str(ans[i] % 10)while ans[-1] == '0' and len(ans) > 1:ans.pop()ans.reverse()return ''.join(ans)大数加法https://www.nowcoder.com/practice/11ae12e8c6fe48f883cad618c2e81475?tpId=117&tPage=3&rp=3&ru=%2Fta%2Fcoding-interviews&qru=%2Fta%2Fcoding-interviews%2Fquestion-rankin以字符串的形式读入两个数字,编写一个函数计算它们的和,以字符串形式返回。(字符串长度不大于100000,保证字符串仅由'0'~'9'这10种字符组成)
4.链表
链表中环的入口结点
class Solution(object):def hasCycle(self, head):""":type head: ListNode:rtype: bool"""if head == None or head.next == None:return Falseslow = fast = headwhile fast and fast.next:slow = slow.nextfast = fast.next.nextif slow == fast:return Truereturn False
class Solution:def EntryNodeOfLoop(self, pHead):# write code hereif pHead== None or pHead.next == None:return Nonefast = slow = pHeadwhile(fast and fast.next):slow = slow.nextfast = fast.next.nextif slow == fast:fast = pHeadwhile(fast!=slow):fast = fast.nextslow = slow.nextreturn fastreturn None
翻转链表
https://blog.csdn.net/songyunli1111/article/details/79416684
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:# 返回ListNodedef ReverseList(self, pHead):if not pHead or not pHead.next:return pHeadlast = None #指向上一个节点while pHead:#先用tmp保存pHead的下一个节点的信息,#保证单链表不会因为失去pHead节点的next而就此断裂tmp = pHead.next #保存完next,就可以让pHead的next指向last了pHead.next = last#让last,pHead依次向后移动一个节点,继续下一次的指针反转last = pHeadpHead = tmpreturn last###### 反转m和n之间的链表 lintcode92
# 1-2-3-4-5,m=3,n=4;
# 1-2-4-3-5;
class Solution:def reverseBetween(self , head , m , n ):# write code hereif head is None or head.next is None or m>=n:return head# steps:1.find m node, 2. reverse m and n 3. return # step_1dummy = ListNode(-1)dummy.next = headlast = dummyi=1while(i<m):last = headhead = head.nexti += 1# temp savepart1 = last # 前半部分的最后一个节点part2 = head # 后半部分的最后一个节点# step_2while(i<=n):tmp = head.nexthead.next = lastlast = headhead = tmpi+=1part1.next = last # 指向最新的头结点part2.next = head # 保证后续有的连起来return dummy.next
链表中倒数第k个结点
class Solution:def FindKthToTail(self, head, k):# write code herep1 = p2 = headfor i in range(k):if p1==None:return Nonep1 = p1.nextwhile(p1):p2 = p2.nextp1 = p1.nextreturn p2
合并两个排序的链表
class Solution:# 返回合并后列表def Merge(self, pHead1, pHead2):# write code hereret = ListNode(0)tmp = ret p1 = pHead1p2 = pHead2while(p1 and p2):if p1.val<p2.val:tmp.next = p1p1 = p1.nextelse:tmp.next = p2p2 = p2.nexttmp = tmp.nextif p1:tmp.next = p1if p2:tmp.next = p2return ret.next
复杂链表的复制
- 将原链表所有的结点拷贝一份,并且每个拷贝的结点和原来的结点连续出现,如下图:
- 此时,原来结点指向下一个结点的指针都可以先链接上,原来的random指针也还在;但是每个复制新建的node的random区域还是空的
- 找出规律:A.next.random = a.random.next
理解:如上图:A.next.raomd,是指第二个“1结点”的random指针,它应该指向 第一个“1结点”的random(第一个“3结点”)后一个结点(即第二个“3结点”),所以有上述变化通式 - 让每两个相同的结点断开,具体做法为:比如第一个“1结点” 让它指向 第一个“2结点”,random也跟着原来的指向变化,后面的结点重复操作,就能达到下图示意的,复制了复杂链表的操作
class RandomListNode:def __init__(self, x):self.label = xself.next = Noneself.random = Noneclass Solution:# 返回 RandomListNodedef Clone(self, pHead):if pHead is None:return None# 为每一个结点复制一个node,并插入到原链表中pTemp = pHead while pTemp:node = RandomListNode(pTemp.label)node.next = pTemp.next # 如下图2-1pTemp.next = node # 如下图 2-2pTemp = node.next # 如下图2-3:完成第一个新node插入,移动pTemp,重复上述,完成第二个# 实现新建node的random指向pTemp = pHead while pTemp:if pTemp.random: # 如果random指针存在pTemp.next.random = pTemp.random.next # 图2-4:通过前一个random找到node的randompTemp = pTemp.next.next # 完成一个,移动pTemp帮助找到下一个的random# 断开 原来node 和新 node 间 的链接pTemp = pHead newHead = pHead.next # 这个是新链表的头,到最后返回,一般要保留pNewTemp = pHead.next # 再新建一个中间变量来存储新的nodewhile pTemp:pTemp.next = pTemp.next.next # 改变前一个node的指向,让它不要指向新建的nodeif pNewTemp.next: # 如果下个一的新node存在 (备注 1)pNewTemp.next = pNewTemp.next.next # (备注 2)pNewTemp = pNewTemp.next # (备注 3)pTemp = pTemp.next # (备注 4) 备注(1~4)见下备注图解return newHead# 测试一下
if __name__ == '__main__':n1 = RandomListNode(1)n2 = RandomListNode(2)n3 = RandomListNode(3)n4 = RandomListNode(4)n5 = RandomListNode(5)n1.next = n2n2.next = n3n3.next = n4n4.next = n5s = Solution()new_head = s.Clone(n1)res = new_headwhile res:print(res.label)res = res.next # 输出结果 1 2 3 4 5 说明复制成功
两个链表的第一个公共结点
思考:设链表pHead1的长度为a,到公共结点的长度为l1;链表pHead2的长度为b,到公共结点的长度为l2,有a+l2 = b+l1
### 思路:第一次循环 while(pa!=pb)会将长度自动对齐;
### 第二次循环,就正常去判断了;一个trick
### https://blog.csdn.net/qq_36243414/article/details/90452723
class Solution:def FindFirstCommonNode(self, pHead1, pHead2):# write code hereif pHead1== None or pHead2 == None:return Nonepa = pHead1pb = pHead2 while(pa!=pb):pa = pHead2 if pa is None else pa.nextpb = pHead1 if pb is None else pb.nextreturn pa
5.二叉树
二叉树的镜像(Symmetric Tree)
牛客网链接
Leetcode链接
class Solution:# 返回镜像树的根节点def Mirror(self, root):if root == None:return self.Mirror(root.left)self.Mirror(root.right)root.left,root.right = root.right,root.left
二叉树的先序、中序、后续遍历 递归和非递归
# 先序打印二叉树(递归)
def preOrderTraverse(node):if node is None:return Noneprint(node.val)preOrderTraverse(node.left)preOrderTraverse(node.right)
# 先序打印二叉树(非递归)
def preOrderTravese(node):stack = [node]while len(stack) > 0:print(node.val)if node.right is not None:stack.append(node.right)if node.left is not None:stack.append(node.left)node = stack.pop()# 中序打印二叉树(递归)
def inOrderTraverse(node):if node is None:return NoneinOrderTraverse(node.left)print(node.val)inOrderTraverse(node.right)
# 中序打印二叉树(非递归)
def inOrderTraverse(node):stack = []pos = nodewhile pos is not None or len(stack) > 0:if pos is not None:stack.append(pos)pos = pos.leftelse:pos = stack.pop()print(pos.val)pos = pos.right# 后序打印二叉树(递归)
def postOrderTraverse(node):if node is None:return NonepostOrderTraverse(node.left)postOrderTraverse(node.right)print(node.val)
# 后序打印二叉树(非递归)
# 使用两个栈结构
# 第一个栈进栈顺序:左节点->右节点->跟节点
# 第一个栈弹出顺序: 跟节点->右节点->左节点(先序遍历栈弹出顺序:跟->左->右)
# 第二个栈存储为第一个栈的每个弹出依次进栈
# 最后第二个栈依次出栈
def postOrderTraverse(node):stack = [node]stack2 = []while len(stack) > 0:node = stack.pop()stack2.append(node)if node.left is not None:stack.append(node.left)if node.right is not None:stack.append(node.right)while len(stack2) > 0:print(stack2.pop().val)# 先进先出选用队列结构
import queue
def layerTraverse(head):if not head:return Noneque = queue.Queue() # 创建先进先出队列que.put(head)while not que.empty():head = que.get() # 弹出第一个元素并打印print(head.val)if head.left: # 若该节点存在左子节点,则加入队列(先push左节点)que.put(head.left)if head.right: # 若该节点存在右子节点,则加入队列(再push右节点)que.put(head.right)
# 求二叉树节点个数
def treeNodenums(node):if node is None:return 0nums = treeNodenums(node.left)nums += treeNodenums(node.right)return nums + 1
平衡二叉树的判断
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:def IsBalanced_Solution(self, pRoot):if not pRoot: return Trueleft = self.TreeDepth(pRoot.left)right = self.TreeDepth(pRoot.right)if abs(left - right) > 1:return Falsereturn self.IsBalanced_Solution(pRoot.left) and self.IsBalanced_Solution(pRoot.right)def TreeDepth(self, pRoot):if not pRoot: return 0left = self.TreeDepth(pRoot.left)right = self.TreeDepth(pRoot.right)return max(left, right) + 1
二叉树的深度
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:def TreeDepth(self, pRoot):# write code hereif pRoot == None:return 0if pRoot.left == None and pRoot.right==None:return 1return max(self.TreeDepth(pRoot.left),self.TreeDepth(pRoot.right))+1
二叉树的下一个结点
class Solution:def GetNext(self, pNode):# write code here# left root rightif pNode == None: # 空节点return Noneif pNode.right: # 有右节点tmp = pNode.rightwhile(tmp.left):tmp = tmp.leftreturn tmpp = pNode.next # 没有右节点while(p and p.right==pNode):pNode = pp = p.nextreturn p
对称的二叉树
Leetcode 101. Symmetric Tree
判断一棵树是不是左右对称的树
class Solution:def Symmetrical(self,Lnode,Rnode):if Lnode == None and Rnode == None:return Trueif Lnode and Rnode:return Lnode.val == Rnode.val and self.Symmetrical(Lnode.right,Rnode.left) and self.Symmetrical(Lnode.left,Rnode.right)else:return Falsedef isSymmetrical(self, pRoot):# write code hereif pRoot == None:return Truereturn self.Symmetrical(pRoot.left,pRoot.right)
将二叉树按照层级转化为链表
1/ \2 3/
4
[1->null,2->3->null,4->null
]
"""
Definition of TreeNode:
class TreeNode:def __init__(self, val):this.val = valthis.left, this.right = None, None
Definition for singly-linked list.
class ListNode:def __init__(self, x):self.val = xself.next = None
"""
class Solution:# @param {TreeNode} root the root of binary tree# @return {ListNode[]} a lists of linked listdef binaryTreeToLists(self, root):# Write your code here#二叉树的层次遍历res_list = []if not root:return []q = [root]while q:new_q = []dummy = ListNode(0)pre = dummyfor node in q:if node.left:new_q.append(node.left)if node.right:new_q.append(node.right)pre.next = ListNode(node.val)pre = pre.nextq = new_qres_list.append(dummy.next)return res_list
把二叉树打印成多行
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
class Solution:# 返回二维列表[[1,2],[4,5]]def Print(self, pRoot):# write code hereif pRoot == None:return []stack = [pRoot]ret = []while(stack):tmpstack = []tmp = []for node in stack:tmp.append(node.val)if node.left:tmpstack.append(node.left)if node.right:tmpstack.append(node.right)ret.append(tmp[:])stack = tmpstack[:]return ret
之字形打印二叉树
class Solution:def Print(self, pRoot):# write code hereif pRoot == None:return []stack = [pRoot]step = 1ret = []while(stack):tmpstack = []tmp = []for node in stack:tmp+=[node.val]if node.left:tmpstack.append(node.left)if node.right:tmpstack.append(node.right)if step%2==0:tmp.reverse()ret.append(tmp)step += 1stack = tmpstack[:]return ret
序列化和反序列化二叉树
Serialize and Deserialize Binary Tree
class Solution:def Serialize(self, root):# write code heredef doit(node):if node: # 先序遍历的方式vals.append(str(node.val))doit(node.left)doit(node.right)else:vals.append('#')vals = []doit(root)return ' '.join(vals)def Deserialize(self, s):# write code heredef doit():val = next(vals)if val == '#':return Nonenode = TreeNode(int(val))node.left = doit()node.right = doit()return nodevals = iter(s.split())return doit()
二叉平衡树中的第k小数
二叉搜索树中的第k大结点
Leetcode 230. Kth Smallest Element in a BST
思路:BST的中序遍历就是一个有序数组,需要注意到Leetcode中限制了k在[1,树结点个数]而牛客网没有,所以需要考虑k的值有没有超出
class Solution:# 返回对应节点TreeNodedef KthNode(self, pRoot, k):# write code hereif not pRoot:return stack=[]cnt=0while pRoot or len(stack)>0:if pRoot is not None:stack.append(pRoot)pRoot = pRoot.leftelse:pRoot = stack.pop()cnt+=1if cnt==k:return pRootpRoot = pRoot.right
重建二叉树
Leetcode 105. Construct Binary Tree from Preorder and Inorder Traversal
根据先序、中序来构建二叉树
class Solution(object):def buildTree(self, pre, tin):""":type preorder: List[int]:type inorder: List[int]:rtype: TreeNode"""if pre==[]:return Noneval = pre[0]idx = tin.index(val)ltin = tin[0:idx]rtin = tin[idx+1:]lpre = pre[1:1+len(ltin)]rpre = pre[1+len(ltin):]root = TreeNode(val)root.left = self.buildTree(lpre,ltin)root.right = self.buildTree(rpre,rtin)return root
Leetcode 106. Construct Binary Tree from Inorder and Postorder Traversal
根据中序和后序构建二叉树
class Solution(object):def buildTree(self, inorder, postorder):""":type inorder: List[int]:type postorder: List[int]:rtype: TreeNode"""if postorder == []:return Noneval = postorder[-1]idx = inorder.index(val)lin = inorder[0:idx]rin = inorder[idx+1:]lpos = postorder[0:len(lin)]rpos = postorder[len(lin):-1]root = TreeNode(val)root.left = self.buildTree(lin,lpos)root.right = self.buildTree(rin,rpos)return root
二叉搜索树与双向链表
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
思考:左子树上最右结点 -> root -> 右子树上的最左结点
2.1 有右子树,那本节点是右子树的最左侧的下一个(递归返回的保证是最左侧节点)
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:def Convert(self, pRootOfTree):# write code hereif pRootOfTree == None:return pRootOfTreeif pRootOfTree.left == None and pRootOfTree.right == None:return pRootOfTreeleft = self.Convert(pRootOfTree.left)p = leftif left:while(p.right):p = p.rightp.right = pRootOfTreepRootOfTree.left = pright = self.Convert(pRootOfTree.right)if right:pRootOfTree.right = rightright.left = pRootOfTreereturn left if left else pRootOfTree
判断树B是否是树A的子结构
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
两个逻辑,一个是找到一个之后判断是否完全一样,另外一个是递归找到第一个一样的;
class Solution:# 给定两个二叉树(的根节点)A、B,判断B 是不是A 的二叉树def HasSubtree(self, pRoot1, pRoot2):if pRoot1 == None or pRoot2 == None:return Falseresult = Falseif pRoot1.val == pRoot2.val:result = self.isSubtree(pRoot1, pRoot2)if result == False:result = self.HasSubtree(pRoot1.left, pRoot2) | self.HasSubtree(pRoot1.right, pRoot2)return resultdef isSubtree(self, root1, root2):if root2 == None:return Trueif root1 == None:return Falseif root1.val == root2.val:return self.isSubtree(root1.left, root2.left) & self.isSubtree(root1.right, root2.right)return False
二叉树中和为某一值的路径
输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
思考:dfs
###### https://www.jiuzhang.com/problem/binary-tree-path-sum/#tag-lang-python
"""
Definition of TreeNode:
class TreeNode:def __init__(self, val):self.val = valself.left, self.right = None, None
"""
class Solution:# @param {TreeNode} root the root of binary tree# @param {int} target an integer# @return {int[][]} all valid pathsdef binaryTreePathSum(self, root, target):# Write your code hereresult = []path = []self.dfs(root, path, result, 0, target)return resultdef dfs(self, root, path, result, len, target):if root is None:returnpath.append(root.val)len += root.valif root.left is None and root.right is None and len == target:result.append(path[:])self.dfs(root.left, path, result, len, target)self.dfs(root.right, path, result, len, target)path.pop()
######
### https://www.jiuzhang.com/problem/binary-tree-path-sum-ii/#tag-lang-python
"""
Definition of TreeNode:
class TreeNode:def __init__(self, val):self.val = valself.left, self.right = None, None
"""
class Solution:# @param {TreeNode} root the root of binary tree# @param {int} target an integer# @return {int[][]} all valid pathsdef binaryTreePathSum2(self, root, target):# Write your code hereresult = []path = []if root is None:return resultself.dfs(root, path, result, 0, target)return resultdef dfs(self, root, path, result, l, target):if root is None:returnpath.append(root.val)tmp = targetfor i in xrange(l , -1, -1):tmp -= path[i]if tmp == 0:result.append(path[i:])self.dfs(root.left, path, result, l + 1, target)self.dfs(root.right, path, result, l + 1, target)path.pop()class Solution:# 返回二维列表,内部每个列表表示找到的路径def FindPath(self, root, expectNumber):# write code hereret = []def dfs(root,sum_,tmp):if root:if root.left==None and root.right == None:if root.val == sum_:tmp.append(root.val)ret.append(tmp[:])else:tmp.append(root.val)dfs(root.left,sum_-root.val,tmp[:])dfs(root.right,sum_-root.val,tmp[:])dfs(root,expectNumber,[])return ret####
二叉搜索树的后序遍历序列
# coding:utf-8
class Solution:def VerifySquenceOfBST(self, sequence):# write code hereif sequence==None or len(sequence)==0:return Falselength=len(sequence)root=sequence[length-1]# 在二叉搜索 树中 左子树节点小于根节点for i in range(length):#循环的值设置得很巧妙,和下方的left、right初始值对应if sequence[i]>root:break# 二叉搜索树中右子树的节点都大于根节点for j in range(i,length):if sequence[j]<root:return False# 判断左子树是否为二叉树left=Trueif i>0:#说明存在左子树,求左子树是否为后续遍历,然后更新left的值left=self.VerifySquenceOfBST(sequence[0:i])# 判断右子树是否为二叉树right=Trueif j<length-1:#说明存在右子树,判断右子树是否为后续遍历。如果不存在右子树,默认为真。right=self.VerifySquenceOfBST(sequence[i:-1])return left and right
最近公共祖先
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
给定一棵二叉树以及这棵树上的两个节点 o1 和 o2,请找到 o1 和 o2 的最近公共祖先节点。
[3,5,1,6,2,0,8,#,#,7,4],5,1
3
# https://www.jiuzhang.com/problem/lowest-common-ancestor/#tag-lang-python
class Solution:"""@param: root: The root of the binary search tree.@param: A: A TreeNode in a Binary.@param: B: A TreeNode in a Binary.@return: Return the least common ancestor(LCA) of the two nodes."""def lowestCommonAncestor(self, root, A, B):if root is None:return Noneif root == A or root == B:return rootleft = self.lowestCommonAncestor(root.left, A, B)right = self.lowestCommonAncestor(root.right, A, B)if left and right:return rootif left:return leftif right:return rightreturn None
6.复杂数据结构
顺时针打印矩阵
# -*- coding:utf-8 -*-
class Solution:# matrix类型为二维列表,需要返回列表def printMatrix(self, matrix):# write code hereans=[]m=len(matrix)if m==0:return ansn=len(matrix[0])# 边界范围upper_i =0;lower_i=m-1;left_j=0;right_j=n-1# 整体计数,确定何时结束num=1# 轮询i=0;j=0# 轮询方向right_pointer=1down_pointer=0while(num<=m*n):ans.append(matrix[i][j])if right_pointer==1: # 判断朝向if j<right_j: # 没有到边界j=j+1else: # 到边界right_pointer=0down_pointer=1upper_i = upper_i+1i = i+1elif down_pointer == 1:if i<lower_i:i = i+1else:right_pointer=-1down_pointer=0right_j = right_j -1j = j-1elif right_pointer ==-1:if j > left_j:j=j-1else:right_pointer=0down_pointer=-1lower_i =lower_i-1i = i-1elif down_pointer == -1:if i > upper_i:i=i-1else:right_pointer=1down_pointer=0left_j = left_j +1j = j+1num=num+1return ans
数据流中的中位数
from heapq import *
#heapq默认就是最小堆,large 是最小堆,但是都是正数所以比较大的最小堆,small是最大堆,但是都是负数,所以是比较小的最大堆;
#1.首先将large 跟当前num做判断,然后弹出最小的那个,放入最大堆;这里large的个数并没有增加,只是增加了小的,
#2.如果large个数比较小,就在向large里面放,
#3.中位数如果是奇数个,那么它一定在large里面;如果是偶数个,那就求个平均数;
class MedianFinder:def __init__(self):self.heaps = [], []def addNum(self, num):small, large = self.heapsheappush(small, -heappushpop(large, num))if len(large) < len(small):heappush(large, -heappop(small))def findMedian(self):small, large = self.heapsif len(large) > len(small):return float(large[0])return (large[0] - small[0]) / 2.0
滑动窗口的最大值
### 暴力解法
class Solution:def maxInWindows(self, num, size):# write code hereans=[]if not num or size==0:return ans for i in range(len(num)-size+1):mx=0for j in range(size):mx=max(mx,num[i+j])ans.append(mx)return ans
### 单调队列解法
## https://blog.csdn.net/qq_20141867/article/details/81088705
# -*- coding:utf-8 -*-
class Solution:def maxInWindows(self, num, size):# write code here# 存放可能是最大值的下标,单调递增的队列maxqueue = []# 存放窗口中最大值maxlist = []n = len(num)# 参数检验if n == 0 or size == 0 or size > n:return maxlistfor i in range(n):# 判断队首下标对应的元素是否已经滑出窗口if len(maxqueue) > 0 and i - size >= maxqueue[0]:maxqueue.pop(0)# 判断新入的是否比第0 index的要大,如果是就要全部替换掉;while len(maxqueue) > 0 and num[i] > num[maxqueue[-1]]:maxqueue.pop()maxqueue.append(i)if i >= size - 1:maxlist.append(num[maxqueue[0]])return maxlist
用两个栈实现队列
# -*- coding:utf-8 -*-
class Solution:def __init__(self):self.stack1 = []self.stack2 = []def push(self, node):# write code hereself.stack1.append(node)def pop(self):# return xxif len(self.stack2):return self.stack2.pop()while(self.stack1):self.stack2.append(self.stack1.pop())return self.stack2.pop()
包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。
# -*- coding:utf-8 -*-
class Solution:def __init__(self):"""initialize your data structure here."""self.stack = []self.minstack =[]def push(self, x):""":type x: int:rtype: void"""self.stack.append(x)if len(self.minstack)==0 or self.minstack[-1][0]>x:self.minstack.append((x,1))elif self.minstack[-1][0] == x:self.minstack[-1] = (x,self.minstack[-1][1]+1)def pop(self):""":rtype: void"""ans = self.stack[-1]self.stack = self.stack[0:len(self.stack)-1]if ans == self.minstack[-1][0]:if self.minstack[-1][1] == 1:self.minstack.remove(self.minstack[-1])else:self.minstack[-1] = (ans,self.minstack[-1][1]-1)return ansdef top(self):""":rtype: int"""return self.stack[-1]def min(self):""":rtype: int"""return self.minstack[-1][0]
栈的压入、弹出序列
# -*- coding:utf-8 -*-
class Solution:def IsPopOrder(self, pushV, popV):# write code herestack = []while(popV):if pushV and pushV[0]==popV[0]:pushV.pop(0)popV.pop(0)elif stack and stack[-1]==popV[0]:stack.pop()popV.pop(0)elif pushV:stack.append(pushV.pop(0))else:return Falsereturn True
矩阵中的路径
矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
class Solution:def dfs(self, matrix, flag, rows, cols, r, c, s):if s == '':return Truedx = [-1, 1, 0, 0]dy = [0, 0, -1, 1] # 利用两个数组,来实现对每个格子周围格子的访问for k in range(4):x = dx[k] + ry = dy[k] + cif x >= 0 and x < rows and y >= 0 and y < cols and flag[x][y] and matrix[x * cols + y] == s[0]:flag[x][y] = False # 修改当前格子的标识if self.dfs(matrix, flag[:], rows, cols, x, y, s[1:]): # 递归return Trueflag[x][y] = True# 如果上一个判断条件返回的是False,那么就说明这个格子目前还不是路径上的格子,再把当前格子的标识修改回来。return Falsedef hasPath(self, matrix, rows, cols, path):if path == '':return Trueflag = [[True for c in range(cols)] for r in range(rows)] # 定义一个表示矩阵for r in range(rows):# 对这个矩阵中的元素进行遍历,不断找路径进入矩阵的起点,直到以某个格子为起点找到整个路径为止。for c in range(cols):if matrix[r * cols + c] == path[0]:flag[r][c] = Falseif self.dfs(matrix, flag[:], rows, cols, r, c, path[1:]):return Trueflag[r][c] = Truereturn False
机器人的运动范围
# -*- coding:utf-8 -*-
class Solution:def movingCount(self, threshold, rows, cols):# write code herememories = set()def dfs(i,j):def judge(i,j):return sum(map(int, list(str(i)))) + sum(map(int, list(str(j)))) <= thresholdif not judge(i,j) or (i,j) in memories:returnmemories.add((i,j))if i != rows - 1:dfs(i + 1, j)if j != cols - 1:dfs(i, j + 1)dfs(0,0)return len(memories)
剑指offer 手刷python 汇总整理版本~相关推荐
- LeetCode刷题——剑指offer深度优先搜索题目汇总
剑指offer深度优先搜索题目汇总 剑指 Offer 12. 矩阵中的路径 剑指 Offer 34. 二叉树中和为某一值的路径 剑指 Offer 36. 二叉搜索树与双向链表 剑指 Offer 54. ...
- 《剑指offer》刷题笔记(发散思维能力):求1+2+3+...+n
<剑指offer>刷题笔记(发散思维能力):求1+2+3+-+n 转载请注明作者和出处:http://blog.csdn.net/u011475210 代码地址:https://githu ...
- 剑指offer有python版吗_剑指Offer算法类题目[Python版]
标签:重复 作用 coding 面试 medium mba none fas utf-8 面试题012 数值的整数次方 解题思路1 考虑所有情况,循环连乘 代码: de ...
- 《剑指offer》刷题——【链表】从尾到头打印链表
<剑指offer>刷题--[链表]-<从尾到头打印链表> 问题分析: 递归实现: 1. 无返回值 2. 有返回值(ArrayList) 问题分析: 从头到尾打印链表比较简单,那 ...
- 《剑指Offer》刷题之最小的K个数
<剑指Offer>刷题之最小的K个数 我不知道将去向何方,但我已在路上! 时光匆匆,虽未曾谋面,却相遇于斯,实在是莫大的缘分,感谢您的到访 ! 题目: 给定一个数组,找出其中最小的K个数. ...
- 剑指Offer——毕业生求职网站汇总(干货)
#剑指Offer--毕业生求职网站汇总(干货) 致2017即将毕业的你~ ##精品网站 牛客网:https://www.nowcoder.com 赛码网:http://www.acmcoder.com ...
- 剑指Offer 66题 python版本 汇总
牛客网剑指offer 66题汇总 (python) 有部分参考牛客网答案,部分为自己提交结果 1. 二维数组中的查找 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每 ...
- Java算法:牛客网Java版剑指Offer全套算法面试题目整理及电子档,Java算法与数据结构面试题,面试刷题、背题必备!牛客网剑指offer
剑指offer(java版) 牛客网Java版剑指Offer全套题目67道 资源来源于网络 目录 1.二维数组中的查找 2.替换空格 3.从尾到头打印链表 4.重建二叉树 5.用两个栈实现队列 6.旋 ...
- 剑指offer算法题分析与整理(二)
下面整理一下我在刷剑指offer时,自己做的和网上大神做的各种思路与答案,自己的代码是思路一,保证可以通过,网友的代码提供出处链接. 目录 1.序列化二叉树 2.带记忆的DFS搜索 3.坐标数位和不大 ...
最新文章
- zookeeper启动占用8080端口
- cad2016中选择全图字体怎么操作_打开CAD图纸字体丢失、重新选择怎么办?这样设置,一辈子用的到...
- html5技术英文论文参考文献,英文论文的参考文献范例(精选8篇)
- python读写磁盘扇区数据_[Win32] 直接读写磁盘扇区(磁盘绝对读写)
- memcached全面剖析–5. memcached的应用和兼容程序(转)
- 计数器verilog代码(quartus II)
- 我为什么选择Hexo建站
- MPB:南京​湖泊所王建军组-​湖泊沉积物的野外采集方法
- 八月未央,梦落泸沽。
- 几十年前的老旧照片如何修复?还不知道旧照片怎么恢复清晰吗?
- 流利说英语level4_英语流利说level4原文graph?分享一下我的经验?
- 天池竞赛赛题-特征工程-天猫用户重复购买预测解析
- LiveGBS流媒体平台国标GB/T28181作为下级支持国标级联海康大华宇视华为等第三方国标平台支持对接政务公安内网国标视频平台
- 论文撰写八大技巧与八大心得,一文读懂
- python在windows中备份文件并压缩的解决办法
- Dremel的学习与理解
- vm虚拟服务器添加网卡,win7系统下vmware虚拟机添加加载无线网卡的方法
- 西游记中神兽谛听的能力 这款小程序也有
- 计算机网络——香农公式
- Linux--vim编辑器的使用
热门文章
- (23)语义分割--UNet
- 用计算机弹音乐我们一起猫叫,抖音上面我们一起学猫叫一起喵喵喵是什么歌 抖音学猫叫歌曲歌词...
- ASEMI代理AD8606ACBZ-REEL7原装ADI车规级AD8606ACBZ-REEL7
- pure specifier can only be specified for functions
- 怎样将收藏的网址导入到搜狗账号中
- 港大黄凯斌:6G时代的边缘智能,香农与图灵的相遇
- ESP32基础应用之使用两个ESP32通过阿里云物联网平台实现相互通信
- .NET周报【11月第4期 2022-11-30】
- open judge 1.6.4
- origin双y轴数据散点图显示