leetcode刷题记录

目录

一:动态规划

1. 爬楼梯

 2.强盗抢劫

3.强盗在环形街区抢劫

4.最短路径的和

5.矩阵的总路径数

6:数组中等差递增子区间的个数

 7.分割整数的最大乘积

8. 按平方数来分割整数

9. 最长递增子序列

10.最长数对链

11:最长波动序列个数

12:最长公共子序列

13、最小花费爬楼梯

14、 最长公共子串(连续)

15、 最长公共子串 (不连续)

16、把数字翻译成字符串

17、 兑换零钱

18、连续子数组的最大和

19、最长回文子串

20、编辑距离

二:双指针问题

1、两数之和 II - 输入有序数组

2.平方数之和

3.反转字符串中元音字母

4:回文子串

5:链表是否有环

6、合并区间

 7、最长不重复连续子串 (双指针 + set)

8、接雨水问题

三:贪心思想

1、分饼干问题

2.无重叠区间(求删除个数)

​编辑

3.飞镖气球

4.买卖股票(一次交易)

5.买卖股票(多次交易)

6.种花问题

7、s是否是t子串

8、分糖果问题

9、主持人调度

四:栈与队列

1.判断括号

2:数组中元素与下一个比它大的元素之间的距离(气温问题)

3.下一个更大元素

4、用两个栈实现队列

5、包含min函数的栈

6、滑动窗口的最大值 (双端队列+单调递减)

7、最小的k个数 (堆)

8、寻找第k大的数 (堆)

9、数据流中位数

五:二叉树

1、树高度 num 104

2、判断是否是avl树 num 110

3、树直径(高度变种)num 543

4 二叉树镜像

5、两棵树对应节点求和 num 617

6、是否存在叶子节点到根节点总和对应输入的数字 num112

7、判断t是否是s的子树

8、判断树是否对称 num101

9、树的最小深度

10、所有左叶子节点的和

11、相同节点值的最大路径长度(待定)

12、间隔求和

13、求第二小的节点

14、层次遍历( 一棵树每层节点的平均数)

15、(层序遍历)得到左下角的节点

16、先序遍历(非递归)

17、中序遍历(非递归)

18、修剪二叉树(节点值全部在(L,R)之间)

19、第k小的元素

20、二叉搜索树转换为累加树

21、最底的公共祖先

22、从有序数组中构造二叉查找树

23、 在二叉查找树中寻找两个节点,使它们的和为一个给定值

24、二叉搜索树的最小绝对差

25、二叉搜索树(众树)

26、前缀树(待定更新)

27、二叉树后续遍历(非递归)

28  按之字形顺序打印二叉树

29、 判断是不是二叉搜索树 (中序遍历的结果是不是顺序)

30、判断是不是完全二叉树

31、序列化和反序列化(前序)

32、重建二叉树

六:二分法

1.求开方

2、大于给定元素的最小元素

3、有序数组只有一个数不出现两次,找出这个数。

4、第一个错误版本

5、旋转数组最小数字

6、查找连续数组

7、有序数组二分查找

8、寻找峰值

9、版本号比较

七:搜索问题

1、最短路径(BFS)

2、岛屿最大面积,连续一的个数(DFS)

3、岛屿数量(DFS)

4、好友关系个数(DFS)

5、填充边界的O

6、手机键盘组合(回溯)

7、IP地址划分

8、单词搜索(回溯)

9、给定一个 没有重复 数字的序列,返回其所有可能的全排列。(回溯)

10、有相同元素全排列

11、组合

12、括号生成

13、矩阵递增序列

八:HASH表专题:

1、数组中两个数的和为给定值(双指针和hash表解决)

2、存在重复元素

3、最长和谐子序列

4、最长连续序列(桶排序和set)

5、三数之和

九:字符串专题:

1、两个字符串包含的字符是否完全相同(排序后判断即可)

2、计算一组字符集合可以组成的回文字符串的最大长度(统计每个字符出现次数)

3、同构字符串

4、判断一个整数是否是回文数(转成字符双指针或者求回文的数)

5、统计二进制字符串中连续 1 和连续 0 数量相同的子字符串个数

6、字符串变形

7、最长公共前缀字符串

8、大数加法

9、验证IP地址

十:数组和矩阵专题

1、移动0

2、改变矩阵维度

3、最长连续的1

4、有序矩阵查找

5、一个数组元素在 [1, n] 之间,其中一个数被替换为另一个数,找出重复的数和丢失的数

6、(二分)找出数组中重复的数,数组值在 [1, n] 之间(要求不能修改数组,也不能使用额外的空间。)

7、数组的度

8、对角元素相等的矩阵

9、S[i] 表示一个集合,集合的第一个元素是 A[i],第二个元素是 A[A[i]],如此嵌套下去。求最大的 S[i],指导首尾相等

10、分隔数组,使得对每部分排序后数组就为有序。

11、螺旋矩阵

12、 顺时针旋转矩阵

13、旋转数组

十一:排序专题

1、数组中的第K个最大元素(快排或者堆排序)

2、前k个高频元素

3、根据字符出现频率排序

4、三种颜色国旗排列

十二:位运算

1:统计两个数的二进制表示有多少位不同

2:数组中唯一一个不重复的元素

3:找出数组中缺失的那个数

4:数组中不重复的两个元素

5:判断一个数是不是 2 的 n 次方

6:判断一个数是不是 4 的 n 次方

7:判断一个数的位级表示是否不会出现连续的 0 和 1

8:数字的补数

9:字符串数组最大乘积

10: 统计从 0 ~ n 每个数的二进制表示中 1 的个数

十三:链表

1、链表反转(迭代 + 头插)

2、区间内反转 

3、 链表中的节点每k个一组翻转

4、合并两个有序链表

5、K个链表合并

6、链表是否有环(快慢指针,见双指针)

7、链表环的入口 (相遇之后,一个指针指向最开头)

8、找出倒数最后k个链表节点

9、删除倒数第n个节点 (先走n步找到该节点)

10、两个链表的第一个公共节点

 11、两个链表相加

12、单链表排序

13、 判断链表是否是回文

14、 删除有序链表中重复的元素-I

15、删除有序链表中重复的元素-II 

一:动态规划

1. 爬楼梯

import numpy as np
class Solution:
    def climbStairs(self, n: int) -> int:
        res=np.zeros(n+1,np.int)
        res[0],res[1]=1,1
        for i in range(2,n+1):
            res[i] = res[i - 1] + res[i - 2]
        return int(res[n])

 2.强盗抢劫

题目描述:抢劫一排住户,但是不能抢邻近的住户,求最大抢劫量。定义 dp 数组用来存储最大的抢劫量,其中 dp[i] 表示抢到第 i 个住户时的最大抢劫量。由于不能抢劫邻近住户,如果抢劫了第 i -1 个住户,那么就不能再抢劫第 i 个住户,所以

​编辑

import numpy as np
import math
class Solution:
    #初始化比较麻烦 dp[0]=nums[0] dp[1]=max(nums[0],nums[1]) 
    #递推公式 dp[i]=max(dp[i-1],dp[i-2]+nums[i])
    def rob(self, nums: List[int]) -> int:
        if not nums:
            return 0
        if(len(nums)==1):
            return nums[0]
        dp=np.zeros(len(nums)+1,np.int)
        dp[0]=nums[0]
        dp[1]=max(nums[0],nums[1])
        for index in range(2,len(nums)):
            dp[index]=max(dp[index-1],dp[index-2]+nums[index])
        return int(dp[len(nums)-1])

3.强盗在环形街区抢劫

这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。

import numpy
class Solution:
    def rob(self, nums: List[int]) -> int:
        #一个是从0到n-1,另一个是从1到n
        if not nums:
            return 0
        if(len(nums)==1):
            return nums[0]
        if(len(nums)==2):
            return max(nums[0],nums[1])
        dp1,dp2=numpy.zeros(len(nums),numpy.int),numpy.zeros(len(nums),numpy.int)
        dp1[0]=nums[0]
        dp1[1]=max(nums[1],nums[0])
        for index1 in range(2,len(nums)-1):
            dp1[index1]=max(dp1[index1-1],dp1[index1-2]+nums[index1])
        nums2=nums[1:]
        dp2[0]=nums2[0]
        dp2[1]=max(nums2[0],nums2[1])
        for index2 in range(2,len(nums)-1):
            dp2[index2]=max(dp2[index2-1],dp2[index2-2]+nums2[index2])
        return int(max(dp1[len(nums)-2],dp2[len(nums)-2]))

4.最短路径的和

给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。

示例:

