文章目录

  • 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

变态跳台阶
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
思考:在dp[n] = dp[n-1] + dp[n-2] + … + dp[1] + 1(直接跳n)步骤
即dp[n]=∑n−1i=1dp[i]+1dp[n]=∑i=1n−1dp[i]+1

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

矩形覆盖
我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2n的大矩形,总共有多少种方法?
思考: 2
1 1 种; 22 2种 23 3种 2*4 5种
dp[n]=dp[n−1]+dp[n−2]dp[n]=dp[n−1]+dp[n−2]

# -*- 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))

丑数

只包含因子2、3和5的数称作丑数(Ugly Number),求按从小到大的顺序的第N个丑数。因为丑数只包含质因子2,3,5,假设我们已经有n-1个丑数,按照顺序排列,且第n-1的丑数为M。那么第n个丑数一定是由这n-1个丑数分别乘以2,3,5,得到的所有大于M的结果中,最小的那个数。

事实上我们不需要每次都计算前面所有丑数乘以2,3,5的结果,然后再比较大小。因为在已存在的丑数中,一定存在某个数T2T2,在它之前的所有数乘以2都小于已有丑数,而T2×2T2×2的结果一定大于M,同理,也存在这样的数T3,T5T3,T5,我们只需要标记这三个数即可。

# -*- 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]

正则表达式匹配

请实现一个函数用来匹配包括’.‘和’*‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串”aaa”与模式”a.a”和”abaca”匹配,但是与”aa.a”和”ab*a”均不匹配
思考:
第一种情况,当p == ” 时 return s==”
当len§==1时 要满足len(s)==1 AND (p[0]s[0] OR p[0] == ‘.’)
当len§>1时,要讨论p[1] 是不是为’*’ ,因为如果p[1]’’ 时候 可能会是p[2:] 和 s 匹配情况
但当p[1]!=’
’ 时候 意味着 必须要关注是否 p[0]s[0] 或者 p[0]’.’
那么这两个可以合并为
IF len§ == 0 or p[1]!=’
返回 len(s) AND match(p[1:],s[1:]) AND (p[0]==s[0] OR p[0] == ‘.’)
然后最复杂的一种情况p[1] == ‘

p = ‘b*bbacd’ s = ‘bbbbbacd’
很明显的是如果p[0]!=s[0] 且 p[0]!=’.’ 那么 看p[2:] 和 s 的匹配情况
如果p[0] == s[0] 或者 p[0] == ‘.’ , 可以判断p[2:] 和 s[1:] … p[2:] 和 s[2:] … p[2:] 和 s[3:] … 搞个循环 就可以

# -*- 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 收集雨水

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.


The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped. Thanks Marcos for contributing this image!

Example:

