Python文档算法整理

参考leetcode大神

基础

ternary operator 三目运算符

a=int(input("a="))
b=int(input("b="))
max=a if a>b else b
print(max)

https://www.runoob.com/python/python-func-enumerate.html

__init__

https://www.zhihu.com/question/46973549/answer/767530541

Python中 __init__的通俗解释是什么? - 追远·J的回答 - 知乎 https://www.zhihu.com/question/46973549/answer/767530541

while

yield

strip()

只去掉首尾的字符

python链表

set()

哈希表

enumerate()

zip()     

矩阵转置

def trans(m):
    return list(zip(*m)) #注意,转出来的行是元组

range()

ln()  矩阵,处理二维数组

def ln(x): #封装一个ln()函数(可应用于处理array)
    ln_x=[]
    for i in range(len(x)):
        ln_x.append(np.log(x[i])) #逐个存入list
    return np.array(ln_x) #返回数组

算法

#输入
{"headers": {
  "Employee": ["Id", "Name", "Salary", "DepartmentId"], 
  "Department": ["Id", "Name"]}, 
 "rows": {
   "Employee": [[1, "Joe", 70000, 1], [2, "Jim", 90000, 1], [3, "Henry", 80000, 2], 
                [4, "Sam", 60000, 2], [5, "Max", 90000, 1]], 
    "Department": [[1, "IT"], [2, "Sales"]]
 }
}

#MySQL
SELECT
    Department.name AS 'Department',
    Employee.name AS 'Employee',
    Salary
FROM
    Employee
        JOIN
    Department ON Employee.DepartmentId = Department.Id
WHERE
    (Employee.DepartmentId , Salary) IN
    (   SELECT
            DepartmentId, MAX(Salary)
        FROM
            Employee
        GROUP BY DepartmentId
	)
;
#输出
{
  "headers": ["Department", "Employee", "Salary"], 
  "values": [["IT", "Jim", 90000], ["Sales", "Henry", 80000], ["IT", "Max", 90000]]
}
#视图
| Department | Employee | Salary |
|------------|----------|--------|
| Sales      | Henry    | 80000  |
| IT         | Max      | 90000  |

设置目标值为两数之和,返回两数下标

import json
from typing import List

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:  #要求返回list格式
        tmp = {}
        for k, v in enumerate(nums):  # k从0开始,v从num[0]开始
            print(k,v)
            tmp[v] = k #将list的下标和值存入字典,因为字典下标可以方便目标值和移动取值v做差
            if target - v in tmp:
                return [tmp[target - v], k] #tmp[target - v]为一个数的下标,k为另一个数的下标
            # tmp[v] = k  #关键点,利用下标来确定tmp字典里的值是来自list的

def stringToIntegerList(input):
    return json.loads(input)

def integerListToString(nums, len_of_list=None):
    if not len_of_list:
        len_of_list = len(nums)
    return json.dumps(nums[:len_of_list]) #注意dumps有s

def main():
    import sys
    import io
    def readlines():
        for line in io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8'):
            yield line.strip('\n') #换行终止该行输入(改行字符串属于一个单独的lines)

    lines = readlines()
    while True:
        try:
            line = next(lines) #开启一行的输入
            nums = stringToIntegerList(line);
            line = next(lines) #开启新的一行的输入
            target = int(line);

            ret = Solution().twoSum(nums, target)

            out = integerListToString(ret);
            print(out)
        except StopIteration:
            break

if __name__ == '__main__':
    main()

json.dumps 

运行效果

[2,7,11,15]
9
[0,1]

两数相加

定义一个单链表

import io
import json
import sys
""" 链表逆序之和 """
class ListNode:
    def __init__(self,val=0,next=None):
        self.val=val
        self.next=next

def stringToIntegerList(line):
    return json.loads(line)

def stringToListNode(line):
    numbers=stringToIntegerList(line)

    dummyRoot=ListNode(0) #哑结点的指针
    ptr=dummyRoot #声明与构造 ptr具备ListNode类型并被赋予哑结点的指针,即具备指向头结点的性能,则头结点就是ptr.next
    for number in numbers:
        ptr.next=ListNode(number) #结点的赋值
        ptr=ptr.next #结点值依次传递
    new=dummyRoot.next #哑结点值传递(这样能保证从头到尾都能循环)
    return new #这里的new是结点值,因为它是.next赋值过来的

class Solution:
    def addTwoNumbers(self,l1:ListNode,l2:ListNode):
        head=ListNode() #注意这里不用赋予(0),无需哑结点
        p=head #等下利用p进行循环
        carry=0
        while carry or l1 or l2:
            var = carry  # 关键点:val为0或1,满10进1,商作为进位
            if l1:
                var1= l1.val + var
                l1=l1.next
            if l2:
                var2 = l2.val + var1
                l2=l2.next
            carry,var3=divmod(var2,10) #商,余数
            p.next=ListNode(var3)
            p=p.next
        return head.next #p只能一个一个的带值,用全部存入ListNode后赋给head来读出

def ListNodeToString(node):
    if not node:
        return "[]"
    result=""
    while node:
        result+=str(node.val)+","
        node=node.next
    return "["+result[:-1]+"]"

def EnterMain():
    def readline():
        for line in io.TextIOWrapper(sys.stdin.buffer,encoding='utf-8'):
            yield line.strip('\n')
    lines=readline()

    while True:
        try:
            line=next(lines)
            l1=stringToListNode(line)
            line=next(lines)
            l2=stringToListNode(line)
            node=Solution().addTwoNumbers(l1, l2)
            out=ListNodeToString(node)
            print(out)
        except StopIteration:
            break

if __name__ == '__main__':
    EnterMain()

运行

[2,4,3]
[8,1,1]
0 <__main__.ListNode object at 0x159dece50> <__main__.ListNode object at 0x159dfd040>
<class '__main__.ListNode'> <class '__main__.ListNode'>
0 0 2
var1= 2
+ 8 =var2= 10
0 10
1 0
<class '__main__.ListNode'> <class '__main__.ListNode'>
1 1 4
var1= 5
+ 1 =var2= 6
1 6
0 6
<class '__main__.ListNode'> <class '__main__.ListNode'>
0 0 3
var1= 3
+ 1 =var2= 4
0 4
0 4
[0, 6, 4]

