top30

方法论

回溯:无序组合;字符串切割;集合子集;有序排列;棋盘问题

  1. 组合:一个元素不能重复使用,用startindex控制 ,下次递归 (i+1)
    【元素可无限选取,下次递归i】【原数组,包含重复元素,同一树层,去重,对数组排序used】
  2. 分割:
  3. 子集:找树的所有节点,在终止条件前,就手机结果
  4. 排列:used标记用过的元素,用过的不能用
def bk(     ,   ,  startindex, used, path,res)
void backtracking(参数){
	if (终止条件):
		{收集结果
		 return }
 		
	for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) : #处理集合的每一个元素
		{处理节点
		 backtracking(路径,选择列表)#递归函数
		 回溯操作 #撤销处理节点的
		}
}

动态规划

动态规划5步曲

  1. 确定dp数组 & 下标含义
  2. 递推公式
  3. dp数组初始化 【涉及乘法,dp[0] =1 】
  4. 遍历顺序
  5. 举例推导dp数组

背包问题

  1. 01背包(每件物品只能用0或1次):n件物品,最多装重量w的背包,第i件物品的重量为weight[i],价值value[i],每件物品只能装1次,求背包价值最大总和
  • 二维dp, dp[i][j]:从下标[0,i]任取,放进容量为j的背包,价值最大为dp[i][j]
    dp[i][j] = max( dp[i-1][j] , dp[i-1][j-weight[i]]+ value[i]) 拿不拿第i个物品
  • 一维dp, 先遍历物品i, 在倒序遍历容量j【倒序是为了保证:物品只拿一次】
    dp[j] = max(dp[j], dp[j-weight[i]] + value[i])

  1. 完全背包(每个物品数量无限)
    先遍历物品i,或者先正序遍历物品j都行
    【组合数:外层for物品,内层for容量】【排列数:外层for容量,内层for物品】

打家劫舍 dp[i]:下标i内(包括i)的房子,最多偷的金额为dp[i]

  1. 2个相邻都被偷,会报警 dp[i] = max(dp[i-1], dp[i-2]+nums[i]) 其实就是nums[i]偷不偷
  2. 房屋成环 res1 = rob(nums[:-1]) res2 = rob(nums[1:]) res = max(res1, res2)
  3. 房屋树形 dp[0]代表不偷该节点,得到的最大钱, dp[1]代表偷该节点,得到的最大钱

股票买卖的最佳时机dp[i][0]第i天持有股票,所获最大钱 dp[i][1]第i天不持有股票,所获最大钱

  1. 只能买卖1次 dp[i][0] = max(d[i-1][0], -price[i]) dp[i][1] = max(dp[i-1][0]. dp[i-1][0]+price[i])
  2. 多次买卖 dp[i][0] = max(d[i-1][0], -price[i] + dp[i-1][1])
  3. 只能买卖2次
  4. 只能买卖k次 dp[i][j]【 j=0不操作, j= 2k-1第k次买入,j=2k第k次卖出 】
  5. 含有冷冻期 dp[i][j]【 j=0持有股票, j=1不持有股票也不在冷冻期,也不是刚卖,j=2冷冻期,j=3刚卖出 】
  6. 卖出有手续费 dp[i][1] = max(dp[i-1][0]. dp[i-1][0]+price[i]-fee)