输入:
[
  [1,3,1],
  [1,5,1],
  [4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。

import numpy as np
class Solution:
    def minPathSum(self, grid: List[List[int]]) -> int:
        #初始化 dp[0][0] = grid[0][0];
        #第一行第一列均为之前求和
        #dp[row][col]=min(dp[row-1][col],dp[row][col-1])+grid[row][col]
        rows=len(grid)
        cols=len(grid[0])
        dp=np.zeros((rows,cols),dtype=np.int32)
        dp[0][0] = grid[0][0];
        for row in range(1,rows):
            dp[row][0]=dp[row-1][0]+grid[row][0]
        for col in range(1,cols):
            dp[0][col]=dp[0][col-1]+grid[0][col]
        for row in range(1,rows):
            for col in range(1,cols):
                dp[row][col]=min(dp[row-1][col],dp[row][col-1])+grid[row][col]
        return int(dp[rows-1][cols-1])

5.矩阵的总路径数

import numpy as np
class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        #初始状态第一行第一列全是1
        #dp[i][j]=dp[i-1][j]+dp[i][j-1]
        dp=np.zeros((m,n),np.int32)
        for i in range(m):
            for j in range(n):
                if(i==0 or j==0):
                    dp[i][j]=1
        for i in range(1,m):
            for j in range(1,n):
                dp[i][j]=dp[i-1][j]+dp[i][j-1]
        return int(dp[m-1][n-1])

6:数组中等差递增子区间的个数

如果一个数列至少有三个元素,并且任意两个相邻元素之差相同,则称该数列为等差数列。例如,以下数列为等差数列:

1, 3, 5, 7, 9
7, 7, 7, 7
3, -1, -5, -9
以下数列不是等差数列。

1, 1, 2, 5, 7
数组 A 包含 N 个数,且索引从0开始。数组 A 的一个子数组划分为数组 (P, Q),P 与 Q 是整数且满足 0<=P<Q<N 。如果满足以下条件,则称子数组(P, Q)为等差数组:元素 A[P], A[p + 1], ..., A[Q - 1], A[Q] 是等差的。并且 P + 1 < Q 。

函数要返回数组 A 中所有为等差数组的子数组个数。

import numpy as np
class Solution:
    def numberOfArithmeticSlices(self, A: List[int]) -> int:
        #dp[i] 表示以 A[i] 为结尾的等差递增子区间的个数。
        # dp[2] = 1
        # [0, 1, 2]
        # dp[3] = dp[2] + 1 = 2
        # [0, 1, 2, 3], // [0, 1, 2] 之后加一个 3
        # [1, 2, 3]     // 新的递增子区间
        # dp[4] = dp[3] + 1 = 3
        # [0, 1, 2, 3, 4], // [0, 1, 2, 3] 之后加一个 4
        # [1, 2, 3, 4],    // [1, 2, 3] 之后加一个 4
        # [2, 3, 4]        // 新的递增子区间
        if not A or len(A)<=2:
            return 0
        dp=np.zeros(len(A),np.int)
        dp[0],dp[1]=0,0
        for i in range(2,len(A)):
            if(A[i]-A[i-1]==A[i-1]-A[i-2]):
                dp[i]=dp[i-1]+1        
        return int(sum(dp))

 7.分割整数的最大乘积

import numpy as np
class Solution:
    def integerBreak(self, n: int) -> int:
        #dp[i]表示整数i对应的最大乘积,dp[i]的值应是dp[j]*(i-j),j属于[1,i-1]的最大值,
        #同时注意dp[i]对应的值是经过拆分了的,所以还应判断两个数拆分的情况,即j*(i-j)的值,取最大即可。像2拆成1+1,积是1
        dp=np.zeros(n+1,np.int)
        dp[0],dp[1]=0,0
        for i in range(2,n+1):
            for j in range(0,i):
                dp[i]=max(dp[i],dp[j]*(i-j),j*(i-j))
        return dp[n]

8. 按平方数来分割整数

import numpy as np
import math
class Solution:
    def numSquares(self, n: int) -> int:
        #dp[i]表示i平方和最小所需要的个数
        #dp[i]=min(dp[i],dp[i-j*j]+1)
        dp=np.zeros(n+1,np.int)
        dp[0],dp[1]=0,1
        for i in range(2,n+1):
            dp[i]=i
            for j in range(1,int(math.sqrt(i))+1):
                dp[i]=min(dp[i],dp[i-j*j]+1)
        return int(dp[n])

9. 最长递增子序列

import numpy as np
class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        if not nums:
            return 0
        dp=np.zeros(len(nums),np.int)
        dp[0]=1
        for i in range(1,len(nums)):
            dp[i]=1
            for j in range(0,i):
                if(nums[i]>nums[j]):
                    dp[i]=max(dp[i],dp[j]+1)
        return int(max(dp))

10.最长数对链

给出 n 个数对。 在每一个数对中,第一个数字总是比第二个数字小。

现在,我们定义一种跟随关系,当且仅当 b < c 时,数对(c, d) 才可以跟在 (a, b) 后面。我们用这种形式来构造一个数对链。

给定一个对数集合,找出能够形成的最长数对链的长度。你不需要用到所有的数对,你可以以任何顺序选择其中的一些数对来构造。

示例 :

输入: [[1,2], [2,3], [3,4]]
输出: 2
解释: 最长的数对链是 [1,2] -> [3,4]

import numpy as np
class Solution:
    def findLongestChain(self, pairs: List[List[int]]) -> int:
        #dp[i]表示以第i 个元素结尾最多书对链长度
        #dp[i]=max(dp[j]+1,dp[i])
        #返回列表中最大的
        dp=[0]*len(pairs)
        dp[0]=1
        pairs.sort(key = lambda x:x[1])
        for i in range(1,len(pairs)):
            dp[i]=1
            for j in range(i):
                if(pairs[j][1]<pairs[i][0]):
                    dp[i]=max(dp[j]+1,dp[i])
        return max(dp)

11:最长波动序列个数

import numpy as np
class Solution:
    def wiggleMaxLength(self, nums: List[int]) -> int:
        #首先对list进行去重
        #dp[i]代表下标i之前的最大,如果是当前元素是摆动dp[i]=dp[i-1]+1,否则dp[i]=dp[i-1]
        result=[]
        if not nums:
            return 0
        result.append(nums[0])
        for i in range(1,len(nums)):
            if(nums[i]!=nums[i-1]):
                result.append(nums[i])
        if(len(result)<=2):
            return len(result)
        dp=np.zeros(len(result),np.int)
        dp[0],dp[1]=1,2
        for i in range(2,len(result)):
            if((result[i]-result[i-1])*(result[i-1]-result[i-2])<0):
                dp[i]=dp[i-1]+1
            else:
                dp[i]=dp[i-1]
        return dp[len(result)-1]

12:最长公共子序列

import numpy as  np
class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        m,n=len(text1),len(text2)
        dp=np.zeros((m+1,n+1),np.int)
        for i in range(1,m+1):
            for j in range(1,n+1):
                if(text2[j-1]==text1[i-1]):
                    dp[i][j]=dp[i-1][j-1]+1
                else:
                    dp[i][j]=max(dp[i-1][j],dp[i][j-1])
        return dp[m][n]

13、最小花费爬楼梯

class Solution:
    def minCostClimbingStairs(self , cost: List[int]) -> int:
        # write code here
        
        # 动态规划
        # 1、确定状态
        # 最后一步前必定是在第i-1级台阶 或 第i-2级台阶
        # 原问题:求通过第i级台阶所花费的最少代价
        # 子问题:求通过第i-1级台阶和通过第i-2级台阶之间花费的最少代价
        # 2、转移方程
        # f(i) = min {f(i-1)+cost(i-1), f(i-2)+cost(i-2)}
        # 3、初始条件
        # 因为可以选择直接从台阶0或台阶1开始爬楼梯,所以: f(0)=0, f(1)=0
        # 4、计算顺序
        # 从小到大依次计算
        # 5、编程实现
        n = len(cost)    # 有n级台阶
        f = [0]*(n+1)    # 台阶从0开始,所以索引n为楼梯顶部,即有n+1级台阶
        for i in range(2, n+1): # 按从小到大的顺序计算
            f[i] = min(f[i-1]+cost[i-1], f[i-2]+cost[i-2])
        return f[n]

14、 最长公共子串(连续)


class Solution:
    def LCS(self , str1: str, str2: str) -> str:
        # write code here
        maxLen = 0
        endIndex = 0
        
        f = [[0 for j in range(len(str2)+1)] for i in range(len(str1)+1)]
        
        for i in range(1, len(str1)+1):
            for j in range(1, len(str2)+1):
                if (str1[i-1] == str2[j-1]):
                    f[i][j] = f[i-1][j-1] + 1
                else:
                    f[i][j] = 0
                if maxLen < f[i][j]:
                    maxLen = f[i][j]
                    endIndex = i # end index of the first string
        
        # print(maxLen)
        return str1[endIndex-maxLen:endIndex]

15、 最长公共子串 (不连续)

class Solution:
    def LCS(self , s1: str, s2: str) -> str:
        if s1 is None or s2 is None:
            return '-1'
        len1 = len(s1)
        len2 = len(s2)
        dp = [[''] * (len2 + 1) for i in range(len1 + 1)]
        for i in range(1, len1+1):
            for j in range(1, len2+1):
                if s1[i-1] == s2[j-1]:
                    dp[i][j] = dp[i-1][j-1] + s1[i -1]
                else:
                    dp[i][j] = dp[i][j-1] if len(dp[i][j-1]) > len(dp[i-1][j]) else dp[i-1][j]
        return dp[-1][-1] if dp[-1][-1] != '' else '-1'

16、把数字翻译成字符串

class Solution:
    def solve(self , nums: str) -> int:
        # write code here
        n = len(nums)
        dp = [0] * (n+1)
        dp[0] = 1
        dp[1] = 1 if nums[0] != '0' else 0
        print(dp)
        for i in range(2, n+1):
            if nums[i-1] != '0':
                dp[i] += dp[i-1]
            if '10'<= nums[i-2:i] <= '26':
                dp[i] += dp[i-2]
        return dp[n]

17、 兑换零钱

class Solution:
    def minMoney(self , arr: List[int], aim: int) -> int:
        # 定义a[i]为组成i的最少货币数
        # 状态转移矩阵a[i] = min(a[i-arr[0]], a[i-arr[n]]) + 1
        # 输出值a[aim]
        # 边界条件: a[i]全部初始化为0即可

        a = [0] * (aim + 1)
        for i in range(1, aim+1):
            min_num = 9999
            for coin in arr:
                if i >= coin:
                    min_num = min(min_num, a[i-coin] + 1)
            a[i] = min_num
        return a[aim] if a[aim] < 9999 else -1

18、连续子数组的最大和

class Solution:
    def FindGreatestSumOfSubArray(self , array: List[int]) -> int:
        # 定义a[i]为前i个元素的子数组最大和
        # 状态转移矩阵为 if a[i-1] <0 then a[i] = arr[i]; if a[i-1]>0 then a[i] = a[i-1] + arr[i]
        # 输出max(a[0], a[1], a[m-1])
        # a初始化为0即可
        m = len(array)
        a = [0] * m
        a[0] = array[0]
        for i in range(1, m):
            if a[i-1] < 0:
                a[i] = array[i]
            else:
                a[i] = a[i-1] + array[i]
        return max(a)

19、最长回文子串

class Solution:
    def getLongestPalindrome(self , A: str) -> int:
        # write code here
        n = len(A)
        dp = [ [0] * n for _ in range(n)]
        max_len = 0
        for i in range(n - 1, -1, -1):
            for j in range(i, n):
                if((A[i] == A[j]) and (j - i < 2 or dp[i + 1][j - 1])):
                    dp[i][j] = 1
                    max_len = max(max_len, j - i + 1)
        return max_len

20、编辑距离

class Solution:
    def editDistance(self , str1: str, str2: str) -> int:
        # write code here
        m, n = len(str1), len(str2)
        dp = [[0] * (n+1) for _ in range(m+1)] # 状态转移方程 (m, n) matrix
        # 初始化边界
        for i in range(m+1):
            dp[i][0] = i 
        for j in range(n+1):
            dp[0][j] = j
        for i in range(1, m+1):
            for j in range(1, n+1):
                if str1[i-1] == str2[j-1]:
                    dp[i][j] = dp[i-1][j-1]
                else:
                    dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1])+1
        return dp[m][n]

21、最大正方形

class Solution:
    def maximalSquare(self, matrix):
        max_side = 0
        h,w = len(matrix),len(matrix[0])
        dp = [[0 for i in range(w)] for i in range(h)]
        print('初始化dp',np.array(dp))
        for i in range(h):
            dp[i][0] = int(matrix[i][0])
            max_side = max(max_side, dp[i][0])
        for i in range(w):
            dp[0][i] = int(matrix[0][i])
            max_side = max(max_side, dp[0][i])
        print('初始化边界dp',np.array(dp))
 
        for i in range(1,h):
            for j in range(1,w):
                if matrix[i][j]=='1':
                    dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1])+1
                max_side = max(max_side, dp[i][j])
        print('转移好dp',np.array(dp))
        return max_side**2
 
 
matrix = [["1","0","1","0","0"],
          ["1","0","1","1","1"],
          ["1","1","1","1","1"],
          ["1","0","0","1","0"]]
# matrix = [["0","1"],["1","0"]]
sol = Solution()
res=  sol.maximalSquare(matrix)
print(res)

22、目标和

class Solution:
    def findTargetSumWays(self, nums: List[int], S: int) -> int:
        sumAll = sum(nums)
        if S > sumAll or (S + sumAll) % 2:
            return 0
        target = (S + sumAll) // 2

        dp = [0] * (target + 1)
        dp[0] = 1

        for num in nums:
            for j in range(target, num - 1, -1):
                dp[j] = dp[j] + dp[j - num]
        return dp[-1]

23、分割等和子集

class Solution:
    def canPartition(self, nums: List[int]) -> bool:

        total = sum(nums)
        if total % 2 == 1:      # 总和无法等分
            return False
        
        target = total // 2
        if max(nums) > target:  # 最大值大于总和的一半,无法分割
            return False

        # 初始化
        dp = [False] * (target+1)
        dp[0] = True

        # 状态更新
        for num in nums:
            for j in range(target, num-1, -1):  # 倒序,且j>=num 【j<num时无需更新dp[j]】
                dp[j] |= dp[j-num]      # 可选择当前数字num,也可不选
            
        return dp[target]

24、变态跳台阶

public class Solution {
    public int JumpFloorII(int target) {
            
        if(target==0||target==1 )
            return 1;
        else{
            int sum=0;
            for(int i=1;i<=target;i++)
                sum+=JumpFloorII(target-i);//类比上一题,跳两次是f(n-1)+f(n-2)
            return sum;
        }
      
        
    }
}


# -*- coding:utf-8 -*-
class Solution:
    def jumpFloorII(self, number):
        # write code here
        num = [0, 1]
        while len(num) <= number:
            num.append(2*num[-1])
        return num[number]

25、矩形覆盖

def answer(num):
    dp = np.zeros(num+1)
    dp[1], dp[2] = 1, 2
    for i in  range(num + 1):
        dp[i] = dp[i - 1] + dp[i - 2]
    return dp[-1]

二:双指针问题

1、两数之和 II - 输入有序数组

题目描述:在有序数组中找出两个数,使它们的和为 target。

使用双指针,一个指针指向值较小的元素,一个指针指向值较大的元素。指向较小元素的指针从头向尾遍历,指向较大元素的指针从尾向头遍历。

  • 如果两个指针指向元素的和 sum == target,那么得到要求的结果;
  • 如果 sum > target,移动较大的元素,使 sum 变小一些;
  • 如果 sum < target,移动较小的元素,使 sum 变大一些。

数组中的元素最多遍历一次,时间复杂度为 O(N)。只使用了两个额外变量,空间复杂度为 O(1)。

class Solution(object):
    def twoSum(self, numbers, target):
        """
        :type numbers: List[int]
        :type target: int
        :rtype: List[int]
        """
        list=[]
        first,latest=0,len(numbers)-1
        while(first<latest):
            if(numbers[first]+numbers[latest]==target):
                list.append(first+1)
                list.append(latest+1)
                return list
            elif(numbers[first]+numbers[latest]>target):
                latest=latest-1
            else:
                first=first+1

2.平方数之和

Input: 5
Output: True
Explanation: 1 * 1 + 2 * 2 = 5

题目描述:判断一个非负整数是否为两个整数的平方和。

可以看成是在元素为 0~target 的有序数组中查找两个数,使得这两个数的平方和为 target,如果能找到,则返回 true,表示 target 是两个整数的平方和。

本题和 167. Two Sum II - Input array is sorted 类似,只有一个明显区别:一个是和为 target,一个是平方和为 target。本题同样可以使用双指针得到两个数,使其平方和为 target。

本题的关键是右指针的初始化,实现剪枝,从而降低时间复杂度。设右指针为 x,左指针固定为 0,为了使 02 + x2 的值尽可能接近 target,我们可以将 x 取为 sqrt(target)。

因为最多只需要遍历一次 0~sqrt(target),所以时间复杂度为 O(sqrt(target))。又因为只使用了两个额外的变量,因此空间复杂度为 O(1)。

import math
class Solution:
    def judgeSquareSum(self, c: int) -> bool:
        first,latest=0,int(math.sqrt(c))
        while(first<=latest):
            sum=first*first+latest*latest
            if(sum==c):
                return True
            elif(sum>c):
                latest=latest-1
            else:
                first=first+1
        return False

3.反转字符串中元音字母