寻找两个正序数组的中位数

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        n1 = len(nums1)
        n2 = len(nums2)
        if n1 > n2: #保证左边参数list小于右边参数
            return self.findMedianSortedArrays(nums2, nums1)
        k = (n1 + n2 + 1) // 2 #取商整
        print("整合两个list的中位数k=",k)
        left = 0
        right = n1
        print("right=",right)
        while left < right: #直到left>=right跳出
            m1 = left + (right - left) // 2 #总会取到(奇)中位数(偶数中位线)的左边一位
            print("1.m1=",m1)
            m2 = k - m1
            print("1.m2=k - m1=", m2)
            print("nums1[m1]=",nums1[m1],"nums2[m2 - 1]=",nums2[m2 - 1]) #总会取到中位数
            if nums1[m1] < nums2[m2 - 1]:
                left = m1 + 1
                print("left=", left)
            else:
                right = m1
                print("right=", right)
        m1 = left
        print("2.m1=", m1)
        m2 = k - m1
        c1 = max(nums1[m1 - 1] if m1 > 0 else float("-inf"), nums2[m2 - 1] if m2 > 0 else float("-inf")) #三目运算符
        if (n1 + n2) % 2 == 1:
            print("奇数c1=",c1)
            return c1
        c2 = min(nums1[m1] if m1 < n1 else float("inf"), nums2[m2] if m2 < n2 else float("inf"))
        print("偶数(c1 + c2) / 2=",(c1 + c2) / 2)
        #关键点:c1,c2分别为两个list的中位数
        return (c1 + c2) / 2

运行

[1,3,8]
[2,7,9]
整合两个list的中位数k= 3
right= 3
1.m1= 1
1.m2=k - m1= 2
nums1[m1]= 3 nums2[m2 - 1]= 7
left= 2
1.m1= 2
1.m2=k - m1= 1
nums1[m1]= 8 nums2[m2 - 1]= 2
right= 2
2.m1= 2
偶数(c1 + c2) / 2= 5.0
5.0

盛最多水的容器

import json
from typing import List

class Solution:
    def maxArea(self, height: List[int]) -> int:
        # 初始化双指针
        i, j = 0, len(height) - 1 #j取最后一位
        maxarea = 0
        # 循环遍历, 求面积注意:h是高, w是宽, h应该是 height[i] height[j]中的”矮“的   ~不然水就漏了~
        # 谁比较“矮”谁优先
        while i < j:
            if height[i] > height[j]:
                h, w = height[j], j - i
                j -= 1 #矮的靠近另一头移动
            else:
                h, w = height[i], j - i
                i += 1
            print("h=",h,"w=",w)
            maxarea = max(maxarea, h * w) #循环取最大值(一遍扫描过去就可以了)
            print("maxarea",maxarea)
        return maxarea

def stringToIntegerList(input):
    return json.loads(input)

def main():
    import sys
    import io
    def readlines():
        for line in io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8'):
            yield line.strip('\n')

    lines = readlines()
    while True:
        try:
            line = next(lines)
            height = stringToIntegerList(line);

            ret = Solution().maxArea(height)

            out = str(ret);
            print(out)
        except StopIteration:
            break

if __name__ == '__main__':
    main()

运行

[1,8,6,2,5,4,8,3,7]
h= 1 w= 8
maxarea 8
h= 7 w= 7
maxarea 49
h= 3 w= 6
maxarea 49
h= 8 w= 5
maxarea 49
h= 6 w= 4
maxarea 49
h= 2 w= 3
maxarea 49
h= 5 w= 2
maxarea 49
h= 4 w= 1
maxarea 49
49

反转链表


import json
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        p, rev = head, None
        while p: #当p回到p=None时跳出
            print("值rev=p=",p)
            print("反转rev.next=rev=",rev)
            print("顺序记录循环次数p=p.next=",p.next)
            print("")
            rev,rev.next, p =p, rev, p.next #多元赋值,不能分行操作,要同时进行
        return rev

def stringToIntegerList(input):
    return json.loads(input)

def stringToListNode(input):
    # Generate list from the input
    numbers = stringToIntegerList(input)

    # Now convert that list into linked list
    dummyRoot = ListNode(0)
    ptr = dummyRoot
    for number in numbers:
        ptr.next = ListNode(number)
        ptr = ptr.next

    ptr = dummyRoot.next
    return ptr

def listNodeToString(node):
    if not node:
        return "[]"

    result = ""
    while node:
        result += str(node.val) + ", "
        node = node.next
    return "[" + result[:-2] + "]"

def main():
    import sys
    import io
    def readlines():
        for line in io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8'):
            yield line.strip('\n')

    lines = readlines()
    while True:
        try:
            line = next(lines)
            head = stringToListNode(line);

            ret = Solution().reverseList(head)

            out = listNodeToString(ret);
            print(out)
        except StopIteration:
            break

if __name__ == '__main__':
    main()

运行

[1,2,3,4,5]
值rev=p= <__main__.ListNode object at 0x15de5cc70>
反转rev.next=rev= None
顺序记录循环次数p=p.next= <__main__.ListNode object at 0x15de5cbe0>

值rev=p= <__main__.ListNode object at 0x15de5cbe0>
反转rev.next=rev= <__main__.ListNode object at 0x15de5cc70>
顺序记录循环次数p=p.next= <__main__.ListNode object at 0x15de5cb80>

值rev=p= <__main__.ListNode object at 0x15de5cb80>
反转rev.next=rev= <__main__.ListNode object at 0x15de5cbe0>
顺序记录循环次数p=p.next= <__main__.ListNode object at 0x15de5cb20>

值rev=p= <__main__.ListNode object at 0x15de5cb20>
反转rev.next=rev= <__main__.ListNode object at 0x15de5cb80>
顺序记录循环次数p=p.next= <__main__.ListNode object at 0x15de5cac0>

值rev=p= <__main__.ListNode object at 0x15de5cac0>
反转rev.next=rev= <__main__.ListNode object at 0x15de5cb20>
顺序记录循环次数p=p.next= None

[5, 4, 3, 2, 1]

 回文数

数组:索引O(1),基于内存寻址

链表:索引O(n),需通过指针获取到下一个位置的节点

方法一:链表复制到数组

class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        vals = [] #list跟数组类似,但不是numpy.array
        current_node = head #链表
        while current_node is not None: #循环到current_node=None时跳出
            vals.append(current_node.val) #压入链表值到list
            current_node = current_node.next #逐个
            print(vals[::-1]) #从后往前读
        return vals == vals[::-1] #当正序和倒序相等时,返回true