子序列问题

  1. 在一个序列里面:求最长递增子序列长度【 dp[i]:子序列答案以nums[i]结尾的最长递增子序列的长度】
    1.1 不连续 for i,遍历j<i, 如果nums[i] > nums[j],dp[i] = max(dp[i], dp[j]+1)
    1.2 连续 if num[i[ > nums[i-1]:dp[i] = dp[i-1]+1
    【求连续数组的最大和】 dp[i] = max(dp[i-1]+nums[i], nums[i])
  2. 两个序列:求最长公共子序列的长度【 dp[i][j]:A[0,i-1]和B[0,j-1]最长连续公共子序列的长度】
    2.1 不连续 if A[i-1]== B[j-1]:dp[i][j] = dp[i-1][j-1]+1 else:dp[i][j] = max(dp[i-1][j], dp[i][j-1])
    2.2 连续 if A[i-1]== B[j-1]:dp[i][j] = dp[i-1][j-1]+1

回文子串

1.两数之和

在这里插入图片描述

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        record = {} #key:数 value:下标
        for index, i in enumerate(nums):
            if target-i in record:
                return [index, record[target-i]]
            else:
                record[i] = index

5.最长的回文子串

在这里插入图片描述

'''
1.dp[i][j]:区间[i:j]左闭右闭的子串,是否是回文子串
2.如果s[i] != s[j], dp[i][j] = False
  如果s[i]== s[j]【1.下标相同,是回文子串 ; 
                   2.下标相差为1,‘aa’,也是回文; 
                    3.下标相差大于1,如果dp[i+1][j-1]也是回文,才是回文】 
3.初始化:dp[i][j] = False
4.i从大到小, j从小到大
'''
class Solution:
    def longestPalindrome(self, s: str) -> str:
        dp = [[False] * len(s) for _ in range(len(s))]
        maxlenth = 0
        left = 0
        right = 0
        for i in range(len(s) - 1, -1, -1):
            for j in range(i, len(s)):
                if s[j] == s[i]:
                    if j - i <= 1 or dp[i + 1][j - 1] == True:
                        dp[i][j] = True
                if dp[i][j] and j - i + 1 > maxlenth:
                    maxlenth = j - i + 1
                    left = i
                    right = j
        return s[left:right + 1]

2.两数相加

在这里插入图片描述

class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
class Solution:
    def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
        cur = dummy_head = ListNode(next = None)
        carry = 0
        while l1 or l2 or carry :
            value = (l1.val if l1 else 0)+(l2.val if l2 else 0)+carry
            cur.next =  ListNode(val= value%10)
            carry = value//10
            cur = cur.next
            
            if l1 :  #加入l1本来就是空,如果if l1.next会引发错误
                l1 = l1.next
            if l2 :
                l2 = l2.next
        return dummy_head.next
'''递归'''
class Solution:
    def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode], carry=0) -> Optional[ListNode]:
    
        if l1 is None and l2 is None: 
            return ListNode(carry) if carry else None  # 如果进位了,就额外创建一个节点
   
        if l1 is None:    # 确保l1不空,否则l1.val会报错
        	l2, l1 = l1, l2
            
        carry += (l1.val ) + (l2.val if l2 else 0) 
        l1.val = carry % 10  # 每个节点保存一个数位
        l1.next = self.addTwoNumbers(l1.next , l2.next if l2 else None, carry // 10)  # 进位
        return l1

1480.一维数组的动态和

在这里插入图片描述

class Solution:
    def runningSum(self, nums: List[int]) -> List[int]:
        dp = [0] * len(nums)
        dp[0] = nums[0]
        for i in range(1, len(nums)):
            dp[i] = dp[i - 1] + nums[i]
        return dp

4.寻找两个正序数组的中位数【难!】

在这里插入图片描述

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        m = len(nums1)
        n = len(nums2)
        target = (m+n)//2+1
        l1 = l2 = 0
        cur=pre = 0
        for i in range(target):
            pre = cur 
            if (l2 >= n) or (l1 < m and  nums1[l1] <nums2[l2])   :
                cur = nums1[l1]
                l1 += 1
            else:
                cur = nums2[l2]
                l2 += 1
        
        if (m+n)%2 ==1 : return cur
        else : return (cur+pre)/2

3.无重复字符的最长子串

在这里插入图片描述

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        if len(s) <= 1: return len(s)
        left, right = 0 ,0
        maxlen = 0
        while right< len(s):
            if s[right] not in s[left:right]:
                maxlen = max(maxlen,right-left+1)
                right += 1
            else :   
                while s[right] in s[left:right]:
                    left += 1
            
        return maxlen

704.二分查找

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        left ,right = 0, len(nums)-1
        while left <= right:  # target在闭区间【left, right】
            mid = (left+right)//2
            if nums[mid] == target:
                return mid
            elif nums[mid] < target:
                left = mid +1
            else:
                right = mid-1
        return -1

20.有效的括号

在这里插入图片描述

class Solution:
    def isValid(self, s: str) -> bool:
        stack = []
        mapping = {'(':")", "[":']',"{":"}"}
        for i in s:
            if i in mapping:
                stack.append(mapping[i])
            elif stack and stack[-1] == i:  #栈顶元素和当前元素匹配
                stack.pop()
            else:
                return False
        return False if stack else True

09.用两个栈实现队列

class MyQueue:
    def __init__(self):
        self.stack_in = []
        self.stack_out = []
    def push(self, x: int) -> None:
        self.stack_in.append(x)
        
    def pop(self) -> int:  #取出栈顶元素,并移除
        if self.empty():
            return None
        if self.stack_out:
            return self.stack_out.pop()
        else:
            for i in range(len(self.stack_in)):
                self.stack_out.append(self.stack_in.pop())
            return self.stack_out.pop()
            
    def peek(self) -> int:
        ans = self.pop()
        self.stack_out.append(ans)
        return ans
        
    def empty(self) -> bool:
        return  not (self.stack_in or self.stack_out)

217.存在重复元素

集合去重后元素个数 == 原数组的元素个数

class Solution:
    def containsDuplicate(self, nums: List[int]) -> bool:
        return len(nums) != len(set(nums))

70.爬楼梯

在这里插入图片描述

class Solution:
    def climbStairs(self, n: int) -> int:
        #dp[i] 爬到第i届的方法数
        #dp[i] = dp[i-1] + dp[i-2]
        # dp[0] = 0  dp[1] = 1 
        if n <= 1: 
        	return n 
        	
        dp = [0] * (n+1)
        dp[1]  = 1
        dp[2] = 2
        for i in range(3, n+1):
            dp[i] = dp[i-1] + dp[i-2]
        return dp[n]
            

14.最长公共前缀

在这里插入图片描述
在这里插入图片描述

'''
内置函数zip+ set
'''
class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        ans = ''
        for i in list(zip(*strs)):
            if len(set(i)) == 1:
                ans += i[0]
            else:
                break
        return ans
class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        start = strs[0]
        for index, char in enumerate(start):
            for s in strs:
                if index == len(s) or s[index] != char:  #1.strs[s][index] != start[index]
                    return start[:index]
        return start

42.接雨水

在这里插入图片描述
在这里插入图片描述

'''
找下标i的柱子,左边最高[:i+1]和右边最高[i: ]的柱子【要包括本柱子】
每个柱子的雨水 = min(左边最高,右边最高)-柱子高 
'''
class Solution:
    def trap(self, height: List[int]) -> int:
        left_height = [0] * len(height)
        right_height = [0] * len(height)
        left_height[0] = height[0]
        right_height[-1] = height[-1]
        for i in range(1, len(height)):
            left_height[i] = max(height[i], left_height[i-1])
        for i in range(len(height)-2, -1,-1):
            right_height[i] = max(right_height[i+1], height[i])

        res = 0
        for i in range(len(height)):
            res += min(left_height[i], right_height[i])- height[i]
        return res

11.盛最多水的容器

在这里插入图片描述
在这里插入图片描述

class Solution:
    def maxArea(self, height: List[int]) -> int:
        left, right, con = 0, len(height)-1, 0
        while left < right:
            con = max(con, min(height[left], height[right])* (right-left))
            if height[left] < height[right]:
                left += 1
            else:
                right -= 1 
        return  con

72.编辑距离

在这里插入图片描述

'''
1. dp[i][j] : 将word1[0:i]转变成word2[0:j],最少操作数
2. 如果 word1[i-1]==word2[j-1]: dp[i][j] = dp[i-1][j-1]
    如果  word[i-1]!=word2[j-1]: dp[i][j] = min(dp[i-1][j], dp[i][j-1],dp[i-1][j-1])+1
3.dp[0][j]=j dp[i][0] = i
'''
class Solution:
    def minDistance(self, word1: str, word2: str) -> int:
        dp = [[0] * (len(word2)+1) for _ in range(len(word1)+1) ]
        for i in range(len(word2)+1):
            dp[0][i] = i
        for i in range(len(word1)+1):
            dp[i][0] = i
        
        for i in range(1, len(word1)+1):
            for j in range(1, len(word2)+1):
                if word2[j-1]==word1[i-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[len(word1)][len(word2)]

200.岛屿数量

在这里插入图片描述

class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        m, n = len(grid), len(grid[0])
        visited = [[False] * n for _ in range(m)]
        dirs = [(-1, 0), (0, 1), (1, 0), (0, -1)]  # 四个方向,左,右,下,上
        result = 0

        def dfs(x, y):
            for d in dirs:
                nextx = x + d[0]
                nexty = y + d[1]
                if nextx < 0 or nextx >= m or nexty < 0 or nexty >= n:  # 越界了,直接跳过
                    continue
                if not visited[nextx][nexty] and grid[nextx][nexty] == '1':  # 没有访问过的同时是陆地的
                    visited[nextx][nexty] = True
                    dfs(nextx, nexty)
        
        for i in range(m):
            for j in range(n):
                if not visited[i][j] and grid[i][j] == '1':  #没有参观过& 陆地
                    visited[i][j] = True
                    result += 1  # 遇到没访问过的陆地,+1
                    dfs(i, j)  # 将与其链接的陆地都标记上 true

        return result
      

146.LRU缓存

在这里插入图片描述

#哈希表+双向链表
#哈希表,查询时间复杂度O(1)
#双向链表存储顺序
#删除最久未使用的数据时,需要用到链表来确定,要删的结点【即要删,双向链表的头结点】
class Node:
    def __init__(self, key=0, val=0):
        self.key = key
        self.val = val
        self.next = None
        self.pre = None

class LRUCache:
    def __init__(self, capacity: int):
        self.capacity = capacity
        self.hashmap = {}  #【key:node.key】【value:node】
        self.head = Node()  #头结点,仅仅指示位置
        self.tail = Node()   #尾结点,仅仅指示位置
        self.head.next = self.tail
        self.tail.pre = self.head

    def move(self, node):
        node.pre.next = node.next
        node.next.pre = node.pre
    
    def add_to_last(self, node):
        self.tail.pre.next = node
        node.next = self.tail
        node.pre = self.tail.pre
        self.tail.pre = node
    
    def move_to_last(self, node): #把元素从链表移除,并移到链表末尾【表示最近访问过】
        self.move(node)
        self.add_to_last(node)
       
    def get(self, key: int) -> int:
        if key not in self.hashmap:
            return -1 
        node = self.hashmap[key]
        self.move_to_last(node)  #访问了该节点
        return node.val

    def put(self, key: int, value: int) -> None:
        if key in self.hashmap:  # 如果关键字 key 已经存在,则变更其数据值 value
            node = self.hashmap[key]
            node.val = value
            self.move_to_last(node)   #访问了该节点
            return 
        if len(self.hashmap) == self.capacity:  #如果超过容量,还要加节点,则删除头结点之后的节点
            del self.hashmap[self.head.next.key]  #哈希表删掉node.key
            self.move(self.head.next)   #双向链表删掉node

        node = Node(key, value)
        self.hashmap[key] = node
        self.add_to_last(node)
        return 

15.三数之和

在这里插入图片描述

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        res = []
        nums.sort()
        for i in range(len(nums)):
            if nums[i] >0:    #剪枝
            	return res
            	
            if i > 0 and nums[i] == nums[i-1]:
            	continue

            left = i + 1
            right = len(nums)-1
            while left < right:
                cursum = nums[i] + nums[left] + nums[right]
                if cursum < 0:
                    left += 1
                elif cursum > 0:
                    right -= 1
                else : 
                    res.append( [nums[i] , nums[left] , nums[right]])
                    while left < right and nums[right] == nums[right-1]:
                        right -= 1
                    while left < right and nums[left] == nums[left+1]:
                        left += 1
                    left += 1
                    right -= 1
        return res

121.买卖股票的最佳时机【买卖1次】

在这里插入图片描述

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        #dp[i][0] 第i天不持有股票,获得最大利润
        #dp[i][1] 第i天持有股票,最大利润
        # dp[i][0] = max(dp[i-1][0], dp[i-1][1]+ price[i])
        #dp[i][1] = max(dp[i-1][1], -price[i])

        dp = [[0] * 2 for i in range(len(prices))]
        dp[0][1] = -prices[0]
        for i in range(1, len(prices)):
            dp[i][0] = max(dp[i-1][0], dp[i-1][1]+ prices[i])
            dp[i][1] = max(dp[i-1][1], -prices[i])
        return dp[len(prices)-1][0]    

9.回文数

在这里插入图片描述

class Solution:
    def isPalindrome(self, x: int) -> bool:
        return str(x) == str(x)[::-1]

53.最大子数组和

在这里插入图片描述

想到动态规划:当前状态和前一个状态,有关

'''
dp[i]:以nums[i]结尾的连续子数组的,最大和
dp[i] = max(dp[i-1]+nums[i], nums[i])
dp[0]=nums[0]
'''
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        dp = [0] * len(nums)
        dp[0] = nums[0]
        for i in range(1, len(nums)):
            dp[i] = max(dp[i-1]+nums[i], nums[i])
        return max(dp)

22.括号生成

在这里插入图片描述

class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        res = []
        self.backtracking(n, 0,0,[], res)
        return res

    
    def backtracking(self, n, left, right, path , res):
        if left == n and right == n :
            res.append(''.join(path))
            return 
        
        if left < n:
            path.append('(')
            self.backtracking(n, left+1, right, path, res)
            path.pop()
        
        if left > right:
            path.append(')')
            self.backtracking(n, left, right+1, path, res)
            path.pop()

如果是 elif right<n: 输出是[“((()))”]
如果是if right < n : 输出是[“((()))”,“(()())”,“(())()”,“(()))(”,“()(())”,“()()()”,“()())(”,“())(()”,“())()(”,“()))((”,“)((())”,“)(()()”,“)(())(”,“)()(()”,“)()()(”,“)())((”,“))((()”,“))(()(”,“))()((”,“)))(((”]=C36=20个
因为是有效的括号,所以必须要是left >right

6.N字形变换

在这里插入图片描述

class Solution:
    def convert(self, s: str, numRows: int) -> str:
        if numRows < 2: 
            return s

        res = ["" for _ in range(numRows)]
        i, flag = 0, -1
        for char in s:
            res[i] += char
            if i == 0 or i == numRows - 1: 
                flag = -flag
            i += flag
        return "".join(res)

#i的变化轨迹[numrows=3]: 0,1,2,1,0,1,2,0...N字形

21.合并两个有序链表

在这里插入图片描述

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        if not list1 : return list2
        if not list2: return list1
        
        if list1.val < list2.val:
            list1.next = self.mergeTwoLists(list1.next, list2)
            return list1
        else : 
            list2.next = self.mergeTwoLists(list1, list2.next)
            return list2

18.四数之和

在这里插入图片描述

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        rec = []
        nums.sort()
        for i in range(len(nums)):
            if nums[i] > target and nums[i] > 0: 
                return rec
            if i>0 and nums[i]==nums[i-1]:
                continue

            for j in range(i+1, len(nums)):
                if nums[i] + nums[j] > target and target > 0: #剪枝(可省)
                    break
                if j > i+1 and nums[j] == nums[j-1]: # 去重
                    continue
                left = j+1
                right = len(nums)-1
                while left < right:
                    s = nums[i] + nums[j] + nums[left] + nums[right]
                    if s == target:
                        rec.append([nums[i], nums[j], nums[left], nums[right]])
                        while left < right and nums[left] == nums[left+1]:
                            left += 1
                        while left < right and nums[right] == nums[right-1]:
                            right -= 1
                        left += 1
                        right -= 1
                    elif s < target:
                        left += 1
                    else:
                        right -= 1
        return rec

136.只出现一次的数字

在这里插入图片描述

class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        x = 0
        for i in nums:
            x ^= i 
        return x

17.09 第k个数

在这里插入图片描述

class Solution:
    def getKthMagicNumber(self, k):

         # 使用小顶堆处理(因为每次需要得到最小的数字)
        heap = [1] # 第一个元素是1

        for i in range(k):
            res = heapq.heappop(heap) # 每次取出堆中的首元素(最小元素)
            while heap and res == heap[0]:  # 忽略重复的元素
                heapq.heappop(heap)
            heapq.heappush(heap, res * 3) # 依次将当前元素乘以3,5,7的值压入堆中
            heapq.heappush(heap, res * 5)
            heapq.heappush(heap, res * 7)
        return res
# 1, 3, 5,7,9,15,21,15,25,35

10.正则表达式匹配

16.最接近的三数之和

在这里插入图片描述

class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        nums.sort()
        mindis = float('inf')
        for i in range(len(nums)):
            	
            if i > 0 and nums[i] == nums[i-1]:
            	continue

            left = i + 1
            right = len(nums)-1
            while left < right:
                cursum = nums[i] + nums[left] + nums[right]
                if cursum == target:
                    return target
                
                if abs(cursum-target) < mindis:
                    res = [nums[i] , nums[left] , nums[right]]
                    mindis = abs(cursum-target)
                
                if cursum < target:
                    left += 1
                else:
                    right -= 1
        return sum(res)

88. 合并两个有序数组【原地合并】【逆向排序】

在这里插入图片描述

class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        p1, p2, p = m - 1, n - 1, m + n - 1
        while p2 >= 0:  # nums2 还有要合并的元素
            # 如果 p1 < 0,那么走 else 分支,把 nums2 合并到 nums1 中
            if p1 >= 0 and nums1[p1] > nums2[p2]:
                nums1[p] = nums1[p1]  # 填入 nums1[p1]
                p1 -= 1
            else:
                nums1[p] = nums2[p2]  # 填入 nums2[p1]
                p2 -= 1
            p -= 1  # 下一个要填入的位置

39.组合总和

在这里插入图片描述

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        res = []
        self.backtracking(candidates, target, 0, [], res)
        return res
    
    def backtracking(self, candidates, target, startindex, path , res):
        if target == 0:
            res.append(path[:])
            return 
        
        if target < 0: return 
        
        for i in range(startindex, len(candidates)):
            path.append(candidates[i])
            self.backtracking(candidates, target-candidates[i], i, path, res)
            path.pop()

7. 整数反转

在这里插入图片描述

class Solution:
    def reverse(self, x: int) -> int:
        y, res = abs(x), 0
        of = (1 << 31) - 1 if x > 0 else 1 << 31
        while y != 0:
            res = res * 10 + y % 10
            if res > of: 
                return 0
            y //= 10
        return res if x > 0 else -res
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值