class Solution:
    def reverseVowels(self, s: str) -> str:
        first,latest=0,len(s)-1
        char_list=['a','o','e','i','u','A','E','I','O','U']
        temp_list=[]
        #str字符串可以看成数组,但是不能修改
        for ele in s:
            temp_list.append(ele)
        while(first<latest):
            if(temp_list[first] in char_list and temp_list[latest] in char_list):
                temp=temp_list[first]
                temp_list[first]=temp_list[latest]
                temp_list[latest]=temp
                first+=1
                latest-=1
            elif(temp_list[first] in char_list and temp_list[latest] not in char_list):
                latest-=1
            else:
                first+=1
        result=''
        for ele in temp_list:
            result+=ele
        return result

4:回文子串

给定一个非空字符串 s最多删除一个字符。判断是否能成为回文字符串。

class Solution:
    def validPalindrome(self, s: str) -> bool:
        first,late=0,len(s)-1
        for i in range(int(len(s)/2)):
            if(s[i]==s[late-i]):
                continue
            else:
                return self.judge(s,i+1,late-i) or self.judge(s,i,late-i-1)
        return True
        
    def judge(self,s,i,j):
        first,late=i,j
        count=0
        while(first<late):
            if(s[first]==s[late]):
                first+=1
                late-=1
            else:
                return False
        return True

5:链表是否有环

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        p,q=head,head
        if(head==None or head.next==None):
            return False
        while(q.next!=None and p!=None):
            p=p.next
            q=q.next.next
            if(p==q):
                return True
        return False

6、合并区间

class Solution:
    def merge(self , intervals ):
        intervals.sort(key=(lambda elme:elme.start))
        res = []
        for i in range (len(intervals)):
            if res == []:
                res.append(intervals[i])
            else:
                if res[-1].end >= intervals[i].start :
                    res[-1].end = max(intervals[i].end, res[-1].end)
                else:
                    res.append(intervals[i])
        return res

 7、最长不重复连续子串 (双指针 + set)

class Solution:
    def maxLength(self , arr: List[int]) -> int:
        # write code here
        i, j = 0, 0
        val_set = set()
        max_len = 0 
        while i < len(arr) and j < len(arr):
            if (arr[j] not in val_set):
                val_set.add(arr[j])
                max_len = max(max_len, j - i + 1)
                j += 1
            else:
                val_set.remove(arr[i])
                i += 1
        return max_len

8、接雨水问题