Input: [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6

这道收集雨水的题跟之前的那道 Largest Rectangle in Histogram 有些类似,但是又不太一样,先来看一种方法,这种方法是基于动态规划 Dynamic Programming 的,维护一个一维的 dp 数组,这个 DP 算法需要遍历两遍数组,第一遍在 dp[i] 中存入i位置左边的最大值,然后开始第二遍遍历数组,第二次遍历时找右边最大值,然后和左边最大值比较取其中的较小值,然后跟当前值 A[i] 相比,如果大于当前值,则将差值存入结果,参见代码如下:

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 直方图中最大的矩形

Given n non-negative integers representing the histogram’s bar height where the width of each bar is 1, find the area of largest rectangle in the 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.

这道题让求直方图中最大的矩形,刚开始看到求极值问题以为要用DP来做,可是想不出递推式,只得作罢。这道题如果用暴力搜索法估计肯定没法通过OJ,但是我也没想出好的优化方法,在网上搜到了网友水中的鱼的博客,发现他想出了一种很好的优化方法,就是遍历数组,每找到一个局部峰值(只要当前的数字大于后面的一个数字,那么当前数字就看作一个局部峰值,跟前面的数字大小无关),然后向前遍历所有的值,算出共同的矩形面积,每次对比保留最大值。这里再说下为啥要从局部峰值处理,看题目中的例子,局部峰值为 2,6,3,我们只需在这些局部峰值出进行处理,为啥不用在非局部峰值处统计呢,这是因为非局部峰值处的情况,后面的局部峰值都可以包括,比如1和5,由于局部峰值6是高于1和5的,所有1和5能组成的矩形,到6这里都能组成,并且还可以加上6本身的一部分组成更大的矩形,那么就不用费力气去再统计一个1和5处能组成的矩形了。代码如下:

//就是遍历数组,每找到一个局部峰值(只要当前的数字大于后面的一个数字,那么当前数字就看作一个局部峰值,跟前面的数字大小无关),然后向前遍历所有的值,算出共同的矩形面积,每次对比保留最大值。
// 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 天的价格。

如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。

注意你不能在买入股票前卖出股票。

示例 1:

输入: [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)基本就是要用二分法,二分法的本质是保留有解的一半。

3.通用的二分法模板(四个要素)

①start+1<end

②start+(end-start)/2

③A[mid]==,<,>

④A[start] A[end] ? target

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

查找range

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

假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
你可以假设数组中不存在重复的元素。
你的算法时间复杂度必须是 O(log n) 级别。
示例:

Copy输入: nums = [4,5,6,7,0,1,2], target = 0
输出: 4输入: nums = [4,5,6,7,0,1,2], target = 3
输出: -1

题目链接: https://leetcode-cn.com/problems/search-in-rotated-sorted-array/
做这题之前要先把二分查找做了,并理解二分查找两种写法的不同的原因。

题目要求时间复杂度必须是O(logn)级别,所以不能直接遍历查找,而O(logn)的时间复杂度通常意味着二分查找。
旋转数组可以看做是两段升序数组的拼接,所以可以使用二分查找来做。令查找的边界left=0, right=nums.size()-1, 每次查找都在[left, right]范围内进行:

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的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
思考:

解法:1.穷举法,2.滑动窗口法

,3.数字规律法(往下看)

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

数组中只出现一次的数字

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字
思考:用hash;或者位运算
首先利用0 ^ a = a; a^a = 0的性质
两个不相等的元素在位级表示上必定会有一位存在不同,
将数组的所有元素异或得到的结果为不存在重复的两个元素异或的结果,
据异或的结果1所在的最低位,把数字分成两半,每一半里都还有一个出现一次的数据和其他成对出现的数据,
问题就转化为了两个独立的子问题“数组中只有一个数出现一次,其他数都出现了2次,找出这个数字”。

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

第一个只出现一次的字符

思考:用dict 最多256个来空间换时间

# -*- 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]

数组中的逆序对

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
方法1:思考:这边的python会超时,但是思路是对的
时间复杂度O(nlogn),空间复杂度O(n)。
先将数组逆转,构建一个新的数组L,将num二分插入到L中,所插入的位置i,代表有i个数字比当前这个数字小

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

方法2:归并排序的思路

连续子数组的最大和

可以用动态规划的思想来分析这个问题。如果用函数f(i)表示以第i个数字结尾的子数组的最大和,那么我们需要求出max[f(i)],其中0 <= i < n。我们可用如下边归公式求f(i):

这个公式的意义:当以第i-1 个数字结尾的子数组中所有数字的和小于0时,如果把这个负数与第i个数累加,得到的结果比第i个数字本身还要小,所以这种情况下以第i个数字结尾的子数组就是第i个数字本身。如果以第i-1 个数字结尾的子数组中所有数字的和大于0 ,与第i 个数字累加就得到以第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)

数组中重复的数字

在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中第一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

返回描述:

如果数组中有重复的数字,函数返回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

二维数组中的查找

在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
思考:从0,n-1出开始,小了往下,大了往左

# -*- 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

扑克牌顺子

LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张_)…他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子……LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何。为了方便起见,你可以认为大小王是0。

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

孩子们的游戏

每年六一儿童节,我都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)