运行

[1,2,9,4,9,2,1]
[1]
[2, 1]
[9, 2, 1]
[4, 9, 2, 1]
[9, 4, 9, 2, 1]
[2, 9, 4, 9, 2, 1]
[1, 2, 9, 4, 9, 2, 1]
True

方法二:递归(存在堆栈帧的开销问题,比第一种差)

方法三:快慢指针

避免使用 O(n)O(n) 额外空间的方法就是改变输入->空间复杂度降到 O(1)O(1)

最小路径和

动态规划=动态设置+状态转移方程

逆方向思考选择向左还是向右

时间复杂度:O(mn)O(mn),计算dp 的每个元素的值

空间复杂度:O(mn)O(mn),创建一个二维数组 dpdp,和网格大小相同

import json
from typing import List

class Solution:
    def minPathSum(self, grid: List[List[int]]) -> int:
        if not grid or not grid[0]: #行或列为空
            return 0

        rows, columns = len(grid), len(grid[0])
        dp = [[0] * columns for _ in range(rows)] #定义同等行列数dp[][]并初始化为[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
        print(dp)
        dp[0][0] = grid[0][0]
        for i in range(1, rows):
            dp[i][0] = dp[i - 1][0] + grid[i][0] #选行方向
            print("dp[i][0]=",dp[i][0])
        for j in range(1, columns):
            dp[0][j] = dp[0][j - 1] + grid[0][j] #选列方向
            print("dp[0][j]=",dp[0][j])
        for i in range(1, rows):
            for j in range(1, columns):
                print("dp[i - 1][j]=",dp[i - 1][j], "dp[i][j - 1]=",dp[i][j - 1],"dp[i][j]=",grid[i][j])
                #比较逆方向上的 左和上一位的大小,选择小的相加,构成新的dp[i][j]
                dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j]
                print("dp[i][j]=",dp[i][j])
        return dp[rows - 1][columns - 1] #从右下往左上推进,以保证从左上向右下选取最佳路径(两个值最小的)

def stringToIntegerList(input):
    return json.loads(input)

def main():
    import sys
    import io
    def readlines():
        for line in io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8'):
            yield line.strip('\n')

    lines = readlines()
    while True:
        try:
            line = next(lines)
            twoD = stringToIntegerList(line);
            ret = Solution().minPathSum(twoD)

            out = str(ret);
            print(out)
        except StopIteration:
            break

if __name__ == '__main__':
    main()

运行

[[1,3,1],[1,5,1],[4,2,1]]
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
dp[i][0]= 2
dp[i][0]= 6
dp[0][j]= 4
dp[0][j]= 5
dp[i - 1][j]= 4 dp[i][j - 1]= 2 dp[i][j]= 5
dp[i][j]= 7
dp[i - 1][j]= 5 dp[i][j - 1]= 7 dp[i][j]= 1
dp[i][j]= 6
dp[i - 1][j]= 7 dp[i][j - 1]= 6 dp[i][j]= 2
dp[i][j]= 8
dp[i - 1][j]= 6 dp[i][j - 1]= 8 dp[i][j]= 1
dp[i][j]= 7
7

对称二叉树

深度周游(递归)

 DFS(深度优先搜索)

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        if not root:
            return True

        # True是真实的,而ture是逻辑上的真,一般指1,并且r和u位置不同
        def dfs(left, right):  # 形参可以随便取
            if not (left or right): #这有个()所以里面用or,整体相当于如果left,right都没有的话是根树
                return True
            if not (left and right): #()里面的and整体上相当于or
                return False
            if left.val != right.val:
                return False
            return dfs(left.left, right.right) and dfs(left.right, right.left)  # 按递归迭代的规则来

        return dfs(root.left, root.right)  # 返回的逻辑要按规则来,并满足递归

def stringToTreeNode(input):
    input = input.strip() #取掉首位的空格(如果有的话)
    print(type(input),"input=",input)
    input = input[1:-1]
    print(type(input),"input=", input)
    if not input:
        return None
    print(type(input.split(',')),input.split(',')) #加上.split(',')之后,str就转成list了
    inputValues = [s.strip() for s in input.split(',')] #利用for循环去除","
    print(type(inputValues),"inputValues=",inputValues)
    root = TreeNode(int(inputValues[0])) #强转后存入二叉树
    print(type(root),root) #root是二叉树的对象
    nodeQueue = [root] #二叉树转list 表示 队列
    print(type(nodeQueue),nodeQueue)
    front = 0
    index = 1 #保证不超出list长度,从1开始计数
    while index < len(inputValues):
        node = nodeQueue[front] #输入的第一个数作为根结点,之后随front+1循环
        front = front + 1 #孩子作为新的父结点

        item = inputValues[index] #输入的第二个数
        index = index + 1
        if item != "null": #如果根结点有孩子(按输入的顺序),挨着父结点的记这个为左孩子
            leftNumber = int(item)
            node.left = TreeNode(leftNumber) #按二叉树结构处理
            nodeQueue.append(node.left) #存入list队列

        if index >= len(inputValues):
            break

        item = inputValues[index] #输入的第三个数
        index = index + 1
        if item != "null":
            rightNumber = int(item)
            node.right = TreeNode(rightNumber)
            nodeQueue.append(node.right)
    return root #返回nodeQueue所有的值(这些值都是新的结点)

def main():
    import sys
    import io
    def readlines():
        for line in io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8'):
            yield line.strip('\n')

    lines = readlines()
    while True:
        try:
            line = next(lines)
            root = stringToTreeNode(line);
            ret = Solution().isSymmetric(root)

            out = (ret);
            print(out)
        except StopIteration:
            break

if __name__ == '__main__':
    main()

运行

[1,2,2,3,4,4,3]
True
[9,11,11,0,1,1,0]
True
[1,1,1,1,1,1,1]
True

广度周游(队列)

class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        if not root and (root.left or root.right):
            return True
        queue = [root.left, root.right]  # 用list表示队列,输入的节点被保存到队列,注意属于TreeNode对象
        while queue: #直到left= None right= None 时,跳出循环
            # 先取出前两个节点
            left = queue.pop(0) #因为queue是list,则pop(0)是弹出list[0]的左右孩子结点(按输入顺序)
            right = queue.pop(0)
            print("left=",left,"right=",right)
            print("left=", left.val, "right=", right.val)
            if not (left or right):
                return True
            if not (left and right):
                return False
            if left.val != right.val:  # 这行才是实实在在比较节点值
                return False
            # 左孩子的左节点和右孩子右节点存入队列
            queue.append(left.left)
            queue.append(right.right)
            print(queue) #None节点
            # 左孩子的右节点和右孩子的右节点存入队列
            queue.append(left.right)
            queue.append(right.left)
            print(queue)
        return True