class Solution:
    def trap(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        left, right = 0, len(height) - 1
        left_max, right_max = 0, 0
        res = 0
        while left < right:
            if height[left] < height[right]:
                if height[left] >= left_max:
                    left_max = height[left]
                else:
                    res += left_max - height[left]
                left += 1
            else:
                if height[right] >= right_max:
                    right_max = height[right]
                else:
                    res += right_max - height[right]
                right -= 1
                
        return res

9、盛最多水的容器

class Solution:
    def maxArea(self, height: List[int]) -> int:
                maxA = 0
                i = 0 
                j = len(height) - 1
                while i < j:
                    h = min(height[i], height[j]);
                    maxA = max(maxA, h * (j - i));
                    if height[i] < height[j]:
                        i = i + 1
                    else:
                        j = j - 1
                return int(maxA)

10、 最大无序连续子数组

 解法一:
使用排序,然后将排序后的数组与排序前对比,找到最开始和最后元素不同的位置

class Solution(object):
    def findUnsortedSubarray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        left, right = 0, -1
        new_nums = sorted(nums)
        for i in range(len(nums)):
            if nums[i] != new_nums[i]:
                left = i 
                break
        for i in range(len(nums)):
            if nums[i] != new_nums[i]:
                right = i 
        return right - left + 1

解法二
从网上学习到一个非常牛的解法,使用双指针;
(1)左指针处理,逆向遍历数组,找到最后大于已遍历部分的极小值位置,即为最初需要变动的元素
(2)右指针处理,正向向遍历数组,找到最后小于已遍历部分的极大值位置,即为最后需要变动的元素位置

class Solution(object):
    def findUnsortedSubarray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        length = len(nums)
        left, right = 0, -1
        max, min = nums[0], nums[length - 1]
        for i in range(length):
            if nums[i] < max:
                right = i
            else: 
                max = nums[i]
            if nums[length - i - 1] > min:
                left = length - i - 1
            else:
                min = nums[length - i - 1]
        return right - left + 1

11、交换一次使得数字最大

def  change_num():
    id1, id2 = -1, -1
    max_id = len(nums) - 1
    for i in range(len(nums)-1, -1 , -1):
        if(nums[i]  > nums[max_id]):
            max_id = i
        elif(nums[i] < nums[max_id]):
            id1, id2 = i, max_id
    nums[id1],nums[id2] = nums[id2], nums[id1]

if __name__ == '__main__':
    nums = [9, 8, 9 , 6, 5]
    change_num()
    print(nums)

12、丑数

def ugly_num(index):
    p2, p3, p5 = 0,0,0
    res = [1]
    while(len(res) < index):
        num = min(res[p2] * 2, res[p3] * 3, res[p5] * 5)
        res.append(num)
        if(num == res[p2] * 2):
            p2 += 1
        elif(num == res[p3] * 3):
            p3 += 1
        else:
            p5 += 1
    return res[-1]

13、和为s的连续序列

# 双指针,fast 表示 子序列以fast为最右元素
# slow指针判定子序列最左的元素
# 同时从左到右进行遍历
# > tsum 就是减少子序列个数,<tsum 增加子序列个数
# -*- coding:utf-8 -*-
class Solution:
    def FindContinuousSequence(self, tsum):
        # write code here
        n = tsum//2+1
        fast = 2
        slow = 1
        res = []
        while slow<fast and fast <= n:
            curr = (slow+fast)*(fast-slow+1)//2
            if curr == tsum:
                res.append(list(range(slow,fast+1)))
                fast += 1
            elif curr < tsum:
                fast += 1
            else:
                slow += 1
        return res

三:贪心思想

1、分饼干问题

输入: [1,2,3], [1,1]

输出: 1

解释: 
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。

class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        m,n=len(g),len(s)
        g.sort()
        s.sort()
        i,j,count=0,0,0
        while(i<m and j<n):
            if(g[i]<=s[j]):
                count+=1
                i+=1
                j+=1
            else:
                j+=1
        return count

2.无重叠区间(求删除个数)

class Solution:
    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        if not intervals:
            return 0
        intervals.sort(key=lambda x:x[1])
        count=1
        end=intervals[0][1]
        for i in range(1,len(intervals)):
            if(intervals[i][0]>=end):
                count+=1
                end=intervals[i][1]
        return len(intervals)-count

3.飞镖气球

class Solution:
    def findMinArrowShots(self, points: List[List[int]]) -> int:
        #求不重叠区间个数,就是飞镖个数
        if not points:
            return 0
        points.sort(key=lambda x:x[1])
        count=1
        end=points[0][1]
        for i in range(1,len(points)):
            if(points[i][0]>end):
                end=points[i][1]
                count+=1
        return count

4.买卖股票(一次交易)

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        #一次交易
        if not prices:
            return 0
        max_profit=0
        min_price=prices[0]
        for i in range(1,len(prices)):
            min_price=min(prices[i],min_price)
            max_profit=max(max_profit,prices[i]-min_price)
        return max_profit

5.买卖股票(多次交易)

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        #多次交易
        if not prices:
            return 0
        sum_profit=0
        for i in range(1,len(prices)):
            if(prices[i]>prices[i-1]):
                sum_profit+=prices[i]-prices[i-1]
        return sum_profit

6.种花问题

题目描述:flowerbed 数组中 1 表示已经种下了花朵。花朵之间至少需要一个单位的间隔,求解是否能种下 n 朵花。

class Solution:
    def canPlaceFlowers(self, flowerbed: List[int], n: int) -> bool:
        #只需要判断前后即可,防止考虑边界问题,在前后加上[0],只要连续出现在三个[0]就可以种花
        flowerbed=[0]+flowerbed+[0]
        count=0
        for i in range(1,len(flowerbed)-1):
            if(flowerbed[i-1]==0 and flowerbed[i]==0 and flowerbed[i+1]==0):
                flowerbed[i]=1
                count+=1
        if(count>=n):
            return True
        else:
            return False
        

7、s是否是t子串

class Solution:
    def isSubsequence(self, s: str, t: str) -> bool:
        index=-1
        for ele in s:
            index=t.find(ele,index+1)
            if index==-1:
                return False
        return True

8、分糖果问题

class Solution:
    def candy(self , arr ):
        # write code here
        res = [1] * len(arr)
        for i in range(1, len(arr)):
            if arr[i] > arr[i-1]:
                res[i] = res[i-1] + 1
        for i in range(len(arr)-2, -1, -1):
            if arr[i] > arr[i+1]:
                res[i] = max(res[i+1] + 1, res[i])
        return sum(res)

9、主持人调度

class Solution:
    def minmumNumberOfHost(self , n: int, startEnd: List[List[int]]) -> int:
        start = list()
        end =list()
        #分别得到活动起始时间
        for i in range(n):
            start.append(startEnd[i][0])
            end.append(startEnd[i][1])
        #分别对开始和结束时间排序
        start.sort()
        end.sort()
        res = 0
        j = 0
        for i in range(n):
            #新开始的节目大于上一轮结束的时间,主持人不变
            if start[i] >= end[j]: 
                j += 1
            else:
                #主持人增加
                res += 1  
        return res

10、跳跃游戏

class Solution:
    def canJump(self, nums: List[int]) -> bool:
        farest_idx = 0  # 最远可达位置
        for i, jump in enumerate(nums):
            if i <= farest_idx and farest_idx < i + jump:
                farest_idx = i + jump
        return farest_idx >= len(nums) - 1

四:栈与队列

1.判断括号

class Solution:
    def isValid(self, s: str) -> bool:
        stack=[]
        if not s:
            return True
        stack.append(s[0])
        for i in range(1,len(s)):
            if(len(stack) and ((s[i]==')' and stack[-1]=='(') or (s[i]=='}' and stack[-1]=='{') or (s[i]==']' and stack[-1]=='['))):
                stack.pop()
            else:
                stack.append(s[i])
        if(len(stack)>0):
            return False
        return True

2:数组中元素与下一个比它大的元素之间的距离(气温问题)

Input: [73, 74, 75, 71, 69, 72, 76, 73]
Output: [1, 1, 4, 2, 1, 1, 0, 0]
import numpy as np
class Solution:
    def dailyTemperatures(self, T: List[int]) -> List[int]:
        stack=[]
        res=np.zeros(len(T),np.int)
        stack.append(0)
        for cur_index in range(1,len(T)):
            while(len(stack)!=0 and T[cur_index]>T[stack[-1]]):#判断条件
                pre_index=stack.pop()
                res[pre_index]=cur_index-pre_index
            stack.append(cur_index)
        return res

3.下一个更大元素

class Solution:
    def nextGreaterElements(self, nums: List[int]) -> List[int]:
        #遍历列表两次,只将第一次的入队列
        list_len=len(nums)
        res=[-1]*list_len
        stack=[]
        for index in range(2*list_len):
            while(len(stack) and nums[index%list_len]>nums[stack[-1]]):
                pre_index=stack.pop()
                res[pre_index]=nums[index%list_len]
            if(index<len(nums)):
                stack.append(index)
        return res

4、用两个栈实现队列

# -*- coding:utf-8 -*-
class Solution:
    '''
    1.当插入时,直接插入 stack1
    2.当弹出时,当 stack2 不为空,弹出 stack2 栈顶元素,
    如果 stack2 为空,将 stack1 中的全部数逐个出栈入栈 stack2,
    再弹出 stack2 栈顶元素
    '''
    def __init__(self):
        self.stack1= []
        self.stack2= []
    def push(self, node):
        # write code here
        self.stack1.append(node)
    def pop(self):
        # return xx
        if len(self.stack2)==0:
            while(len(self.stack1)!=0):
                self.stack2.append(self.stack1.pop())
        return self.stack2.pop()

5、包含min函数的栈

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.stack = []  #初始化原栈
        self.stack_min = []  #初始化最小值栈
    def push(self, node):
        self.stack.append(node) #往原栈中添加 元素
        if not self.stack_min:    #一开始也往最小值栈中添加元素
            self.stack_min.append(node)
        elif node < self.stack_min[-1]:  #再次添加元素的时候要同最小值栈中元素比较,小于最小值栈中索引-1的对应值,就把node加入;
            self.stack_min.append(node)
        else:
            self.stack_min.append(self.stack_min[-1])  #否则把索引-1的对应值添加到stack_min中
    def pop(self):
        self.stack.pop()                    #弹出栈顶元素则分别获取即可
        self.stack_min.pop()
    def top(self):
        return self.stack[-1]                #栈顶元素从原栈中获取
    def min(self):
        return self.stack_min[-1]              #最小值就直接从最小值栈中获取

6、滑动窗口的最大值 (双端队列+单调递减)

class Solution:
    def maxInWindows(self , num: List[int], size: int) -> List[int]:

        res=[]
        #双端队列
        queue=[]#左边做队首,右边做队尾。做成递减队列

        for i in range(len(num)):
            if len(queue)>0 and i>queue[0]+size-1:#i走到超出原来最大值能覆盖的窗口的位置,那么这个最大值要更新了
                queue.pop(0)

            while len(queue)>0 and num[i]>num[queue[-1]]:#要进队的数数值大,那就删除所有前面小的数,再把它加进去。
                #终止时要加进去的数要么排在第一了,要么就排在比它大的数的后面
                #要加len(queue)>0 这个条件,否则当queue被删空了代码就会出现num[-1]这样索引报错的情况
                queue.pop()
            queue.append(i)

            if i>=size-1:
                res.append(num[queue[0]])               
        return res

7、最小的k个数 (堆)


class Solution:
    def GetLeastNumbers_Solution(self, a, k):
         import heapq
         return heapq.nsmallest(k,a)

8、寻找第k大的数 (堆)

import heapq
class Solution:
    def findKth(self , a: List[int], n: int, K: int) -> int:
         heap = []
         for i in range(n):
             heapq.heappush(heap, -a[i]) # 小顶堆存进去负数
         for i in range(K-1):
             heapq.heappop(heap) #出队前K-1个(最大的)
         return -heapq.heappop(heap) # 相反数

9、数据流中位数

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.li = []

    def Insert(self, num):
        for i in range(len(self.li)):
            if num < self.li[i]:
                self.li.insert(i, num)
                break
        else:
            self.li.append(num)

    def GetMedian(self):
        length = len(self.li)
        if length == 1:
            return self.li[0]
        return (self.li[length//2] + self.li[(length-1)//2]) / 2

10、字符串解码

 
class Solution:
    def decodeString(self, s):
        stack = []  # (str, int) 记录之前的字符串和括号外的上一个数字
        num = 0
        res = ""  # 实时记录当前可以提取出来的字符串
        for c in s:
            if c.isdigit():
                num = num * 10 + int(c)
            elif c == "[":
                stack.append((res, num))
                res, num = "", 0
            elif c == "]":
                top = stack.pop()
                print('===top:', top)
                res = top[0] + res * top[1]
                print('==res:', res)
            else:
                res += c
        return res
 
# s = "3[a]2[bc]"
s = "3[a2[c]]"
sol = Solution()
res = sol.decodeString(s)
print('res:', res)

11、LRU缓存机制

class Solution:
    def LRU(self , operators: List[List[int]], k: int) -> List[int]:
        stack = [] #有序
        div_kv = {} #无序
        res = []  #结果
        for op in operators:
            if op[0] == 1:#set操作
                if len(stack) >= k: 
                    del div_kv[stack.pop(0)]
                if op[1] in div_kv: 
                    stack.remove(op[1])
                stack.append(op[1])
                div_kv[op[1]] = op[2] 
            elif op[0] == 2:#get操作
                if op[1] not in div_kv:
                    res.append(-1)
                else:
                    stack.remove(op[1])
                    stack.append(op[1])
                    res.append(div_kv[op[1]])
        return res

11、栈的压入和弹出

# -*- coding:utf-8 -*-
class Solution:
    def IsPopOrder(self, pushV, popV):
        # write code here
        if not pushV or len(pushV) != len(popV):
            return False
        stack = []
        for ii in pushV:
            stack.append(ii)
            while len(stack) and stack[-1] == popV[0]:
                stack.pop()
                popV.pop(0)
                
        if len(stack):
            return False
        return True

五:二叉树

1、树高度 num 104

class TreeNode(object):
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        if not root:
            return 0
        else:
            LD=self.maxDepth(root.left)
            RD=self.maxDepth(root.right)
            return max(LD,RD)+1

2、判断是否是avl树 num 110

class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        def get_depth(root):
            if not  root:
                return 0
            else:
                LD=get_depth(root.left)
                RD=get_depth(root.right)
                return max(LD,RD)+1
        if not root:
            return True
        LD=get_depth(root.left)
        RD=get_depth(root.right)
        if(abs(LD-RD)>1):
            return False
        return self.isBalanced(root.left) and self.isBalanced(root.right)

3、树直径(高度变种)num 543

 给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。

class Solution:
    def diameterOfBinaryTree(self, root: TreeNode) -> int:
        self.max=0
        #最长路径未必经过根节点
        def get_depth(root):
            if not root:
                return 0
            else:
                LD=get_depth(root.left)
                RD=get_depth(root.right)
                self.max=max(LD+RD,self.max)
                return max(LD,RD)+1
        if not root:
            return 0
        else:
            get_depth(root)
            return self.max

4 二叉树镜像

class Solution:
    def invertTree(self, root: TreeNode) -> TreeNode:
        if  root:
            self.invertTree(root.left)
            self.invertTree(root.right)
            temp=root.left
            root.left=root.right
            root.right=temp
        return root

5、两棵树对应节点求和 num 617

class Solution:
    def mergeTrees(self, t1: TreeNode, t2: TreeNode) -> TreeNode:
        #修改之前的树,先序遍历
        if not t1:
            return t2
        if not t2:
            return t1
        else:
            t1.val+=t2.val
            t1.left=self.mergeTrees(t1.left,t2.left)
            t1.right=self.mergeTrees(t1.right,t2.right)
            return t1

6、是否存在叶子节点到根节点总和对应输入的数字 num112

class Solution:
    def hasPathSum(self, root: TreeNode, sum: int) -> bool:
        #与剑指offer一题目类似
        if(not root):
            return False
        if(not root.left and not root.right and root.val==sum):
            return True
        sum-=root.val   
        return self.hasPathSum(root.left,sum) or self.hasPathSum(root.right,sum)

7、判断t是否是s的子树

class Solution:
    def isSubtree(self, root: [TreeNode], subRoot: [TreeNode]) -> bool:
        def is_equal(root, subRoot):
            if not root and not subRoot:
                return True
            if not subRoot or not root:
                return False
            if (root.val == subRoot.val):
                return is_equal(root.left, subRoot.left) and is_equal(root.right, subRoot.right)

        if not root:
            return False

        return is_equal(root, subRoot) or self.isSubtree(root.left, subRoot) or self.isSubtree(root.right, subRoot)

8、判断树是否对称 num101

class Solution:
    def isSymmetric(self, root: TreeNode) -> bool: 
        def dfs(p,q):
            #判断子树是否相同
            if(not p and not q):
                return True
            if(not p or not q):
                return False
            if(p.val==q.val):
                return dfs(p.left,q.right) and dfs(p.right,q.left)
        if not root:
            return True
        return dfs(root.left,root.right)

9、树的最小深度

class Solution:
    def minDepth(self, root: TreeNode) -> int:
        #要注意如果根节点的左或右子树为空的话是构不成子树的。而最小深度是要求从根节点到子树的
        if not root:
            return 0
        elif not root.left:
            return self.minDepth(root.right)+1
        elif not root.right:
            return self.minDepth(root.left)+1
        else:   
            left=self.minDepth(root.left)
            right=self.minDepth(root.right)
            return min(left,right)+1

10、所有左叶子节点的和

class Solution:
    def sumOfLeftLeaves(self, root: TreeNode) -> int:
        #有点疑惑
        if not root:
            return 0
        sum=0
        if root.left and  not root.left.left and not root.left.right:
            sum=sum+root.left.val+self.sumOfLeftLeaves(root.right)
        else:
            sum=sum+self.sumOfLeftLeaves(root.right)+self.sumOfLeftLeaves(root.left)
        return sum

11、相同节点值的最大路径长度(待定)

12、间隔求和

class Solution:
    def rob(self, root: TreeNode) -> int:
        #后序遍历,树dp,dp[0]代表不抢该节点可以获取的最大值,dp[1]代表抢该节点
        def  dfs(root):
            if not root:
                return [0,0]
            left=dfs(root.left)
            right=dfs(root.right)
            result=[0,0]
            result[0]=max(left[0],left[1])+max(right[0],right[1])
            result[1]=root.val+left[0]+right[0]
            return result
        res=dfs(root)
        return max(res[0],res[1])

13、求第二小的节点

class Solution:
    result=[]
    def findSecondMinimumValue(self, root: TreeNode) -> int:
        def pre_order(root,val_list):
            if(root):
                pre_order(root.left,val_list)
                pre_order(root.right,val_list)
                val_list.append(root.val)
        val_list=[]
        pre_order(root,val_list)
        val_list.sort()
        val_2 = list(set(val_list))
        val_2.sort(key = val_list.index)
        if(len(val_2)<2):
            return -1
        return val_2[1]

14、层次遍历( 一棵树每层节点的平均数)

class Solution:
    def averageOfLevels(self, root: TreeNode) -> List[float]:
        queue,result=[],[]
        queue.append(root)
        while(len(queue)):
            length,temp_len=len(queue),len(queue)
            sum=0
            while(length):
                length-=1
                p=queue.pop(0)
                sum+=p.val
                if(p.left):
                    queue.append(p.left)
                if(p.right):
                    queue.append(p.right)
            result.append(sum/temp_len)
        return result

15、(层序遍历)得到左下角的节点

class Solution:
    def findBottomLeftValue(self, root: TreeNode) -> int:
        queue=[]
        queue.append(root)
        while(len(queue)):
            #遍历完一层将结果记录下来
            length,temp_len=len(queue),len(queue)
            level_res=[]
            while(length):
                length-=1
                p=queue.pop(0)
                level_res.append(p.val)
                if(p.left):
                    queue.append(p.left)
                if(p.right):
                    queue.append(p.right)
        return level_res[0]

16、先序遍历(非递归)

class Solution:
    def preorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return []
        stack=[]
        stack.append(root)
        result=[]
        while(len(stack)>0):
            temp=stack.pop()
            result.append(temp.val)
            if(temp.right):
                stack.append(temp.right)
            if(temp.left):
                stack.append(temp.left)
        return result

17、中序遍历(非递归)

class Solution:
    def inorderTraversal(self, root: TreeNode) -> List[int]:
        stack=[]
        p=root
        result=[]
        while(p or len(stack)):
            if(p):
                stack.append(p)
                p=p.left
            else:
                p=stack.pop()
                result.append(p.val)
                p=p.right
        return result

18、修剪二叉树(节点值全部在(L,R)之间)

class Solution:
    def trimBST(self, root: TreeNode, L: int, R: int) -> TreeNode:
        if not root:
            return None
        elif(root.val>R):
            return self.trimBST(root.left,L,R)
        elif(root.val<L):
            return self.trimBST(root.right,L,R)
        else:         
            root.left=self.trimBST(root.left,L,R)
            root.right=self.trimBST(root.right,L,R)
            return root

19、第k小的元素

class Solution:
    def kthSmallest(self, root: TreeNode, k: int) -> int:
        self.count=0
        self.res=0
        def in_order(root):
            if not root:
                return
            else:
                in_order(root.left)
                self.count+=1
                if(self.count==k):
                    self.res=root.val
                in_order(root.right)
        in_order(root)
        return self.res

20、二叉搜索树转换为累加树

class Solution:
    def convertBST(self, root: TreeNode) -> TreeNode:
        self.sum=0
        def in_order(root):
            if root:
                in_order(root.right)
                self.sum+=root.val
                root.val=self.sum
                in_order(root.left)
                return root
        return in_order(root)

21、最底的公共祖先

class Solution:
    def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode':
        if not root:
            return None
        if(p==root):
            return p
        if(q==root):
            return q
        L=self.lowestCommonAncestor(root.left,p,q)
        R=self.lowestCommonAncestor(root.right,p,q)
        if( L and R):
            return root
        elif not R:
            return L
        else:
            return R

22、从有序数组中构造二叉查找树

class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
        def mid_build(ele_list,l,r):
            if(l>r):
                return None
            mid=(l+r)>>1
            root=TreeNode(nums[mid])
            root.left=mid_build(ele_list,l,mid-1)
            root.right=mid_build(ele_list,mid+1,r)
            return root
        if not nums:
            return 
        return mid_build(nums,0,len(nums)-1)

23、 在二叉查找树中寻找两个节点,使它们的和为一个给定值

class Solution:
    def findTarget(self, root: TreeNode, k: int) -> bool:
        res_set=set()
        visit=[]
        def in_order(root,target):
            if root:
                if(root.val not in res_set):
                    res_set.add(root.val)
                if(k-root.val in res_set and k!=2*root.val):
                    return True
                L=in_order(root.left,target)
                R=in_order(root.right,target)
                return L or R
        return in_order(root,k)

24、二叉搜索树的最小绝对差

class Solution:
    def getMinimumDifference(self, root: TreeNode) -> int:
        min_value=1000
        res=[]
        stack=[]
        p=root
        while(p or len(stack)):
            if(p):
                stack.append(p)
                p=p.left
            else:
                p=stack.pop()
                if(len(res)):
                    min_value=min(min_value,abs(p.val-res[-1]))
                res.append(p.val)
                p=p.right
        return min_value

25、二叉搜索树(众树)

class Solution:
    def findMode(self, root: TreeNode) -> List[int]:
        res_dict={}
        res=[]
        def in_order(root):
            if root:
                in_order(root.left)
                if(root.val not in res_dict):
                    res_dict[root.val]=1
                else:
                    res_dict[root.val]+=1
                in_order(root.right)
        in_order(root)
        if not root:
            return 
        res_list=sorted(res_dict.items(),key=lambda x:x[1],reverse=True)
        num=res_list[0][1]
        res.append(res_list[0][0])
        for ele in res_list[1:]:
            if(ele[1] == num):
                res.append(ele[0])
        return res

26、前缀树(待定更新)

27、二叉树后续遍历(非递归)

class Solution:
    def postorderTraversal(self, root):  #迭代法1
        if not root:
            return []
        stack = [root]
        result = []
        while stack:
            node = stack.pop()
            # 中结点先处理
            result.append(node.val)
            # 左孩子先入栈
            if node.left:
                stack.append(node.left)
            # 右孩子后入栈
            if node.right:
                stack.append(node.right)
        # 将最终的数组翻转
        return result[::-1]

28  按之字形顺序打印二叉树

# 层序遍历的时候加个反向的flag。
class Solution:
    def Print(self , pRoot: TreeNode) -> List[List[int]]:
        # write code here
        if not pRoot: return []
        quene = []
        res = []
        quene.append(pRoot)
        reverseFlag = True
        while quene:
            row = []
            for i in range(len(quene)):
                node = quene.pop(0)
                row.append(node.val)
                if node.left:
                    quene.append(node.left)
                if node.right:
                    quene.append(node.right)
            reverseFlag = not reverseFlag
            if reverseFlag:
                res.append(row[::-1])
            else:
                res.append(row)
        return res

29、 判断是不是二叉搜索树 (中序遍历的结果是不是顺序)

class Solution:

    def inOrderTraversal(self, root: TreeNode) -> List[int]:
        if root is None:
            return []
        return self.inOrderTraversal(root.left) + [root.val] + self.inOrderTraversal(root.right)

    def isValidBST(self , root: TreeNode) -> bool:
        res = self.inOrderTraversal(root)
        if len(res) <= 1:
            return True
        for i in range(len(res)-1):
            if res[i] >= res[i+1]:
                return False
        return True

30、判断是不是完全二叉树

class Solution:
    def isCompleteTree(self , root: TreeNode) -> bool:
        if root is None:
            return True
        ret = [root]
        while ret:
            cur = ret.pop(0)
            if cur:
                ret.append(cur.left)
                ret.append(cur.right)
            else:
                break
        for i in ret:
            if i:
                return False
        return True

31、序列化和反序列化(前序)

class Solution:
    str1 = []
    def Serialize(self, root):
        # write code here
        if root == None:
            self.str1.append("#")
            return self.str1
        self.str1.append(str(root.val))
        self.Serialize(root.left)
        self.Serialize(root.right)
        return self.str1
    start=-1
    def Deserialize(self, s):
        # write code here
        self.start=self.start+1;
        if self.start>=len(s) or s[self.start]=="#" or s==None :return ;
        cur=TreeNode(int(s[self.start]))
        cur.left=self.Deserialize(s)
        cur.right=self.Deserialize(s)
        return cur

32、重建二叉树

class Solution:
    def reConstructBinaryTree(self , pre: List[int], vin: List[int]) -> TreeNode:
        # write code here
        if not pre or not vin:
            return None
        #构造根节点,寻找左右子树的分界线
        root = TreeNode(pre[0])
        n = vin.index(pre[0])
        #构造左右子树,递归调用
        root.left = self.reConstructBinaryTree(pre[1:n + 1], vin[:n])
        root.right = self.reConstructBinaryTree(pre[n + 1:], vin[n + 1:])
        #返回根节点
        return root

32、前缀树

 
class Trie:
 
    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.root = {}
        self.word_end = -1
 
    def insert(self, word):
        """
        Inserts a word into the trie.
        """
        curNode = self.root
        for c in word:
            if c not in curNode:
                curNode[c] = {}
            curNode = curNode[c]
        curNode[self.word_end] = True
        # print('==curNode:', curNode)
 
 
    def search(self, word):
        """
        Retu
        rns if the word is in the trie.
        """
        curNode = self.root
        for c in word:
            if c not in curNode:
                return False
            curNode = curNode[c]
        if self.word_end not in curNode:
            return False
        return True
 
 
    def startsWith(self, prefix):
        """
        Returns if there is any word in the trie that starts with the given prefix.
        """
        curNode = self.root
        for c in prefix:
            if c not in curNode:
                return False
            curNode = curNode[c]
        return True
 
word = 'apple'
prefix = 'ad'
obj = Trie()
obj.insert(word='apple')
obj.insert(word='add')
# obj.insert(word='app')
print('tree:', obj.root)
param_2 = obj.search(word)
print('search res:', param_2)
param_3 = obj.startsWith(prefix)
print('==param_3:', param_3)

六:二分法

1.求开方

lass Solution:
    def mySqrt(self, x: int) -> int:
        low,high=0,x
        if x==0 or x==1:
            return x
        while(low<high):
            mid=(low+high)>>1
            val=mid*mid
            val_1=(mid+1)*(mid+1)
            if(val<=x<val_1):
                return mid
            elif(val>=x):
                high=mid
            else:
                low=mid

2、大于给定元素的最小元素

class Solution:
    def nextGreatestLetter(self, letters: List[str], target: str) -> str:
        #不需要等于,返回low
        low,high=0,len(letters)-1
        while(low<high):
            mid=(low+high)>>1
            if(target<letters[mid]):
                high=mid-1
            else:
                low=mid+1
        if(letters[low]<=target):
            return letters[(low+1)%len(letters)]    
        return letters[low]

3、有序数组只有一个数不出现两次,找出这个数。

class Solution:
    def singleNonDuplicate(self, nums: List[int]) -> int:
        low,high=0,len(nums)-1
        while(low<high):
            mid=(low+high)>>1
            if(mid%2):
                mid-=1
            if(nums[mid+1]==nums[mid]):
                low=mid+2
            else:
                high=mid
        return nums[low]

4、第一个错误版本

class Solution:
    def firstBadVersion(self, n):
        """
        :type n: int
        :rtype: int
        """
        low,high=1,n
        while(low<high):
            mid=(low+high)>>1
            if(not isBadVersion(mid)):
                low=mid+1
            else:
                high=mid-1
        if isBadVersion(low):
            return low
        return low+1

5、旋转数组最小数字

class Solution:
    def findMin(self, nums: List[int]) -> int:
        low,high=0,len(nums)-1
        if(len(nums)==1):
            return nums[0]
        while(nums[low]>nums[high]):
            mid=(low+high)>>1
            if(high<low):
                break
            elif(nums[mid]>nums[low]):
                low=mid
            else:
                high=mid
        if(nums[low]<nums[low-1]):
            return nums[low]
        return nums[low+1]

6、查找连续数组

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        if(target not in nums):
            return [-1,-1]
        nums=list(map(float,nums))
        def bin_search(nums, target):
            low, high = 0, len(nums) - 1
            while (low < high):
                mid = int((low + high) / 2)
                if (target == nums[mid]):
                    return mid
                elif (target > nums[mid]):
                    low = mid + 1
                else:
                    high = mid - 1
            return low
        a,b=target-0.5,target+0.5
        i,j=bin_search(nums,a),bin_search(nums,b)
        if(nums[i]!=target):
            i=i+1
        if(nums[j]!=target):
            j=j-1
        return [i,j]

7、有序数组二分查找

class Solution:
    def search(self , nums, target):
        # write code here
        length = len(nums)
        left = 0
        right = length
        if length < 1:
            return -1 
        while  left <= right:
            mid = int((left + right) / 2)
            if nums[mid] == target:
                return mid
            elif nums[mid] < target:
                left = mid + 1
            else:
                right = mid - 1
        return -1

8、寻找峰值

class Solution:
    def findPeakElement(self , nums: List[int]) -> int:
        left,right = 0,len(nums)-1
        while left<right:
            mid = (left+right)//2
            if nums[mid] < nums[mid+1]: left = mid+1
            else: right = mid
        return left

9、版本号比较

def compare(s1, s2):
	s1_val_list, s2_val_list = s1.split('.'),  s2.split('.')
	len_s1, len_s2 = len(s1_val_list), len(s2_val_list)
	max_len = max(len_s1, len_s2)
	if (len_s1 < max_len):
		s1_val_list += [0] * (max_len - len_s1)
	if (len_s2 < max_len):
		s2_val_list += [0] * (max_len - len_s2)
	for i in range(max_len):
		n1 = int(s1_val_list[i])
		n2 = int(s2_val_list[i])
		if(n1 > n2):
			return 1
		if(n1 < n2):
			return 0

versions = ['4.8', '1.7.1', '4.1.9', '5.0.0.0']
for i in range(len(versions)-1, -1, -1):
	for j in range(i):
		if(compare(versions[j], versions[j+1])):
			versions[j], versions[j+1] = versions[j+1], versions[j]

七:搜索问题

1、最短路径(BFS)

class Solution:
    def shortestPathBinaryMatrix(self, grid: List[List[int]]) -> int:
        #bfs
        queue=[]
        rows,cols=len(grid),len(grid[0])
        if(rows==1 and cols==1 and grid[0][0]==0):
            return 1
        if(grid[0][0]==1 or grid[rows-1][cols-1]==1):
            return -1
        queue.append([0,0])
        level=1
        grid[0][0]=1
        next_step=[[0,1],[1,0],[0,-1],[-1,0],[-1,-1],[1,1],[1,-1],[-1,1]]
        while(queue):
            length=len(queue)
            while(length):
                cur=queue.pop(0)
                x=cur[0]
                y=cur[1]
                length-=1
                if(x==rows-1 and y==cols-1):
                    return level
                for i in range(len(next_step)):
                    x+=next_step[i][0]
                    y+=next_step[i][1]
                    if(x>=0 and x<rows and y>=0 and y<cols and grid[x][y]==0): 
                        queue.append([x,y])
                        grid[x][y]=1
                    else:
                        continue
            level+=1
        return -1

2、岛屿最大面积,连续一的个数(DFS)

class Solution:
    def maxAreaOfIsland(self, grid: List[List[int]]) -> int:
        def dfs(grid,i,j):
            if(i<0 or i>=len(grid) or j<0 or j>=len(grid[0]) or grid[i][j]==0):
                return 0
            grid[i][j]=0
            count=1
            count += dfs(grid, i+1, j);
            count += dfs(grid, i-1, j);
            count += dfs(grid, i, j+1);
            count += dfs(grid, i, j-1);
            return count
        max_count=0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if(grid[i][j]==0):
                    continue
                else:
                    max_count=max(max_count,dfs(grid,i,j))
        return max_count

3、岛屿数量(DFS)

class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        def dfs(grid,i,j):
            if(i<0 or i>=len(grid) or j<0 or j>=len(grid[0]) or grid[i][j]=='0' ):
                return
            grid[i][j]='0'
            dfs(grid,i+1,j)
            dfs(grid,i,j+1)
            dfs(grid,i-1,j)
            dfs(grid,i,j-1)
        count=0
        for i in range(len(grid)):
            for j in range(len(grid[0])):
                if(grid[i][j]=='1'):
                    count+=1
                    dfs(grid,i,j)
        return count

4、好友关系个数(DFS)

class Solution:
    def findCircleNum(self, M: List[List[int]]) -> int:
        #最基本的dfs
        visited=[0]*len(M)
        def dfs(i):
            for j in range(len(M)):
                if(visited[j]==0 and M[i][j]==1):
                    visited[j]=1
                    dfs(j)
        count=0
        for i in range(len(M)):
            if(visited[i]==0):
                count+=1
                dfs(i)
        return count

5、填充边界的O

class Solution:
    def solve(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        #对边界的那些‘O’进行dfs改变值,t
        def dfs(grad,i,j):
            if(i<0 or i>=len(board) or j<0 or j>=len(board[0]) or board[i][j]!='O'):
                return 
            board[i][j]='-'
            dfs(board,i-1,j)
            dfs(board,i+1,j)
            dfs(board,i,j-1)
            dfs(board,i,j+1)
        for i in range(len(board)):
            for j in range(len(board[0])):
                if((i==0 or i==len(board)-1 or j==0 or j==len(board[0])-1) and board[i][j]=='O'):
                    dfs(board,i,j)
        for i in range(len(board)):
            for j in range(len(board[0])):
                if(board[i][j]=='O'):
                    board[i][j]='X'
                if(board[i][j]=='-'):
                    board[i][j]='O'

6、手机键盘组合(回溯)

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        if not digits:
            return []
        res=[]
        hash_table={'2':'abc','3':'def','4':'ghi','5':'jkl','6':'mno','7':'pqrs','8':'tuv','9':'wxyz'}
        def dfs(index,cur_str):
            if(index==len(digits)):
                res.append(cur_str)
                return
            val=hash_table[digits[index]]
            for i in range(len(val)):
                cur_str=cur_str+val[i]
                dfs(index+1,cur_str)
                cur_str=cur_str[0:-1]
        dfs(0,'')
        return res

7、IP地址划分

class Solution:
    def restoreIpAddresses(self, s: str) -> List[str]:
        res = []
        for i in range(1, 4):
            for j in range(i+1, i + 4):
                for k in range(j+1, j + 4):
                    num_1, num_2, num_3, num_4 = s[0:i], s[i:j], s[j:k], s[k:len(s)]
                    if(len(s)-k>=4):
                        continue
                    try:
                        if((num_1.startswith('0') and len(num_1)!=1) or (num_2.startswith('0') and len(num_2)!=1) or (num_3.startswith('0') and len(num_3)!=1) or (num_4.startswith('0') and len(num_4)!=1)):
                            continue
                        if (0 <= int(num_1) <= 255 and 0 <=int(num_2) <= 255 and 0 <= int(num_3) <= 255 and 0 <= int(num_4) <= 255):
                            res.append(num_1 + '.' + num_2 + '.' + num_3 + '.' + num_4)
                    except:
                        continue
        return res

8、单词搜索(回溯)

class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        self.rows,self.cols=len(board),len(board[0])
        def search(i,j,index):
            if(index>=len(word)):
                return True
            if(i>=self.rows or j>=self.cols or i<0 or j<0 or board[i][j]!=word[index]):
                return False
            board[i][j]+='1'#改变之前的,是为了防止同一个单元格的元素多次使用,比如说eae,ea就可以走出eae
            res=(search(i,j+1,index+1) or search(i+1,j,index+1) or search(i,j-1,index+1)or search(i-1,j,index+1))
            board[i][j]=board[i][j][:-1]#改为原来的值
            return res
        for i in range(len(board)):
            for j in range(len(board[0])):
                if(board[i][j]==word[0]):
                    if(search(i,j,0)):
                        return True
        return False

9、给定一个 没有重复 数字的序列,返回其所有可能的全排列。(回溯)

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        #啊哈算法全排列,浅拷贝和深拷贝
        temp_list=[0]*len(nums)
        book=[0]*len(nums)
        res_list=[]
        def dfs(step):
            if(step==len(nums)):
                res_list.append(temp_list.copy())
                return 
            for i in range(len(nums)):
                if(book[i]==0):
                    temp_list[step]=nums[i]
                    book[i]=1
                    dfs(step+1)
                    book[i]=0
        dfs(0)
        return res_list

10、有相同元素全排列

class Solution:
    def permuteUnique(self, nums: List[int]) -> List[List[int]]:
        #啊哈算法全排列,浅拷贝和深拷贝
        temp_list=[0]*len(nums)
        book=[0]*len(nums)
        res_list=[]
        def dfs(step):
            if(step==len(nums)):
                res_list.append(temp_list.copy())
                return 
            for i in range(len(nums)):
                if(book[i]==0):
                    temp_list[step]=nums[i]
                    book[i]=1
                    dfs(step+1)
                    book[i]=0
        dfs(0)
        set_list=[]
        for ele in res_list:
            if ele not in set_list:
                set_list.append(ele)
        return set_list

11、组合

class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        temp_val = []
        res_list = []
        def dfs(step):
            if (len(temp_val) == k):
                res_list.append(temp_val.copy())
                return
            else:
                for index in range(step+1, n+1):
                    temp_val.append(index)
                    dfs(index)
                    temp_val.pop()
        dfs(0)
        return res_list

12、括号生成

class Solution:
    def recursion(self, string, res, length):
        tmp = "".join(string)
        if len(string) == length:
            res.add(tmp)
            return res
        
        for i in range(len(string)):
            string.insert(i, ')')
            string.insert(i, '(')
            self.recursion(string, res, length)
            string.pop(i)
            string.pop(i)
        
    def generateParenthesis(self , n):
        # write code here
        length = 2*n
        string = ['(',')']
        res = set()
        self.recursion(string, res, length)
        res = list(res)
        return res

13、矩阵递增序列

class Solution:
    global dirs
    #记录四个方向
    dirs = [[-1, 0], [1, 0], [0, -1], [0, 1]] 
    global n, m
    #深度优先搜索,返回最大单元格数
    def dfs(self, matrix:List[List[int]], dp: List[List[int]], i:int, j:int) :
        if dp[i][j] != 0:
            return dp[i][j]
        dp[i][j] += 1
        for k in range(4):
            nexti = i + dirs[k][0]
            nextj = j + dirs[k][1]
            #判断条件
            if  nexti >= 0 and nexti < n and nextj >= 0 and nextj < m and matrix[nexti][nextj] > matrix[i][j]:
                dp[i][j] = max(dp[i][j], self.dfs(matrix, dp, nexti, nextj) + 1)
        return dp[i][j]
    
    def solve(self , matrix: List[List[int]]) -> int:
        global n,m
        #矩阵不为空
        if len(matrix) == 0 or len(matrix[0]) == 0:
            return 0
        res = 0
        n = len(matrix)
        m = len(matrix[0])
        #i,j处的单元格拥有的最长递增路径
        dp = [[0 for col in range(m)] for row in range(n)]  
        for i in range(n):
            for j in range(m):
                #更新最大值
                res = max(res, self.dfs(matrix, dp, i, j)) 
        return res

14、课程表 (拓扑排序)

 
class Solution:
    def canFinish(self, numCourses, prerequisites):
        indegrees = [0] * numCourses  # 入度列表
        print('==indegrees:', indegrees)
        adjacency = [[] for i in range(numCourses)]  # 邻接列表 存储节点的下一个节点
        print('=adjacency:', adjacency)
        #得到入度和每个课程的邻接列表
        for cur, pre in prerequisites:
            indegrees[cur] += 1
            adjacency[pre].append(cur)
        print('====indegrees:', indegrees)
        print('====adjacency:', adjacency)
 
        quene = []
        # 如果度为0 就进入队列
        for i in range(len(indegrees)):
            if indegrees[i] == 0:
                quene.append(i)
        print('==quene:', quene)
        num_nodes = 0
        while quene:
            node = quene.pop(0)
            num_nodes += 1
            for next_node in adjacency[node]:
                indegrees[next_node] -= 1  # 找出下一个点相应的度-1
                if indegrees[next_node] == 0:  # 入度为0
                    quene.append(next_node)
        print('==num_nodes:', num_nodes)
        return num_nodes == numCourses
 

numCourses, prerequisites = 6, [[3, 0], [3, 1], [4, 1], [4, 2], [5, 3], [5, 4]]
sol = Solution()
res = sol.canFinish(numCourses, prerequisites)
print('res:', res)

 17、课程表 (记录路径)

 
class Solution:
    def canFinish(self, numCourses, prerequisites):
        indegrees = [0] * numCourses  # 入度列表
        print('==indegrees:', indegrees)
        adjacency = [[] for i in range(numCourses)]  # 邻接列表
        print('=adjacency:', adjacency)
        #得到入度和每个课程的邻接列表
        for cur, pre in prerequisites:
            indegrees[cur] += 1
            adjacency[pre].append(cur)
        print('====indegrees:', indegrees)
        print('====adjacency:', adjacency)
 
        quene = []
        # 如果度为0 就进入队列
        for i in range(len(indegrees)):
            if indegrees[i] == 0:
                quene.append(i)
        print('==quene:', quene)
        num_nodes = 0
        learn_node = []
        while quene:
            node = quene.pop(0)
            print('=======node', node)
            learn_node.append(node)
            num_nodes += 1
            for next_node in adjacency[node]:
                indegrees[next_node] -= 1  # 找出下一个点相应的度-1
                if indegrees[next_node] == 0:  # 入度为0
                    quene.append(next_node)
        print('==num_nodes:', num_nodes)
        return learn_node if num_nodes == numCourses else []
 
# numCourses, prerequisites = 2, [[1, 0]]
# numCourses, prerequisites = 2, [[1, 0], [0, 1]]
numCourses, prerequisites = 6, [[3, 0], [3, 1], [4, 1], [4, 2], [5, 3], [5, 4]]
sol = Solution()
res = sol.canFinish(numCourses, prerequisites)
print('res:', res)

18、求1+2+3+...+n

class Solution {
public:
    int Sum_Solution(int n) {
        n && (n += Sum_Solution(n - 1));
        return n;
    }
};

八:HASH表专题:

1、数组中两个数的和为给定值(双指针和hash表解决)

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        res=[]
        return_list=[]
        for i in range(len(nums)):
            if((target-nums[i]) in nums and nums.index(target-nums[i])!=i):
                return [i,nums.index(target-nums[i])]
        return []

2、存在重复元素

class Solution:
    def containsDuplicate(self, nums: List[int]) -> bool:
        res_set=set()
        for i in range(len(nums)):
            if(nums[i] not in res_set):
                res_set.add(nums[i])
            else:
                return True
        return False

3、最长和谐子序列

class Solution:
    def findLHS(self, nums: List[int]) -> int:
        if not nums:
            return 0
        res_dict={}
        max_res=0
        for i in range(len(nums)):
            if(nums[i] not in res_dict):
                res_dict[nums[i]]=1
            else:
                res_dict[nums[i]]+=1
        for i in range(1,len(nums)):
            if( (nums[i]-1) in res_dict):
                max_res=max(max_res,res_dict[nums[i]]+res_dict[nums[i]-1])
        return max_res

4、最长连续序列(桶排序和set)

class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        #用set存储然后遍历查找,只往后查找
        ele_set = set()
        max_len = 0
        for ele in nums:
            if (ele not in ele_set):
                ele_set.add(ele)
        for ele in nums:
            if ((ele - 1) not in ele_set):
                cur_num = ele
                temp_len = 0
                while (cur_num in ele_set):
                    temp_len += 1
                    cur_num += 1
                max_len = max(max_len, temp_len)
        return max_len

5、三数之和

class Solution:
    def threeSum(self , num: List[int]) -> List[List[int]]:
        # write code here
        if len(num) < 3:
            return []
        help = {}
        res = []
        num = sorted(num)
        for i in range(len(num)-2):
            target = -num[i]
            l = i + 1
            r = len(num) - 1
            while l < r:
                if num[l] + num[r] == target:
                    res.append((num[i], num[l], num[r]))
                    res = list(set(res))
                    l += 1
                elif num[l] + num[r] < target:
                    l += 1
                else:
                    r -= 1
        return res

6、和为k的连续子数组 (前缀和 + hashmap)

思路 – hashtable
通过前缀和求解,令P[i] = A[0] + A[1] + … + A[i-1], 令P[j] = A[0] + … + A[j-1],
满足题目条件为 S = P[j] - P[i],目标是计算有多少个S。

  • 方法为使用一个hashtable,key为前缀和,value为这个前缀和出现的次数。
  • 当我们计算到i时,ret += hashtable.get(P[i+1] - S, 0)
  • 同时更新 hashtable[P[i+1]] += 1
    class Solution:
        def subarraySum(self, nums: List[int], k: int) -> int:
            pre_sum = {0:1}
            cur_sum = 0
            res = 0
            for i in nums:
                cur_sum += i
                if cur_sum - k in pre_sum:
                    res += pre_sum[cur_sum - k]
                pre_sum[cur_sum] = pre_sum[cur_sum] + 1 if cur_sum in pre_sum else 1
            return res
    

九:字符串专题:

1、两个字符串包含的字符是否完全相同(排序后判断即可)

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        s="".join((lambda x:(x.sort(),x)[1])(list(s)))
        t="".join((lambda x:(x.sort(),x)[1])(list(t)))
        if(len(s)!=len(t)):
            return False
        for i in range(len(s)):
            if(s[i]!=t[i]):
                return False
        return True

2、计算一组字符集合可以组成的回文字符串的最大长度(统计每个字符出现次数)

class Solution:
    def longestPalindrome(self, s: str) -> int:
        count = collections.Counter(s)
        length=0
        for ele in count.values():
            length+=int(ele/2)*2
            if(length%2==0 and ele%2==1):
                length+=1
        return length

3、同构字符串

所有出现的字符都必须用另一个字符替换,同时保留字符的顺序。两个字符不能映射到同一个字符上,但字符可以映射自己本身。

class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        for i in range(len(s)):
            if(s.find(s[i])==t.find(t[i])):
                continue
            else:
                return False
        return True

4、判断一个整数是否是回文数(转成字符双指针或者求回文的数)

class Solution:
    def isPalindrome(self, x: int) -> bool:
        if(x<0):
            return False
        if -1<x<10:
            return True
        s=str(x)
        begin,end=0,len(s)-1
        while(begin<end):
            if(s[begin]!=s[end]):
                return False
            else:
                begin+=1
                end-=1
        return True

5、统计二进制字符串中连续 1 和连续 0 数量相同的子字符串个数

class Solution:
    def countBinarySubstrings(self, s: str) -> int:
        #从前往后统计每个连续区间相同数字个数
        if(len(s)<2):
            return 0
        count=1
        count_list=[]
        for i in range(1,len(s)):
            if(s[i]==s[i-1]):
                count+=1
            else:
                count_list.append(count)
                count=1
        count_list.append(count)
        if(len(count_list)<2):
            return 0
        sum=0
        for j in range(1,len(count_list)):
            sum+=min(count_list[j],count_list[j-1])
        return sum

6、字符串变形

class Solution:
    def trans(self , s: str, n: int) -> str:
        # write code here
        s0=[]
        for i in s:
            if i!=' ':
                if i.islower():
                    s0.append(i.upper())
                else:
                    s0.append(i.lower())
            else:
                s0.append(' ')
        s0=''.join(s0).split(' ')
        return ' '.join(s0[::-1])

7、最长公共前缀字符串

class Solution:
    def longestCommonPrefix(self , strs: List[str]) -> str:
        # write code here
        if len(strs) == 0:
            return ''
        pre_str = strs[0]
        for string in strs[1:]:
            if pre_str in string:
                continue
            elif string in pre_str:
                pre_str = string
            else:
                while pre_str not in string:
                    pre_str = pre_str[:-1]
        return pre_str

8、大数加法

class Solution:
    def solve(self , s: str, t: str) -> str:
        # write code here
        if not s: return t 
        if not t: return s
        res = ''
        carry = 0
        i = len(s) - 1
        j = len(t) - 1
        while i >= 0 or j >= 0:
            n1 = s[i] if i >= 0 else 0
            n2 = t[j] if j >= 0 else 0
            tmp = int(n1) + int(n2) + carry
            carry = tmp // 10
            res = str(tmp % 10) + res
            i -= 1
            j -= 1
        if carry:
            return '1'+res
        else:
            return res

9、验证IP地址

class Solution:
    def ipv4(self, ip: str) -> str:
        flag = True
        for x in ip.split("."):
            if len(x) > 3:
                flag = False
                break
            for xi in x:
                if not "0" <= xi <= "9":
                    flag = False
                    break
            if not flag:
                break
            if x[0] == "0" or int(x) < 0 or int(x) > 255:
                flag = False
                break
        return "IPv4" if flag else "Neither"
    
    def ipv6(self, ip: str) -> str:
        def check(digit):
            try:
                res = int(digit, 16)
                return True
            except Exception:
                return False
        flag = True
        for x in ip.split(":"):
            if not x or len(x) > 4 or not check(x.upper()) or int(x.upper(), 16) < 0 or int(x.upper(), 16) > 65536:
                flag = False
                break
        return "IPv6" if flag else "Neither"
    
    def solve(self , IP: str) -> str:
        # write code here
        if ":" in IP:
            # ip6
            if len(IP.split(":")) != 8: return "Neither"
            return self.ipv6(IP)
        elif "." in IP:
            if len(IP.split(".")) != 4: return "Neither"
            return self.ipv4(IP)
        else:
            return "Neither"

10、

十:数组和矩阵专题

1、移动0

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        count=0
        for ele in nums:
            if(ele!=0):
                count+=1
        k=0
        for i in range(len(nums)):
            if(nums[i]!=0):
                nums[k]=nums[i]
                k+=1
        for i in range(count,len(nums)):
            nums[i]=0

2、改变矩阵维度

class Solution:
    def matrixReshape(self, nums: List[List[int]], r: int, c: int) -> List[List[int]]:
        if(len(nums)*len(nums[0])<r*c):
            return nums
        new_martix=[]
        row_index,col_index=0,0
        one_row=[]
        for i in range(len(nums)):
            for j in range(len(nums[0])):
                if(col_index<c):
                    one_row.append(nums[i][j])
                    col_index+=1
                else:
                    col_index=0
                    new_martix.append(one_row.copy())
                    one_row=[nums[i][j]]
                    col_index+=1
        new_martix.append(one_row)
        return new_martix

3、最长连续的1

class Solution:
    def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
        if not nums:
            return 0
        count=0
        if(nums[0]==0):
            count=0
        else:
            count=1
        max_count=count
        for i in range(1,len(nums)):
            if(nums[i]==nums[i-1] and nums[i]==1):
                count+=1
                max_count=max(max_count,count)
            elif(nums[i]==1):
                count=1
                max_count=max(max_count,count)

        return max_count

4、有序矩阵查找

class Solution:
    def searchMatrix(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        if not matrix:
            return False
        row_index,col_index=0,len(matrix[0])-1
        while(row_index<len(matrix) and col_index >=0 ):
            if(matrix[row_index][col_index]==target):
                return True
            elif(target<matrix[row_index][col_index]):
                col_index-=1
            else:
                row_index+=1
        return False

5、一个数组元素在 [1, n] 之间,其中一个数被替换为另一个数,找出重复的数和丢失的数

集合 S 包含从1到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个元素复制了成了集合里面的另外一个元素的值,导致集合丢失了一个整数并且有一个元素重复,找出重复的数和缺失的数。

class Solution:
    def findErrorNums(self, nums: List[int]) -> List[int]:
            #其实就是找第一个
            for index in range(len(nums)):
                while(nums[index]!= index+1):
                    #这里终止一定要注意
                    if(nums[index]==nums[nums[index]-1]):
                        break
                    temp=nums[nums[index]-1]
                    nums[nums[index]-1]=nums[index]
                    nums[index]=temp
            for index in range(len(nums)):
                if(nums[index]!= index+1):
                    return [nums[index],index+1]

6、(二分)找出数组中重复的数,数组值在 [1, n] 之间(要求不能修改数组,也不能使用额外的空间。)

给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

class Solution:
    def findDuplicate(self, nums: List[int]) -> int:
        low,high=1,len(nums)-1
        mid=-1
        while(low<high):
            mid=(low+high)>>1
            count=0
            for ele in nums:
                if(ele <= mid):
                    count+=1
            if(count<=mid):
                low=mid+1
            else:
                high=mid
        return low

7、数组的度

class Solution:
    def findShortestSubArray(self, nums: List[int]) -> int:
        freq,left,right={},{},{}
        for index,ele in enumerate(nums):
            if(ele not in freq):
                freq[ele]=1
                left[ele]=index
            else:
                 freq[ele]+=1
            right[ele]=index
        degree=max(freq.values())
        return min(right[i]-left[i]+1 for i,v in freq.items() if v==degree)
            

8、对角元素相等的矩阵

class Solution:
    def isToeplitzMatrix(self, matrix: List[List[int]]) -> bool:
        #只需要判断当前行除了最后一个元素和后一行除了第一个元素是否相等
        rows,cols=len(matrix),len(matrix[0])
        if(rows==1 or cols==1):
            return True
        for index in range(rows-1):
            if(matrix[index][:-1]!=matrix[index+1][1:]):
                return False
        return True

9、S[i] 表示一个集合,集合的第一个元素是 A[i],第二个元素是 A[A[i]],如此嵌套下去。求最大的 S[i],指导首尾相等

class Solution:
    def arrayNesting(self, nums: List[int]) -> int:
        #寻找最大长度的环
        max_len=1
        for index in range(len(nums)):
            if(max_len>len(nums)/2):
                return max_len
            start_num=nums[index]
            temp_num=nums[start_num]
            temp_len=1
            while(temp_num!=start_num):
                temp_len+=1
                temp_num=nums[temp_num]
            max_len=max(max_len,temp_len)
        return max_len

10、分隔数组,使得对每部分排序后数组就为有序。

class Solution:
    def maxChunksToSorted(self, arr: List[int]) -> int:
        #当遍历到第i个位置时,如果可以切分为块,那前i个位置的最大值一定等于i。
        #否则,一定有比i小的数划分到后面的块,那块排序后,一定不满足升序。
        max_value,count=-100,0
        for i in range(len(arr)):
            max_value=max(max_value,arr[i])
            if(max_value==i):
                count+=1
        return count

11、螺旋矩阵

#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 
# @param matrix int整型二维数组 
# @return int整型一维数组
#
class Solution:
    def spiralOrder(self , matrix: List[List[int]]) -> List[int]:
        # write code here
        if matrix == []:
            return []
        m,n = len(matrix),len(matrix[0])
        up,down = 0,m-1
        left,right = 0,n-1
        res = []
        while left<=right and up<=down:
            for i in range(left,right+1):
                res.append(matrix[up][i])
            up += 1
            if up > down:
                break
            
            for i in range(up,down+1):
                res.append(matrix[i][right])
            right -= 1
            if right < left:
                break

            for i in range(right,left-1,-1):
                res.append(matrix[down][i])
            down -= 1
            if up > down:
                break
            
            for i in range(down,up-1,-1):
                res.append(matrix[i][left])
            left += 1
            if left > right:
                break
        
        return res

12、 顺时针旋转矩阵

class Solution:
    def rotateMatrix(self , mat: List[List[int]], n: int) -> List[List[int]]:
        for i in range(n):
            for j in range(i):
                temp = mat[i][j]
                mat[i][j] = mat[j][i]
                mat[j][i] = temp
        for i in range(n):
            mat[i].reverse()
        return mat

13、旋转数组

class Solution:
    def solve(self , n: int, m: int, a: List[int]) -> List[int]:
        m = m % n
        return a[n-m:] + a[:n-m]

14、调整数组顺序使奇数位于偶数前面

# -*- coding:utf-8 -*-
# 不新建数组,类似于冒泡排序
class Solution:
    def reOrderArray(self, array):
        # write code here
        for i in range(0,len(array)):
            for j in range(len(array)-1,i,-1):
                if array[j-1]%2 ==0 and array[j]%2==1:
                    temp = array[j-1]
                    array[j-1] = array[j]
                    array[j] = temp
        return array

注意:对于本题的变体,本人在面试中被问到过,被问的是“不开辟新空间的条件下,使奇数在前,偶数在后”,面试官给的答案是设置两个偶、奇指针,分别位于数组的开头和末尾,当遇到偶数、奇数时交换。

15、数组中出现次数超过一半的数字

# -*- coding:utf-8 -*-
import collections
class Solution:
    def MoreThanHalfNum_Solution(self, numbers):
        # write code here
        temp = collections.Counter(numbers)
        num = len(numbers)/2
        for k,v in temp.items():
            if v > num:
                return k
        return 0

16、把数组排成最小的数

# -*- coding:utf-8 -*-
class Solution:
    def PrintMinNumber(self, numbers):
        # write code here
        if not numbers:
            return ""
        num=map(str,numbers)
        num.sort(lambda x,y:cmp(x+y,y+x))
        return ''.join(num)

17、构建乘积数组

class Solution:
    def multiply(self , A: List[int]) -> List[int]:
        # 初始化数组B
        B = [1 for i in range(len(A))]
        # 先乘左边,从左到右
        for i in range(1, len(A)):
            B[i] = B[i -1] * A[i -1]
        temp = 1
        # 再乘右边,从右到左
        for i in reversed(range(len(A))):
            B[i] *= temp
            temp *= A[i]
        return B

17、扑克牌顺子

public class Solution {
    public boolean isContinuous(int [] numbers) {
        int[]d = new int[14]; 
        d[0] = -5; 
        int len = numbers.length; 
        if(len==0)
            return false;
        int max = -1; 
        int min = 14; 
        for(int i =0;i<len;i++){
            d[numbers[i]]++; 
            if(numbers[i] == 0){
                continue; 
            }
            if(d[numbers[i]]>1){
                return false; 
            }
            if(numbers[i] >max){
                max = numbers[i]; 
            } 
            if(numbers[i] <min){
                min = numbers[i]; 
            }

        }
        if(max-min<5){
            return true; 
        }
            return false;
        }
}

18、孩子们的游戏-圆圈中最后剩下的数

import java.util.*;
public class Solution {
    public int LastRemaining_Solution(int n, int m) {
        if (m == 0 || n == 0) {
            return -1;
        }
        ArrayList<Integer> data = new ArrayList<Integer>();
        for (int i = 0; i < n; i++) {
            data.add(i);
        }
      int index=0;
      while(data.size()>1){
          index=(index+m-1)%data.size();
          data.remove(index);
      }
      return data.get(0);
    }
}

19、不用加减乘除做加法


public class Solution {
    public int Add(int num1,int num2) {
        if(num1>0){
            while(num1--!=0)
                num2++;
        }
        else if(num1<0){
            while(num1++!=0)
                num2--;
        }
        return num2;
    }
}

20、剪绳子

# -*- coding:utf-8 -*-
class Solution:
    def cutRope(self, number):
        # write code here
        if number < 2:
            return 0
        elif number == 2:
            return 1
        elif number == 3:
            return 2
        n = number//3
        l = number%3
        if l == 1:
            return int(4*pow(3, (n-1)))
        elif l == 2:
            return int(pow(3, n)*2)
        else:
            return int(pow(3, n))

十一:排序专题

1、数组中的第K个最大元素(快排或者堆排序)

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
            def quick_sort(nums, l, r, k):
                if (l <=r):
                    temp = nums[l]
                    i, j = l, r
                    while (i != j):
                        while (i < j and temp < nums[j]):
                            j -= 1
                        if (i < j):
                            nums[i] = nums[j]
                            i += 1
                        while (i < j and temp >= nums[i]):
                            i += 1
                        if (i < j):
                            nums[j] = nums[i]
                            j -= 1
                    nums[i] = temp
                    if (i == k - 1):
                        return temp
                    elif (i > k-1):
                        return quick_sort(nums, l, i - 1, k)
                    else:
                        return quick_sort(nums, i + 1, r, k)
            if(k>len(nums)):
                return -1

2、前k个高频元素

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        res_dict={}
        res_list=[]
        for ele in nums:
            if(ele not in res_dict):
                res_dict[ele]=1
            else:
                res_dict[ele]+=1
        res=sorted(res_dict.items(),key=lambda x: x[1], reverse=True)
        if(k>len(res)):
            return []
        for index,ele in enumerate(res):
            if(index<k):
                res_list.append(ele[0])
        return res_list

3、根据字符出现频率排序

import collections
class Solution:
    def frequencySort(self, s: str) -> str:
        m=collections.Counter(s)
        tmp=[[k,v] for k,v in m.items()]
        tmp.sort(key=lambda x:x[1],reverse=True)
        res=''
        for ele in tmp:
            res=res+ele[0]*ele[1]
        return res
        

4、三种颜色国旗排列

class Solution:
    def sortColors(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        low,high=0,len(nums)-1
        index=0
        while(index<=high):
            if(nums[index]==0):
                nums[index],nums[low]=nums[low],nums[index]
                low+=1
                index+=1
            elif(nums[index]==1):
                index+=1
            else:
                nums[index],nums[high]=nums[high],nums[index]
                high-=1
        

十二:位运算

1:统计两个数的二进制表示有多少位不同

class Solution(object):
    def hammingDistance(self, x, y):
        """
        :type x: int
        :type y: int
        :rtype: int
        """
        #所有int型整数都是相同位数
        count=0
        while(x or y):
            if((x & 1) != (y & 1)):
                count+=1
            x=x>>1
            y=y>>1
        return count

2:数组中唯一一个不重复的元素

class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        #交换律:a ^ b ^ c <=> a ^ c ^ b
        #任何数于0异或为任何数 0 ^ n => n
        #相同的数异或为0: n ^ n => 0
        count=0
        for ele in nums:
            count = count ^ ele
        return count

3:找出数组中缺失的那个数

题目描述:数组元素在 0-n 之间,但是有一个数是缺失的,要求找到这个缺失的数。

class Solution(object):
    def missingNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        res=0
        for ele in range(len(nums)+1):
            res^=ele
        for ele in nums:
            res^=ele
        return res

4:数组中不重复的两个元素

class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        #将数组所有元素进行异或操作
        #找出结果的最高位1,两个数中一个最高位是1,一个是0
        bit_mask=0
        for ele in nums:
            bit_mask ^=ele
        #找到最高位是1的index
        n=len(bin(bit_mask))-3
        i,j=0,0
        for ele in nums:
            if((ele>>n)&1):
                i^=ele
            else:
                j^=ele
        return [i,j]

5:判断一个数是不是 2 的 n 次方

class Solution(object):
    def isPowerOfTwo(self, n):
        """
        :type n: int
        :rtype: bool
        """
        #n与n-1,如果为0,则是2的幂次方
        if(n<=0):
            return False
        return (n&(n-1))==0

6:判断一个数是不是 4 的 n 次方

class Solution(object):
    def isPowerOfFour(self, num):
        """
        :type num: int
        :rtype: bool
        """
        return num >0 and (num & (num-1)==0) and (num & 0xaaaaaaaa)==0

7:判断一个数的位级表示是否不会出现连续的 0 和 1

class Solution(object):
    def hasAlternatingBits(self, n):
        """
        :type n: int
        :rtype: bool
        """
        n=(n ^ (n>>1))
        n=(n&(n+1))
        return n==0
        

8:数字的补数

给定一个正整数,输出它的补数。补数是对该数的二进制表示取反。

class Solution(object):
    def findComplement(self, num):
        """
        :type num: int
        :rtype: int
        """
        #转换为求掩码过程
        #100000000...作为mask与num相与,找出最高位1
        mask=1<<30
        while((mask & num ==0)):
            mask = mask>>1
        mask=(mask <<1 )-1
        return mask^num 

9:字符串数组最大乘积

题目描述:字符串数组的字符串只含有小写字符。求解字符串数组中两个字符串长度的最大乘积,要求这两个字符串不能含有相同字符。

class Solution(object):
    def maxProduct(self, words):
        """
        :type words: List[str]
        :rtype: int
        """
        # 或|=:两个二进制对应位只要1个为1,结果就是1,否则是0;
        # 与 &=:两个二进制的对应位都为1时,结果为1,否则结果等于0;
        # 异或 ^=:两个二进制的对应位不同,结果为1,否则结果为0。
        value_list=[0]*len(words)
        for i in range(len(words)):
            for char_val in words[i]:
                #向左移动1
                value_list[i] |= 1 << (ord(char_val)-97)
        #只要有一个位置相同,&就不必为0
        return max([len(words[i])*len(words[j]) for i in range(len(words)) for j in range(i+1,len(words)) if not (value_list[i] & value_list[j])] or [0])

10: 统计从 0 ~ n 每个数的二进制表示中 1 的个数

class Solution(object):
    def countBits(self, num):
        """
        :type num: int
        :rtype: List[int]
        """
        #动态规划找规律
        #如果是偶数,等于其一半的数中1的数目
        #如果是基数,等于其减去一的数中1的数目
        res=[0]
        for ele in range(1,num+1):
            if(ele %2==0):
                res.append(res[ele/2])
            else:
                res.append(res[ele-1]+1)
        return res

十三:链表

1、链表反转(迭代 + 头插)

class Solution:
    def ReverseList(self , head: ListNode) -> ListNode:
        # write code here
        # 空链表处理
        if head == None:
            return head
        # 非空链表处理
        pre = None
        cur = head
        while cur:
            tmp = cur.next
            cur.next = pre
            pre = cur
            cur = tmp
        return pre

2、区间内反转 

class Solution:
    def reverseBetween(self , head: ListNode, m: int, n: int) -> ListNode:
        # write code here
        p = ListNode(0)
        p.next = head  # 保证p.next存在
        new_head = p
        cur = None
        i = 1
        while i < n:
            if i < m:
                p = head
                head = head.next
            elif i >= m:
                cur = head.next
                head.next = cur.next  # 保证第n个节点之后的节点不丢失
                cur.next = p.next
                p.next = cur
            i += 1
        return new_head.next

3、 链表中的节点每k个一组翻转

# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
#
class Solution:
    def reverseKGroup(self , head: ListNode, k: int) -> ListNode:
        # write code here
        new_head = ListNode(0)
        new_head.next=head

        c=0
        last=new_head
        cur = new_head
        while cur:
            if c==k:
                cur=self.reverse(last,k)
                last=cur
                c=0
            c+=1

            cur=cur.next
        return new_head.next

    def reverse(self, last, k):
        queue_head=last.next
        for i in range(1, k):
            next=queue_head.next
            queue_head.next=next.next
            next.next=last.next
            last.next=next
        return queue_head

4、合并两个有序链表

class Solution:
    def Merge(self , pHead1: ListNode, pHead2: ListNode) -> ListNode:
        # write code here
        h = ListNode(0)
        new = h
        # 为什么要用new?因为h接下来不断在动,new记住了表头!
        while pHead1 and pHead2:
            if pHead1.val <= pHead2.val:
                h.next = pHead1
                pHead1 = pHead1.next
            else:
                h.next = pHead2
                pHead2 = pHead2.next
            h = h.next
        else:
            if pHead1:
                h.next = pHead1
            elif pHead2:
                h.next = pHead2
        return new.next

5、K个链表合并

import heapq
class Solution:
    def mergeKLists(self , lists: List[ListNode]) -> ListNode:
        vhead = ListNode(-1)
        p = vhead 
        
        heads = [i for i in lists]
        heap = [(n.val,idx) for idx, n in enumerate(lists) if n is not None]
        heapq.heapify(heap)
        
        while heap:
            idx = heapq.heappop(heap)[1] #
            tmp = heads[idx]
            p.next = tmp
            heads[idx] = heads[idx].next
            p = p.next
            if heads[idx]: heapq.heappush(heap,(heads[idx].val, idx)) 
                
        return vhead.next

6、链表是否有环(快慢指针,见双指针)

7、链表环的入口 (相遇之后,一个指针指向最开头)

class Solution:
    def EntryNodeOfLoop(self, pHead):
        # write code here
        if pHead == None:
            return None
        fast =pHead
        slow = pHead
        while fast and fast.next:
            fast = fast.next.next
            slow = slow.next
            if fast == slow:
                break
        if fast == None&nbs***bsp;fast.next == None:
            return None
        slow = pHead
        while slow != fast:
            slow=slow.next
            fast = fast.next
        return slow

8、找出倒数最后k个链表节点

class Solution:
    def FindKthToTail(self , pHead: ListNode, k: int):
        pre = pHead
        suc = pHead
        for i in range(k):
            if suc:
                suc = suc.next
            else:
                return None
        while suc:
            pre = pre.next
            suc = suc.next
        else:
            return pre

9、删除倒数第n个节点 (先走n步找到该节点)

class Solution:
    def removeNthFromEnd(self , head, n):
        pre = head
        suc = head
        for i in range(n):
            if suc.next:
                suc = suc.next
            else:
                head = head.next
                return head
        while suc.next:
            pre = pre.next
            suc = suc.next
        else:
            pre.next = pre.next.next
        return head

10、两个链表的第一个公共节点

class Solution:
    def FindFirstCommonNode(self , pHead1 , pHead2 ):
        # 计算链表长度的函数
        def lenth(pHead: ListNode):
            i = 0
            while pHead:
                i += 1
                pHead = pHead.next
            return i
        
        # 走差值
        l1 = lenth(pHead1)
        l2 = lenth(pHead2)
        if l1 >= l2:
            n = l1-l2
            while n:
                pHead1 = pHead1.next
                n -= 1
        else:
            n = l2-l1
            while n:
                pHead2 = pHead2.next
                n -= 1
     
        # 一起走
        while pHead1:
            if pHead1 == pHead2:
                return pHead1
            else:
                pHead1 = pHead1.next
                pHead2 = pHead2.next
        
        # 没有交点返回空
        return None

 11、两个链表相加

class Solution:
    # 反转链表,按照个十百位数顺序相加,carry保存进位数据
    # 时间复杂度:O(n)  空间复杂度:O(1)
    def reverse_list(self, head):
        if not head:
            return None
        cur = head
        pre = None
        while cur:
            temp = cur.next
            cur.next = pre 
            pre = cur
            cur = temp
        return pre 

    def addInList(self , head1: ListNode, head2: ListNode) -> ListNode:
        if not head1:
            return head2
        if not head2:
            return head1
        head1 = self.reverse_list(head1)
        head2 = self.reverse_list(head2)
        res = ListNode(2022)
        head = res
        carry = 0
        while head1 or head2 or carry != 0:
            val1 = 0 if not head1 else head1.val
            val2 = 0 if not head2 else head2.val
            sum_ = val1 + val2 + carry
            carry = sum_ // 10
            temp = sum_ % 10
            head.next = ListNode(temp)
            head = head.next
            if head1:
                head1 = head1.next
            if head2:
                head2 = head2.next
        return self.reverse_list(res.next)

12、单链表排序


class Solution:
    def sortInList(self , head ):
        # write code here
        list1 = []
        while(head):
            list1.append(head.val)
            head = head.next
        list1.sort()
        temp = ListNode(0)
        pHead = temp
        for i in list1:
            pHead.next = ListNode(i)
            pHead = pHead.next
        return temp.next

13、 判断链表是否是回文

class Solution:
    def isPail(self , head):
        res = []
        cur = head 
        while cur:
            res.append(cur.val)
            cur = cur.next
        return res == res[::-1]

14、 删除有序链表中重复的元素-I

class Solution:
    def deleteDuplicates(self , head):
        # write code here
        cur = head
        while cur:
            while cur.next and cur.val == cur.next.val:
                cur.next = cur.next.next
            cur = cur.next
        return head

15、删除有序链表中重复的元素-II 

class Solution:
    def deleteDuplicates(self , head: ListNode) -> ListNode:
        # write code here
        dummy = pre = ListNode(-1)
        while head and head.next:
            if head.val == head.next.val:
                temp = head.val
                while head and head.val == temp:
                    head = head.next
                continue
            else:
                pre.next = head
                pre = pre.next
                head = head.next
        pre.next = head
        return dummy.next

 16、二叉树和双向链表

class Solution:
    def Convert(self , pRootOfTree ):
        # write code here
        if not pRootOfTree:return
        #建立左子树的双向链表 返回链表头p
        left=self.Convert(pRootOfTree.left)
        p=left
        #定位到左子树的最右节点
        while left and p.right:
            p=p.right
        #假如存在左子树,和根节点连接成双向链表
        if left:
            p.right=pRootOfTree
            pRootOfTree.left=p 
        #构建右子树的双良链表 
        right=self.Convert(pRootOfTree.right)
        #假如存在柚子树 则和根节点连接成双向链表 
        if right:
            pRootOfTree.right=right 
            right.left=pRootOfTree
        #返回链表
        return left if left else pRootOfTree

 16、二叉树下一个节点

# -*- coding:utf-8 -*-
# class TreeLinkNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
#         self.next = None
class Solution:
    def GetNext(self, pNode):
        # write code here
        if not pNode:
            return None
        if pNode.right:  #有右子树
            res = pNode.right
            while res.left:
                res = res.left
            return res
        while pNode.next:  #无右子树,则找第一个当前节点是父节点左孩子的节点
            tmp = pNode.next
            if tmp.left == pNode:
                return tmp
            pNode = tmp   #沿着父节点向上遍历
        return None  #到了根节点仍没找到,则返回空

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值