如果没有小朋友,请返回-1

为了讨论方便,先把问题稍微改变一下,并不影响原意:
我们知道第一个人(编号一定是(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;
}

剪绳子

题目: 给你一根长度为n绳子,请把绳子剪成m段(m、n都是整数,n>1并且m>1)。每段的绳子的长度记为k[0]、k[1]、……、k[m]。k[0] * k[1]*…*k[m]可能的最大乘积是多少?例如当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到最大的乘积18。
思路:动态规划思想:即:长度为10的绳子,我们就计算出:长度1~9这9种长度的绳子,每种长度的最大乘积是多少。
  要求长度9的绳子的最大乘积,我们要知道18各个长度的最大乘积,要知道长度8的最大乘积,就要知道17长度的各个最大乘积,以此类推。

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

思考:递归 or 公式法

# -*- 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补码有一些问题;

python会讲补码存成正数 需要 -1 & num

https://blog.csdn.net/qq_16949707/article/details/106399430

a+b = a^b + (a&b)<<1;

# -*- 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的每个位上入手,pos来记录位,ans来记录当前1的个数,last来记录前面的数(这样讲好复杂,举个例子好了)
xxxxYzzzz (假设9位)
在Y上1的个数由xxxx,zzzz和Y来决定
首先至少有xxxx0000个
其次看Y
如果Y大于1那么会多了10000个
如果Y等于1那么会多了(zzzz+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

判断一个字符串是否表示数值

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。

# -*- 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

字符串的排列

思考:dfs

输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串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)

字符流中第一个不重复的字符

思考:用个队列和hash

# -*- 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)

最长回文子串

对于一个字符串,请设计一个高效算法,计算其中最长回文子串的长度。

给定字符串A以及它的长度n,请返回最长回文子串的长度。

# 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。

算法思路:

1、把两个字符串分别以行和列组成一个二维矩阵。

2、比较二维矩阵中每个点对应行列字符中否相等,相等的话值设置为1,否则设置为0。

3、通过查找出值为1的最长对角线就能找到最长公共子串。

针对于上面的两个字符串我们可以得到的二维矩阵如下:

从上图可以看到,str1和str2共有5个公共子串,但最长的公共子串长度为5。

为了进一步优化算法的效率,我们可以再计算某个二维矩阵的值的时候顺便计算出来当前最长的公共子串的长度,即某个二维矩阵元素的值由record[i][j]=1演变为record[i][j]=1 +record[i-1][j-1],这样就避免了后续查找对角线长度的操作了。修改后的二维矩阵如下:

# 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

1.定义一个根结点root作为整棵树的查找起点。

2.比如插入一个单词apple:

我们从root开始,依次往下查找a,p,p,l,e:如果在结点n的下一个字母里没有找到我们想要的字母ch,我们就增加新结点到结点n的next[],式子next[ch-‘a’]=new Node()。

3.查找一个单词app:

我们从root开始,依次往下查找a,p,p:如果在结点n的下一个字母里没有找到我们想要的字母ch,那么说明不存在,返回False;如果有,那么继续往下找,直到查找的单词app找到最后一位,这时候我们判断一下这个位置的isWord是否为True,如果为True说明这是一个完整单词,否则只是部分,返回False。

4.查找一个前缀

查找一个前缀和查找一个单词的区别就是,当我们想要查找的前缀找到最后一位,不需要判断是否是完整的单词,直接返回True即可。如果不能全部找到则返回False。

# 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种字符组成)

示例1

"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.链表

链表中环的入口结点

Leetcode 142. Linked List Cycle II
寻找环的入口结点
这题是Leetcode 141. Linked List Cycle的扩展。
判断是否存在环用fast和slow两个指针,从head开始,一个走一步,一个走两步,如果最终到达同一个结点,则说明存在环。

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

而寻找环的入口,假设入口结点距离头结点a个单位,fast和slow相遇在距离入口结点b个单位的位置,环剩下的长度为c,则有a+b+c+b = 2*(a+b) -> a = c
因此,在重合时候,将fast置为head,再一步一步地走,当与slow重合时的结点即为入口结点

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个结点

思考:两个指针p,q p先走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

复杂链表的复制

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

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

平衡二叉树的判断

思考:BST的定义为,原问题拆分为计算树高度和判断高度差

# -*- 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

二叉树的下一个结点

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
思路:中序遍历的顺序为LVR
则有以下三种情况:
a. 如果该结点存在右子结点,那么该结点的下一个结点是右子结点树上最左子结点
b. 如果该结点不存在右子结点,且它是它父结点的左子结点,那么该结点的下一个结点是它的父结点
c. 如果该结点既不存在右子结点,且也不是它父结点的左子结点,则需要一路向祖先结点搜索,直到找到一个结点,该结点是其父亲结点的左子结点。如果这样的结点存在,那么该结点的父亲结点就是我们要找的下一个结点。

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 -> 右子树上的最左结点

分情况讨论:1. 本节点结束;

​ 2.本节点有左右节点;

​ 2.1 有左子树,那本节点是左子树的最右侧的下一个

​ 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####

二叉搜索树的后序遍历序列

输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
思考:后序遍历意味着num[-1]为root,那么根据这个值和二叉搜索树的性质,可以把数组划分成两个部分,left 和 right ,再递归判断

# 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 的最近公共祖先节点。

示例1

[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

数据流中的中位数

Find Median from Data Stream

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

滑动窗口的最大值

给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下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}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
思考:假设当前窗口起始位置为start,结束位置为end,我们要构造一个stack, 使得stack[0]为区间[start,end]的最大值。

窗口的滑动过程中数字的进出类似一个队列中元素的出队入队,这里我们采用一个队列queue存储可能成为最大值的元素下标(之所以队列中存元素下标而不是元素值本身,是因为队列并不存储所有元素,而我们需要知道什么时候队首元素已经离开滑动窗口)。当遇到一个新数时,将它与队尾元素比较,如果大于队尾元素,则丢掉队尾元素,继续重复比较,直到新数小于队尾元素,或者队列为空为止,将新数下标放入队列。同时需要根据滑动窗口的移动判断队首元素是否已经离开

### 暴力解法
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

用两个栈实现队列

思考:栈FILO,队列FIFO

# -*- 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]

栈的压入、弹出序列

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)