运行

[1,2,2,3,4,4,3]
left= <__main__.TreeNode object at 0x15a0cedc0> right= <__main__.TreeNode object at 0x15a0ced30>
left= 2 right= 2
[<__main__.TreeNode object at 0x15a0cecd0>, <__main__.TreeNode object at 0x15a0cebb0>]
[<__main__.TreeNode object at 0x15a0cecd0>, <__main__.TreeNode object at 0x15a0cebb0>, <__main__.TreeNode object at 0x15a0cec70>, <__main__.TreeNode object at 0x15a0cec10>]
left= <__main__.TreeNode object at 0x15a0cecd0> right= <__main__.TreeNode object at 0x15a0cebb0>
left= 3 right= 3
[<__main__.TreeNode object at 0x15a0cec70>, <__main__.TreeNode object at 0x15a0cec10>, None, None]
[<__main__.TreeNode object at 0x15a0cec70>, <__main__.TreeNode object at 0x15a0cec10>, None, None, None, None]
left= <__main__.TreeNode object at 0x15a0cec70> right= <__main__.TreeNode object at 0x15a0cec10>
left= 4 right= 4
[None, None, None, None, None, None]
[None, None, None, None, None, None, None, None]
left= None right= None

判断环形链表 

快慢针   时间复杂度:O(n),空间复杂度O(1)

# Definition for singly-linked list.
import json

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution:
    def hasCycle(self, head: ListNode) -> bool:

        if not head or not head.next:
            return False

        slow = head
        fast = head.next
        # 快指针必须在慢指针前面一位,不然while第一步就因为指针重合跳出循环了
        while slow != fast:
            if not fast or not fast.next: #注意不用少了not
                return False
            # 迭代
            slow = slow.next  # 每次走一步
            fast = fast.next.next  # 每次走两步
        return True

def stringToIntegerList(input):
    return json.loads(input)


def stringToListNode(inputNode,pos):
    # 从输入中生成list
    numbers = stringToIntegerList(inputNode)
    print(type(numbers),numbers[len(numbers)-1]) #得到最后一个数
    # Now convert that list into linked list 列表转化成链表
    dummyRoot = ListNode(0) #虚根,值为0,即ListNode(dummyRoot.val)
    print("ListNode(0)=",dummyRoot,"dummyRoot.val=",dummyRoot.val)
    ptr = dummyRoot #ptr.next才是指针
    for number in numbers:
        ptr.next = ListNode(number) #为ListNode添加链表指针
        ptr = ptr.next
        print(ptr)
    #创建指针循环
    newRoot=ListNode(0)
    ptr_new=newRoot
    #ptr_new=ListNode(numbers[len(numbers) - 1]).next #为输入的list最后一个值赋予指针
    ptr_new.next=ListNode(numbers[pos-1])

    # print(ListNode(numbers[pos-1]).next,ListNode(numbers[pos-1]).val)
    ListNode(numbers[len(numbers) - 1]).next=ptr_new.next
    print("ListNode(numbers[pos])=",ptr)

    ptr = dummyRoot.next
    print("dummyRoot.next=",ptr,"和第二个一样")
    return ptr #ptr就是之后赋值给head

def main():
    import sys
    import io
    def readlines():
        for line in io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8'):
            yield line.strip('\n')

    lines = readlines()
    while True:
        try:
            lineNode = next(lines)
            linePos = next(lines)
            pos = int(linePos)
            head = stringToListNode(lineNode,pos)
            #pos= stringToListNode(pos)
            # pos=1

            ret = Solution().hasCycle(head)

            out = str(ret)
            print(out)

        except StopIteration: #没有下一个元素则会触发 StopIteration 异常
            break

if __name__ == '__main__':
    main()

哈希表,set()函数要求元素不能重复 ,这里时间复杂度和空间复杂度均是O(n)

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        seen = set()

        while head:
            if head in seen: #2.新加入的节点已存在,出现重复,即为环
                return True
            #注意要在while里面
            seen.add(head) #1.先加入节点,set()用add加入新元素,而不是append()
            head=head.next
        return False

enumerate

grid=[[1,1,0,0,1,0],
      [1,0,0,0,0,1],
      [0,0,1,1,1,1],
      [0,0,0,1,1,0]]
for k_row,v_row in enumerate(grid):
    print(k_row,v_row)
    for k_column,v_column in enumerate(v_row):
        print(k_column,v_column)

运行效果

0 [1, 1, 0, 0, 1, 0]
0 1
1 1
2 0
3 0
4 1
5 0
1 [1, 0, 0, 0, 0, 1]
0 1
1 0
2 0
3 0
4 0
5 1
2 [0, 0, 1, 1, 1, 1]
0 0
1 0
2 1
3 1
4 1
5 1
3 [0, 0, 0, 1, 1, 0]
0 0
1 0
2 0
3 1
4 1
5 0

  

岛屿最大面积

图的遍历: 

    1.深度优先遍历(DFS)   :以第一个点连第二点,第二个点连第三个点为先(串联方式)。

    2.广度优先遍历(BFS):以起始点周围相邻点都被访问为先(扩散方式)

这里的递归边界有两种:1.超出下标(小于下标),即靠边(贪吃蛇撞墙)     2.旁边是0(水)

⓵ 在递归边界内,向四个方向深度优先遍历“陆地”并+1求和,且置为0

② 主函数中,不断更新最大岛屿最大值


from typing import List