# -*- 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

矩阵中的路径

思考:dfs加记忆化搜索

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VAqHxN4O-1608185509773)(C:\Users\lijingjie\AppData\Roaming\Typora\typora-user-images\image-20201202162808900.png)]

矩阵中包含一条字符串"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

机器人的运动范围

地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
思考:dfs+记忆化搜索,注意虽然说是可以向左右上下走动,但是因为是从坐标0,0开始,所以只需要向左或者向下走动就行;

# -*- 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 汇总整理版本~相关推荐

  1. LeetCode刷题——剑指offer深度优先搜索题目汇总

    剑指offer深度优先搜索题目汇总 剑指 Offer 12. 矩阵中的路径 剑指 Offer 34. 二叉树中和为某一值的路径 剑指 Offer 36. 二叉搜索树与双向链表 剑指 Offer 54. ...

  2. 《剑指offer》刷题笔记(发散思维能力):求1+2+3+...+n

    <剑指offer>刷题笔记(发散思维能力):求1+2+3+-+n 转载请注明作者和出处:http://blog.csdn.net/u011475210 代码地址:https://githu ...

  3. 剑指offer有python版吗_剑指Offer算法类题目[Python版]

    标签:重复   作用   coding   面试   medium   mba   none   fas   utf-8 面试题012 数值的整数次方 解题思路1 考虑所有情况,循环连乘 代码: de ...

  4. 《剑指offer》刷题——【链表】从尾到头打印链表

    <剑指offer>刷题--[链表]-<从尾到头打印链表> 问题分析: 递归实现: 1. 无返回值 2. 有返回值(ArrayList) 问题分析: 从头到尾打印链表比较简单,那 ...

  5. 《剑指Offer》刷题之最小的K个数

    <剑指Offer>刷题之最小的K个数 我不知道将去向何方,但我已在路上! 时光匆匆,虽未曾谋面,却相遇于斯,实在是莫大的缘分,感谢您的到访 ! 题目: 给定一个数组,找出其中最小的K个数. ...

  6. 剑指Offer——毕业生求职网站汇总(干货)

    #剑指Offer--毕业生求职网站汇总(干货) 致2017即将毕业的你~ ##精品网站 牛客网:https://www.nowcoder.com 赛码网:http://www.acmcoder.com ...

  7. 剑指Offer 66题 python版本 汇总

    牛客网剑指offer 66题汇总 (python) 有部分参考牛客网答案,部分为自己提交结果 1. 二维数组中的查找 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每 ...

  8. Java算法:牛客网Java版剑指Offer全套算法面试题目整理及电子档,Java算法与数据结构面试题,面试刷题、背题必备!牛客网剑指offer

    剑指offer(java版) 牛客网Java版剑指Offer全套题目67道 资源来源于网络 目录 1.二维数组中的查找 2.替换空格 3.从尾到头打印链表 4.重建二叉树 5.用两个栈实现队列 6.旋 ...

  9. 剑指offer算法题分析与整理(二)

    下面整理一下我在刷剑指offer时,自己做的和网上大神做的各种思路与答案,自己的代码是思路一,保证可以通过,网友的代码提供出处链接. 目录 1.序列化二叉树 2.带记忆的DFS搜索 3.坐标数位和不大 ...

最新文章

  1. zookeeper启动占用8080端口
  2. cad2016中选择全图字体怎么操作_打开CAD图纸字体丢失、重新选择怎么办?这样设置,一辈子用的到...
  3. html5技术英文论文参考文献,英文论文的参考文献范例(精选8篇)
  4. python读写磁盘扇区数据_[Win32] 直接读写磁盘扇区(磁盘绝对读写)
  5. memcached全面剖析–5. memcached的应用和兼容程序(转)
  6. 计数器verilog代码(quartus II)
  7. 我为什么选择Hexo建站
  8. MPB:南京​湖泊所王建军组-​湖泊沉积物的野外采集方法
  9. 八月未央,梦落泸沽。
  10. 几十年前的老旧照片如何修复?还不知道旧照片怎么恢复清晰吗?
  11. 流利说英语level4_英语流利说level4原文graph?分享一下我的经验?
  12. 天池竞赛赛题-特征工程-天猫用户重复购买预测解析
  13. LiveGBS流媒体平台国标GB/T28181作为下级支持国标级联海康大华宇视华为等第三方国标平台支持对接政务公安内网国标视频平台
  14. 论文撰写八大技巧与八大心得,一文读懂
  15. python在windows中备份文件并压缩的解决办法
  16. Dremel的学习与理解
  17. vm虚拟服务器添加网卡,win7系统下vmware虚拟机添加加载无线网卡的方法
  18. 西游记中神兽谛听的能力 这款小程序也有
  19. 计算机网络——香农公式
  20. Linux--vim编辑器的使用

热门文章

  1. (23)语义分割--UNet
  2. 用计算机弹音乐我们一起猫叫,抖音上面我们一起学猫叫一起喵喵喵是什么歌 抖音学猫叫歌曲歌词...
  3. ASEMI代理AD8606ACBZ-REEL7原装ADI车规级AD8606ACBZ-REEL7
  4. pure specifier can only be specified for functions
  5. 怎样将收藏的网址导入到搜狗账号中
  6. 港大黄凯斌:6G时代的边缘智能,香农与图灵的相遇
  7. ESP32基础应用之使用两个ESP32通过阿里云物联网平台实现相互通信
  8. .NET周报【11月第4期 2022-11-30】
  9. open judge 1.6.4
  10. origin双y轴数据散点图显示