class Solution:
    # 1.从一点向四个方向深度优先遍历,计算岛屿总面积
    def dfs(self, grid, cur_i, cur_j) -> int: #递归
        if cur_i < 0 or cur_j < 0 or cur_i == len(grid) or cur_j == len(grid[0]) or grid[cur_i][cur_j] != 1:  # 关键点1 判断前进一位这块是不是岛屿,如果是岛屿就向下执行
            return 0 #注意最后一个条件grid[cur_i][cur_j] != 1 同时具有回溯功能
        grid[cur_i][cur_j] = 0  # 初始化为0,还没遇到岛屿的时候,同时#之后被访问过的陆地设为0,不然计算机会一直持续运行下去
        ans = 1  # 关键点2 每次计数加几 ,这里遇到一个小块,一次当然加1了
        for di, dj in [[0, 1], [0, -1], [1, 0], [-1, 0]]: #di是行方向0 0 1 -1,dj是列方向1 -1 0 0 必须满足当di为0时,dj才能移动,当di为0时,di才能移动
            next_i, next_j = cur_i + di, cur_j + dj # 向->上下右左
            ans += self.dfs(grid, next_i, next_j)  # 关键点3 遇到岛屿“1”,就加1,实现递归
        return ans
    # 2.比较每个岛屿面积,取最大值
    def max_Area(self,grid:List[List[int]])->int:
        ans=0
        #这个循环是出发点
        print(grid)
        for k_row,v_row in enumerate(grid): #key-value
            for k_column,v_column in enumerate(v_row): #这个row就相当于grid[0],只不过里面的0由row控制
                #作用就是取坐标而已,这样才能在接下来进行四个方向的深度遍历
                ans = max(self.dfs(grid, k_row, k_column), ans)  # 传入二维list进行面积计算,逐个比较出最大值

        return ans

if __name__ == '__main__':
    #4*5
    grid=[[1,1,0,0,1,0],
          [1,0,0,0,0,1],
          [0,0,1,1,1,1],
          [0,0,0,1,1,0]]

    result=Solution().max_Area(grid) #注意调用类时要加上()
    print(result)

运行

[[1, 1, 0, 0, 1, 0], [1, 0, 0, 0, 0, 1], [0, 0, 1, 1, 1, 1], [0, 0, 0, 1, 1, 0]]
0 0
0 1
0 2
0 3
0 4
0 5
1 0
1 1
1 2
1 3
1 4
1 5
2 0
2 1
2 2
2 3
2 4
2 5
3 0
3 1
3 2
3 3
3 4
3 5
7

深度优先搜索 + 栈

未访问的陆地放在栈里

from typing import List

class Solution:

    def max_Area(self,grid:List[List[int]])->int:
        ans=0
        for i,l in enumerate(grid):
            for j,n in enumerate(l):
                cur=0
                stack=[(i,j)]
                while stack: #只要栈 stack 不为空,就说明我们还有土地待访问
                    cur_i,cur_j=stack.pop()
                    if cur_i<0 or cur_j<0 or cur_i==len(grid) or cur_j==len(grid[0]) or grid[cur_i][cur_j]!=1:
                        continue #当不满足则终止本次循环(不再往下执行)开启下一轮循环,满足则继续向下执行
                    cur+=1
                    grid[cur_i][cur_j]=0 #被访问过的陆地设为0,不然计计算机会一直持续运行下去
                    for dx,dy in [[0,1],[0,-1],[1,0],[-1,0]]:
                        next_i,next_j=cur_i+dx,cur_j+dy
                        stack.append((next_i,next_j)) #栈插入新的坐标,注意坐标要用()包起来
                ans =max(ans,cur)
        return ans

if __name__ == '__main__':
    #4*5
    grid=[[1,1,0,0,1,0],
          [1,0,0,0,0,1],
          [0,0,1,1,1,1],
          [0,0,0,1,1,0]]

    result=Solution().max_Area(grid) #注意调用类时要加上()
    print(result)

运行

栈  [(0, 0)]
栈  [(0, 1)]
栈  [(0, 2)]
栈  [(0, 3)]
栈  [(0, 4)]
栈  [(0, 5)]
栈  [(1, 0)]
栈  [(1, 1)]
栈  [(1, 2)]
栈  [(1, 3)]
栈  [(1, 4)]
栈  [(1, 5)]
栈  [(2, 0)]
栈  [(2, 1)]
栈  [(2, 2)]
栈  [(2, 3)]
栈  [(2, 4)]
栈  [(2, 5)]
栈  [(3, 0)]
栈  [(3, 1)]
栈  [(3, 2)]
栈  [(3, 3)]
栈  [(3, 4)]
栈  [(3, 5)]
7

广度优先搜索BFS -队列  把上面的栈换成队列就可以,注意弹出方法用popleft()

每次从队首取出土地,并将接下来想要遍历的土地放在队尾

import collections
from typing import List

class Solution:

    def max_Area(self,grid:List[List[int]])->int:
        ans=0
        for i,l in enumerate(grid):
            for j,n in enumerate(l):
                cur=0
                queue=collections.deque([(i,j)])
                print("队列 ",queue)
                while queue: #只要栈 stack 不为空,就说明我们还有土地待访问
                    cur_i,cur_j=queue.popleft()
                    if cur_i<0 or cur_j<0 or cur_i==len(grid) or cur_j==len(grid[0]) or grid[cur_i][cur_j]!=1:
                        continue #当不满足则终止本次循环(不再往下执行)开启下一轮循环,满足则继续向下执行
                    cur+=1
                    grid[cur_i][cur_j]=0 #被访问过的陆地设为0,不然计计算机会一直持续运行下去
                    for dx,dy in [[0,1],[0,-1],[1,0],[-1,0]]:
                        next_i,next_j=cur_i+dx,cur_j+dy
                        queue.append((next_i,next_j)) #栈插入新的坐标,注意坐标要用()包起来
                ans =max(ans,cur)
        return ans

if __name__ == '__main__':
    #4*5
    grid=[[1,1,0,0,1,0],
          [1,0,0,0,0,1],
          [0,0,1,1,1,1],
          [0,0,0,1,1,0]]

    result=Solution().max_Area(grid) #注意调用类时要加上()
    print(result)

运行

队列  deque([(0, 0)])
队列  deque([(0, 1)])
队列  deque([(0, 2)])
队列  deque([(0, 3)])
队列  deque([(0, 4)])
队列  deque([(0, 5)])
队列  deque([(1, 0)])
队列  deque([(1, 1)])
队列  deque([(1, 2)])
队列  deque([(1, 3)])
队列  deque([(1, 4)])
队列  deque([(1, 5)])
队列  deque([(2, 0)])
队列  deque([(2, 1)])
队列  deque([(2, 2)])
队列  deque([(2, 3)])
队列  deque([(2, 4)])
队列  deque([(2, 5)])
队列  deque([(3, 0)])
队列  deque([(3, 1)])
队列  deque([(3, 2)])
队列  deque([(3, 3)])
队列  deque([(3, 4)])
队列  deque([(3, 5)])
7

N-皇后 回溯算法

不断尝试,直到不能尝试为止,回退到上一步,继续尝试,其实是个深度优先遍历到过程


from typing import List
"""
if后面的括号可要可不要
参数设置的固定类型可要可不要
"""
class Solution:
    def __init__(self):
        self.res = []  # 用self是为了把二维list返回
    # 新加入的皇后是否符合要求
    def isvalidqueen(self, trace: List[str], row: int, col: int) -> bool:
        nLen = len(trace)
        # 列
        for item in trace: #先一行一行(即一个元素一个元素的检查)注意不是二维数组
            if item[col] == 'Q': #该"列"上的第col+1个字符有没有Q
                return False #有返回False对应not False,没有Q,就跳出该if语句,继续执行下一行
        # 右上 (row -1,col +1)上右
        for i ,j in zip(range(row -1, -1, -1), range(col +1, nLen)): #zip合并两个list(不是加),把范围弄成k-v一样分别赋给i,j
            #-1表示倒序,右上时需要行到序,从尾往前,row 是从0开始的,col也是从0开始的
            print(i ,j)
            if(trace[i][j] == 'Q'):
                return False
        # 左上 (row -1,col -1)左上
        for i ,j in zip(range(row -1 ,-1 ,-1), range(col -1, -1, -1)): #左上时需要行列都倒序
            if(trace[i][j] == 'Q'):
                return False
        return True #返回后的条件是not True=False 即if语句不执行,跳出,进行下一行代码
    def replacechar(self, string :str, idx :int, char: str )-> str: # trace[row] ,col ,'Q'
        strList = list(string) #字符串变成一维数组
        strList[idx] = char #相当于trace[row][col=idx] = char
        s = ''.join(strList)
        return s
    def backtrace(self, trace: List[str], row: int):
        #print(row ,end="")
        # 停止条件 针对方阵
        if(len(trace) == row): #如果进行完成,就把字符全部放入数组
            ret = list(trace)  # list加入list 形成二维list
            self.res.append(ret)
            return
        for col in range(len(trace)):
            if(not self.isvalidqueen(trace, row, col)):  # 判断列 正对角线 副对角线 上是否存在Q
                continue #not false时即True ,有Q满足continue则往上返回到for循环条件col+1,否则跳过col不变进行下一行代码运行放上Q并row+1,没有Q就往下执行
            # 注意下面三行代码要放在for循环里面
            trace[row] = self.replacechar(trace[row] ,col ,'Q')  # 将当前坐标上的.换成Q
            self.backtrace(trace, row +1)  #这里可不是退回上一步,而是保证row+1 使得新的行查看是否满足放Q
            trace[row] = self.replacechar(trace[row] ,col ,'.')  # 检查上一行,将Q重新换成. 这一步放在backtrace函数后面才真正完整的构成回溯

    def solveNQueens(self, n: int) -> List[List[str]]:
        s = '. ' *n #一个元素构成n个字符
        trace = [s] *n #有[]但目前还不是数组,实际上还是一位数组,只不过每个元素有n个字符
        print("一维的7 × 7结构" ,trace)  # 后续还需要再把里面的'.......'进行[]起来
        self.backtrace(trace, 0)  # 0表示row初始,从第一行开始
        return self.res

if __name__ == '__main__':
    n=int(input("please input n="))  # 直接  入的内容会当作字符串形式,需int强转
    result=Solution().solveNQueens(n)  # 注意  用类时要加上()
    for i in range(0,len(result[0])):
        print(result[i])

运行

please input n=7
一维的7 × 7结构 ['.......', '.......', '.......', '.......', '.......', '.......', '.......']
012345456753456345234545343456745523456734556234564345667423453445634545612345456734567545345664234567453455674534565645672345545563455664567234544344344566712345456345674567345455456234565345665645675455234567456563454545523455673456745123455645673456734564565623456534554556723456754553455623456564563456734567456512345456734567523455454534565645672345545567456566345562345645545345674567345645123456764344344452345674566534565455234567456563454567534545672344566345455673456745123456453456434523445676344562345653456723455456734345452345345634556745

['Q......', '..Q....', '....Q..', '......Q', '.Q.....', '...Q...', '.....Q.']
['Q......', '...Q...', '......Q', '..Q....', '.....Q.', '.Q.....', '....Q..']
['Q......', '....Q..', '.Q.....', '.....Q.', '..Q....', '......Q', '...Q...']
['Q......', '.....Q.', '...Q...', '.Q.....', '......Q', '....Q..', '..Q....']
['.Q.....', '...Q...', 'Q......', '......Q', '....Q..', '..Q....', '.....Q.']
['.Q.....', '...Q...', '.....Q.', 'Q......', '..Q....', '....Q..', '......Q']
['.Q.....', '....Q..', 'Q......', '...Q...', '......Q', '..Q....', '.....Q.']

雨水积水

双指针,巧妙公式法

class Solution:
    def trap(self, height: List[int]) -> int:
        n = len(height)
        # 左指针从左往右记录s1在上升的柱子总高度 和  右指针从右往左记录s2在上升(梯子)的柱子总高度
        s1, s2 = 0, 0
        max1, max2 = 0, 0
        for i in range(n):
            if height[i] > max1:
                max1 = height[i]
            if height[n - i - 1] > max2:
                max2 = height[n - i - 1]
            s1 += max1
            s2 += max2
        # 积水面积 = S1 + S2 - 矩形面积 - 柱子面积
        res = s1 + s2 - max1 * len(height) - sum(height) #关键点,神奇的数学公式
        return res

双指针,正常推演

import json
from typing import List


class Solution:
    def trap(self, height: List[int]) -> int:

        if not height: return 0
        n=len(height)

        left,right=0,n-1 #
        leftMax,rightMax=height[0],height[n-1]
        ans=0

        while left<right: #这里可能取<=根据准确

            leftMax=max(height[left],leftMax)
            rightMax=max(height[right],rightMax)
            if leftMax < rightMax:
                ans += leftMax - height[left]
                left+=1
            else:
                ans+=rightMax-height[right]
                right-=1
        return ans

def stringToIntegerList(input):
    return json.loads(input)

def main():
    import sys
    import io
    def readlines():
        for line in io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8'):
            yield line.strip('\n')

    lines = readlines()
    while True:
        try:
            line = next(lines)
            height = stringToIntegerList(line);

            ret = Solution().trap(height)

            out = str(ret);
            print(out)
        except StopIteration:
            break

if __name__ == '__main__':
    main()

运行

[0,1,0,2,1,0,1,3,2,1,2,1]
6

python文档搜索

也可以下载Dash软件来管理API文档(但是没有中文版,要习惯看英文)

链表https://stackabuse.com/python-linked-lists

删除链表的倒数第N个节点-快慢针

import json
"""
删除链表的倒数第N个节点
解决:快慢针
从表头算就是 L-n+1
"""
class ListNode:
    def __init__(self, val=0, next=None): #后面两个都是初始化
        self.val = val
        self.next = next
class Solution:
    def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
        dummy=ListNode(0,head) #设置哑结点,就是在链表头之前的指向链表头的节点(如果不设置,链表只能从表头开始)
        first = head
        second = dummy
        for i in range(n):
            print("先让快指针走:",i)
            first = first.next
        print("当i=n+1时,快指针带动慢指针一起走")
        while first: ##当first到达尾部指向为空时,second指针则刚好指向n+1个结点
            first = first.next
            second = second.next
        #dummy假指针保证倒数第n个数前一个结点(倒数第n+1个数)的指针跳过倒数第n个数指向倒数第n-1个数
        second.next = second.next.next
        return dummy.next
def stringToIntegerList(input):
    return json.loads(input)
def stringToListNode(input):
    # Generate list from the input
    numbers = stringToIntegerList(input)
    print(numbers)
    # Now convert that list into linked list
    dummyRoot = ListNode(0) #还是那句思考,声明或构造一个ListNode,并且(0),这里还只是头结点
    ptr = dummyRoot #这可不是赋值,指向头结点即ptr为哑结点 链表表头之前指向链表头的结点 同时为ptr声明或说构造一个ListNode类型
    for number in numbers:
        ptr.next = ListNode(number) #因为是哑结点的假指针指向的是头指针
        ptr = ptr.next #接着循环下去
    ptr = dummyRoot.next #让它具有哑结点的假指针
    return ptr

def listNodeToString(node):
    if not node:
        return "[]"

    result = ""
    while node:
        result += str(node.val) + ", " #注意它这里是逗号加空格
        node = node.next
    return "[" + result[:-2] + "]" #-2的意思是去掉最后一个数字后面的逗号,如" 5, ",再加上],一维直接写列:-2

def main():
    import sys
    import io
    def readlines():
        for line in io.TextIOWrapper(sys.stdin.buffer, encoding='utf-8'):
            yield line.strip('\n')

    lines = readlines()
    while True:
        try:
            line = next(lines) #next(iterobject,defalt)
            head = stringToListNode(line);
            line = next(lines)
            n = int(line);

            ret = Solution().removeNthFromEnd(head, n)

            out = listNodeToString(ret);
            print(out)
        except StopIteration:
            break

if __name__ == '__main__':
    main()

完全人工敲

import io
import json
import sys
"""
mac冒号 shift+command+回车
"""
class ListNode:
    def __init__(self,val=0,next=None): #next表示结点,None为初始化没有结点
        self.val=val
        self.next=next

def stringToIntegerList(input):
    return json.loads(input) #注意这里是loads不是load,有个s

def stringToListNode(input):
    numbers=stringToIntegerList(input)
    print(numbers)
    dummyRoot=ListNode(0)
    ptr = dummyRoot
    for number in numbers: #注意这里不是range(numbers)
        ptr.next=ListNode(number) #这个.next随便声明
        ptr=ptr.next
    ptr = dummyRoot.next #ptr指向哑结点的假指针
    return ptr

class Solution:
    def deleteNthFromEnd(self,head:ListNode,n: int):
        dummy=ListNode(0,head)
        first=head #头结点
        second=dummy #哑结点 也就是正数 L-n+1
        print(dummy,dummy.next)
        print(second,second.next)

        for i in range(n):
            print(i)
            first=first.next
            print(first.next)

        while first:#当first进行完for循环,没有遍历指向到链表表尾无结点时
            first=first.next
            second=second.next
            print("first=",first)
            print("second=",second)
        second.next=second.next.next

        return dummy.next #这个初始时还在头部,返回时逐个返回结点

def ListNodeToString(node):
    #node是从算法处理ListNode得来的node,具有ListNode类型结果
    if not node:
        return "[]"
    result= ""
    while node:
        result +=str(node.val)+"," #逗号没有加空格
        node=node.next
    return "["+result[:-1]+"]"

def main():
    def readlines():
        for line in io.TextIOWrapper(sys.stdin.buffer,encoding='utf-8'):
            yield line.strip('\n')

    lines=readlines()

    while True:
        try:
            line=next(lines)
            headListNode=stringToListNode(line)
            line_number=next(lines)
            n=int(line_number) #强转
            node=Solution().deleteNthFromEnd(headListNode,n)
            out=ListNodeToString(node)
            print(out)
        except StopIteration:
            break
if __name__ == '__main__':
    main()

运行效果

[1,2,3,4,5,6,7,8]
[1, 2, 3, 4, 5, 6, 7, 8]
3
<__main__.ListNode object at 0x15691f100> <__main__.ListNode object at 0x15691f0a0>
<__main__.ListNode object at 0x15691f100> <__main__.ListNode object at 0x15691f0a0>
0
<__main__.ListNode object at 0x15691cf40>
1
<__main__.ListNode object at 0x15691cee0>
2
<__main__.ListNode object at 0x15691ce80>
first= <__main__.ListNode object at 0x15691ce80>
second= <__main__.ListNode object at 0x15691f0a0>
first= <__main__.ListNode object at 0x15691ce20>
second= <__main__.ListNode object at 0x15691cfd0>
first= <__main__.ListNode object at 0x15691cdc0>
second= <__main__.ListNode object at 0x15691cf40>
first= <__main__.ListNode object at 0x15691cd60>
second= <__main__.ListNode object at 0x15691cee0>
first= None
second= <__main__.ListNode object at 0x15691ce80>
[1,2,3,4,5,7,8]

第N个数字

题型讲解参考

"""
1234567891011121314151617181920212223.....
n>9位数:
第count=1行:10111213...979899 共10**1*9*2=90*2=180位数   每个数的位数count+1=2
第count=2行:100101102103...997998999 共10**2*9*3=900*3=2700位数 每个数的位数count+1=3
第count=3行:1000 1001 1002 ... 9997 9998 9999 共10***3*9*4=36000位数 每个数的位数count+1=3
"""
class Solution:
    def findNthDigit(self, n: int) -> int:
        if n < 10:
            return n
        n -= 9 #减去前面9个
        count = 1
        while True: #循环
            num = 10 ** count * 9 * (count + 1)
            if n > num: #n为减去9之后的n,如果仍然大于第一行180位数
                n -= num #n循环减num
                print("n=",n)
                count += 1 #需定位到下一行
            else:
                i, j = divmod(n, (count + 1)) #很重要
                print("商=",i,"余数=",j)
                if not j: #j是None空,也就是没有余数,余数为0,整除
                    print("count=",count,"没有余数",str(10 ** count + i - 1))
                    ##i有时会是两位数,所以不能直接返回int(str(i-1))
                    return int(str(10 ** count + i - 1)[-1])#后面的()[-1],表示前面数字倒数第一位,这里取个位
                else:
                    print("count=",count,"有余",str(10 ** count + i),"从0,1,2,...开始数",j-1)
                    return int(str(10 ** count + i)[j - 1])

运行结果

2711
n= 2522
商= 840 余数= 2
count= 2 有余 940 从0开始数 1
4
8
8
19
商= 5 余数= 0
count= 1 没有余数 14
4
189
商= 90 余数= 0
count= 1 没有余数 99
9

表现最好的最长时间段

"""
score = [1, 1, -1, -1, -1, -1, 1]
presum = [0, 1, 2, 1, 0, -1, -2, -1] #前缀和
前缀和一开始设置为0作为第一个元素presum[0]=0,
presum[1]=presum[0]+score[0]=0+1=1
presum[2]=presum[1]+score[1]=1+1=2
presum[3]=presum[2]+score[2]=2-1=1
presum[4]=presum[3]+score[3]=1-1=0
presum[5]=presum[4]+score[4]=0-4=-1
presum[6]=presum[5]+score[5]=-1-1=-2
presum[7]=presum[6]+score[6]=-2+1=-1
"""
class Solution:
    def longestWPI(self, hours: List[int]) -> int:
        n = len(hours)
        # 大于8小时计1分 小于等于8小时计-1分
        score = [0] * n #初始化[0, 0, 0, 0, 0, 0, 0]
        for i in range(n):
            if hours[i] > 8:
                score[i] = 1
            else:
                score[i] = -1
        # 前缀和
        presum = [0] * (n + 1) #初始化比hours数组多一位元素的0数组
        for i in range(1, n + 1): #从第2为开始计算presum与score的关系
            presum[i] = presum[i - 1] + score[i - 1]
        print("    score=",score)
        print("presum=",presum)
        ans = 0
        stack = []
        # 顺序生成单调栈,栈中元素从第一个元素开始严格单调递减,最后一个元素肯定是数组中的最小元素所在位置
        #presum[stack[-1]] 单调递减
        for i in range(n + 1):
            if not stack or presum[stack[-1]] > presum[i]: #还未压入新的stack.append(i)时,i=stack[-1]+1
                stack.append(i) #是把下标压进去
                print(i,stack,stack[-1]) #stack[-1]=i
        # 倒序扫描数组,求最大长度坡
        i = n #stack[-1]表示0,1,2,3,4,5,6的进栈的最后一位,即栈顶,数组最后一位
        while i > ans: #从后往前自然i>stack[-1]栈顶元素
            while stack and presum[stack[-1]] < presum[i]: #关键点1:满足presum倒序扫描大于栈中下标得来的presum[]条件的 进入比较处理
                print("压入了元素就有栈时:stack[-1]=", stack[-1], "presum[stack[-1]]=", presum[stack[-1]],"presum[",i,"]=",presum[i])
                print(ans,i - stack[-1])
                ans = max(ans, i - stack[-1]) #关键点2:求最大差值为"表现良好的最长时间段"
                stack.pop() #数组也有pop(),弹出数组尾部元素相当于弹出栈顶元素
                if not stack:
                    print("表现良好的最长时间段有:")
                    for x in range(i):
                        print(hours[x])  # 打印出996
            i -= 1
        return ans #举例中是 3-0=3刚好满足"表现良好的最长时间段"

运行效果

[9,9,6,0,6,6,9]
    score= [1, 1, -1, -1, -1, -1, 1]
presum= [0, 1, 2, 1, 0, -1, -2, -1]
0 [0] 0
5 [0, 5] 5
6 [0, 5, 6] 6
压入了元素就有栈时:stack[-1]= 6 presum[stack[-1]]= -2 presum[ 7 ]= -1
0 1
压入了元素就有栈时:stack[-1]= 5 presum[stack[-1]]= -1 presum[ 4 ]= 0
1 -1
压入了元素就有栈时:stack[-1]= 0 presum[stack[-1]]= 0 presum[ 3 ]= 1
1 3
表现良好的最长时间段有:
9
9
6
长度为: 3

962. 最大宽度坡

"""
示例1
输入:[6,0,8,2,1,5]
输出:4
解释:
最大宽度的坡为 (i, j) = (1, 5): A[1] = 0 且 A[5] = 5.
示例2
输入:[9,8,1,0,1,9,4,0,4,1]
输出:7
解释:
最大宽度的坡为 (i, j) = (2, 9): A[2] = 1 且 A[9] = 1.
"""
class Solution:
    def maxWidthRamp(self, nums: List[int]) -> int:
        ans = 0
        m = float('inf') #inf字符对应一个很大的正数值
        for i in sorted(range(len(nums)), key=nums.__getitem__):
            #nums={6:0,0:1,8:2,2:3,1:4,5:5}对其按key排序为:{0:1,1:4,2:3,5:5,6:0,8:2} 再输出下标即1 4 3 5 0 2
            print("i=",i,"m=",m,"i-m=",i-m) #注意这里的i是按1 4 3 5 0 2
            ans = max(ans, i - m)
            print("ans=",ans)
            m = min(m, i)
            print("m=",m)
        return ans

运行效果

[6,0,8,2,1,5]
i= 1 m= inf i-m= -inf
ans= 0
m= 1
i= 4 m= 1 i-m= 3
ans= 3
m= 1
i= 3 m= 1 i-m= 2
ans= 3
m= 1
i= 5 m= 1 i-m= 4
ans= 4
m= 1
i= 0 m= 1 i-m= -1
ans= 4
m= 0
i= 2 m= 0 i-m= 2
ans= 4
m= 0
4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alex-panda

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值