LeetCode刷题记录:1~10

本文记录了LeetCode中1到10题的解题过程,包括题目描述、解题思路、代码实现及算法分析。涵盖的题目包括两数之和、两数相加、无重复字符的最长子串、寻找两个有序数组的中位数、最长回文子串、整数反转、字符串转换整数、回文数以及正则表达式匹配。每个题目都详细阐述了解题策略和代码实现细节,适合学习和复习算法知识。
摘要由CSDN通过智能技术生成

?.,## 1. 两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

思路:

遍历一遍数组,用一个字典存储遍历结果的值和索引,由于只有一个对应答案(不考虑多答案的情况),索引不需要使用列表的形式存储。
遍历过程如下:
索引i对应的值为x,先从字典中查找是否有target-x的key,有即返回该key对应的value和i,没有则将x:i存储于字典

代码:

class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        num_index = {}
        for i in range(len(nums)):
            x = nums[i]
            target_x = target - x

            if target_x in num_index.keys():
                return [num_index[target_x], i]
            num_index[x] = i

        return []

分析:

时间复杂度:只需要扫描一遍nums即可,所以时间复杂度为O(n)
空间复杂度:用到一个字典储存,O(n)

2.两数相加

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

思路:

使用哑结点技巧
需要使用carry储存进位,l1当前值(l1为None时,只为0), l2当前值(l2为None时,只为0)和carry进行计算,最终循环终止条件,l1 == None and l2 == None, 最后判断carry是否为1,为1需要进位

代码:

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

class Solution(object):
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        # 使用哑结点,更好处理边界情况
        dummy_node = ListNode(0)
        cur_node = dummy_node
        carry = 0
        # 当l1和l2均为None时,退出循环,l1,l1_value需要根据三元表达式得出
        while l1 != None or l2 != None:
            l1_value = 0 if l1 == None else l1.val
            l2_value = 0 if l2 == None else l2.val
            cur_value = l1_value + l2_value + carry
            carry = cur_value // 10         # 进位值
            cur_value = cur_value % 10      # 当前值

            cur_node.next = ListNode(cur_value)
            cur_node = cur_node.next

            l1 = None if l1 == None else l1.next
            l2 = None if l2 == None else l2.next

        # 最后判断carry是否为1
        if carry == 1:
            cur_node.next = ListNode(1)

        return dummy_node.next

分析:

时间复杂度:O(max(n,m)), n,m分别是l1和l2的长度
空间复杂度:O(max(n,m)),需要两个链表中最大长度链表的空间(可能存在最高位进位,此时空间需要加1)

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

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例:

示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

思路:

使用i,j两个指针,分别指向某一时刻最长子串的开头和结尾,j从字符串的第一个元素一直扫描到最后一个元素,使用一个字典储存扫描到每一个字符出现的索引位置并不断更新,i是否更新取决于j指向的字符在字典中的索引位置与i本身索引位置的关系,i较大,则不更新,i较小则i更新。
每次循环需要做的事情:
1.根据条件决定是否移动i
2.储存s[j]
3.计算以i,j子字符串的长度,决定是否更新max_length
4.j += 1

代码:

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        i = 0
        j = 0
        max_length = 0
        char_index = {}

        while j < len(s):
            # 只有在以下条件满足时会移动i,注意条件顺序不要更改
            if j != i and s[j] in char_index and char_index[s[j]] >= i:
                i = char_index[s[j]] + 1
            # 储存/更新s[j]
            char_index[s[j]] = j
            # 计算i,j子字符串的长度
            cur_length = j - i + 1
            if cur_length > max_length:
                max_length = cur_length
            # j += 1
            j += 1
        return max_length

分析:

时间复杂度:只扫描一遍字符串,时间复杂度O(n)
空间复杂度:使用一个字典储存扫描过的字符位置,需要O(n)复杂度,如果字符串的字符有限,例如"a-z",则只需要O(1)的空间

4.寻找两个有序数组的中位数

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。

示例:

示例 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0

示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5

思路:

由于算法的时间复杂度为 O(log(m + n)),则不能使用线性扫描之类的方法,需要使用类似二分查找的方法
首先,我们以较短的数组作为二分查找的基准,每次二分查找后较短数组分为左右两部分,将较长的数组也分为左右两部分,使得两个数组的左部分长度之和等于右部分长度之和,或者左部分长度之和比右部分小于1。
如果左部分最大值小于等于右部分最小值,那么分隔正确,输出结果,否则继续二分查找。
重要技巧:
使用划分点i切分数组,注意i的取值是0到n,n+1种取值,注意i,索引,左侧数组长度之间的关系
需要考虑的特殊情况:
1.一个数组为空的时候
2.切分点在较短数组的左右端点

代码:

class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        # 特殊情况
        if len(nums1) == 0 and len(nums2) == 0:
            return None

        # 设置nums1为较短的有序数组
        if len(nums1) > len(nums2):
            nums1, nums2 = nums2, nums1
        n = len(nums1)
        m = len(nums2)
        odd = 1 if (n + m) % 2  == 1 else 0  # 判断奇偶性

        # 划分点i从0到n,一共n+1种情况,nums1[:i]一共有i个元素,nums1[i-1]是左边的最大元素
        imin = 0
        imax = n
        while imin <= imax : # 循环结束一定出结果
            # i和j之和是nums1和nums2左边数组的长度和,可能是总长度一半(总长度为偶数时),或者偏少的一半(总长度为奇数时)
            # 这样的划分,导致max_left稍微复杂一点
            i = (imin + imax) // 2
            j = (n + m) // 2 - i
            # 下面确定max_left和min_right,需要考虑边界情况
            if i != 0 and j != 0:
                max_left = max(nums2[j - 1], nums1[i - 1])
            elif i != 0:
                max_left = nums1[i - 1]
            elif j != 0:
                max_left = nums2[j - 1]
            else: # i和j可能同时为0
                max_left = None

            if i != n and j != m:
                min_right = min(nums1[i], nums2[j])
            elif i != n:
                min_right = nums1[i]
            elif j != m:
                min_right =  nums2[j]
            else: # 当两数组不均为空时,min_right不会是None
                min_right = None

            # 进行二分查找
            if max_left == None or max_left <= min_right : # max_left == None, 一定是两个数组一个是空,一个是1个元素,返回min_right即可
                return min_right if odd else (max_left + min_right) / 2
            elif  i != 0 and nums1[i - 1] > nums2[j]: # nums1[i - 1]较大,切分点左移
                imax = i - 1
            elif j != 0 and nums2[j - 1] > nums1[i]:  # nums1[i]较小,切分点右移
                imin = i + 1

分析:

时间复杂度:O(log(min(n,m))),只对较短数组进行二分查找
空间复杂度:O(1),只需要常数空间存储变量即可

5. 最长回文子串

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例:

示例 1:
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。

示例 2:
输入: “cbbd”
输出: “bb”

思路:

对于一个长度为n字符串,字符串中可以作为回文中心的位置有2n-1个(每个字符和每两个字符的中间位置),对于每个回文中心,找到它的最长回文子串,最后保存最长的回文子串即可

代码:

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        # 处理特殊情况
        if s == "": return s

        longest_palindrome = ""

        for i in range(len(s)):
            one_char_longest_palindrome = self.get_char_longest_palindrome(i, i, s)
            if len(one_char_longest_palindrome) > len(longest_palindrome):
                longest_palindrome = one_char_longest_palindrome
            two_char_longest_palindrome = self.get_char_longest_palindrome(i, i+1, s)
            if len(two_char_longest_palindrome) > len(longest_palindrome):
                longest_palindrome = two_char_longest_palindrome

        return longest_palindrome


    def get_char_longest_palindrome(self, i, j, s):
        """
        找到以i, j中点为中心的最长回文子串
        以某个字符为中心,则i,j相同
        以某两个相邻字符为中心,则j=i+1
        :param i: 中心点左边的索引
        :param j: 中心点右边的索引
        :param s: 字符串
        :return: 以i, j中点为中心的最长回文子串
        """
        char_longest_palindrome = ""
        imin = i
        imax = j
        while imin >=0 and imax < len(s):
            if s[imin] == s[imax]:
                char_longest_palindrome = s[imin:imax+1]
                imin -= 1
                imax += 1
            else:
                break
        return char_longest_palindrome

分析:

时间复杂度:遍历所有中心点,遍历每个中心点的时间复杂度最差为O(n),所以最终的时间复杂度为O(n2)
空间复杂度:O(1),储存几个变量即可

6. 最长回文子串

将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “LEETCODEISHIRING” 行数为 3 时,排列如下:
L…C…I… R
E T O E S I I G
E…D…H…N
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“LCIRETOESIIGEDHN”。
请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);

示例:

示例 1:
输入: s = “LEETCODEISHIRING”, numRows = 3
输出: “LCIRETOESIIGEDHN”
示例 2:
输入: s = “LEETCODEISHIRING”, numRows = 4
输出: “LDREOEIIECIHNTSG”
解释:
L D R
E O E I I
E C I H N
T S G

思路:

使用包含numRows个列表(每个列表可以看做是矩阵的某一行)的列表储存字符,2numRows-2是一个循环(numRows为1时,特殊处理),字符x根据其在字符串中的索引与2numRows-2的余数,决定字符x进入哪个列表,最后遍历列表的列表得到最终输出的字符串

tips:

有些矩阵位置的记录可以使用列表去代替

代码:

class Solution(object):
    def convert(self, s, numRows):
        """
        :type s: str
        :type numRows: int
        :rtype: str
        """
        # 边界情况,当numRows == 1时,loop_num为0会出错
        if numRows == 1: return s

        loop_num = 2 * numRows - 2  #loop_num是一个循环

        # 初始化矩阵,每个列表作为一行
        matrix = []
        for i in range(min(numRows, len(s))):
            matrix.append([])

        # 将字符储存在矩阵中
        for i in range(len(s)):
            remainder = i % loop_num
            if remainder <= loop_num / 2:
                matrix[remainder].append(s[i])
            else:
                matrix[loop_num-remainder].append(s[i])
                
        # 遍历列表得到结果
        convert_string = ""
        for row in matrix:
            for char in row:
                convert_string += char
                
        return convert_string

分析:

时间复杂度:遍历一遍字符串和一个矩阵(使用列表存储可以避免存储矩阵中的空值,遍历储存空值的矩阵的时间复杂度为O(n2)),总的时间复杂度为O(n)
空间复杂度:O(n), 本程序只需要一个储存字符串中所有元素的矩阵即可

7. 整数反转

给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。

示例:

示例 1:
输入: 123
输出: 321

示例 2:
输入: -123
输出: -321

示例 3:
输入: 120
输出: 21

假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−2^31, 2^31 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。

思路:

只需编写出正数的翻转即可,负数的只需要提取符号做正数的翻转然后加上符号即可,注意120->21的翻转过程(其实对于末尾的0不需要额外处理),注意溢出问题的处理,影响的时间和空间复杂度

代码:

class Solution(object):
    def reverse(self, x):
        """
        :type x: int
        :rtype: int
        """
        reverse_x = self.reverse_positive(x) if x >= 0 else - self.reverse_positive(x)
        return reverse_x

    def reverse_positive(self, x):

        positive = 1 if x >= 0 else 0
        x = x if x >= 0 else - x
        reverse_x = 0

        while x != 0:
            reverse_x = 10 * reverse_x + x % 10
            x = x // 10
            # 判断是否越界
            if (positive == 0 and -reverse_x <= - 2 ** 31) or  (positive == 1 and reverse_x >= 2 ** 31 - 1):
                return 0

        return reverse_x

分析:

时间复杂度:O(log(n)), n是二进制的数位(n很大时,翻转后的数也可能不越界,如1000000000000…),log(n)是十进制的位数
空间复杂度:O(1),储存reverse_num,是有限位的,位数增多后溢出即停止

8. 字符串转换整数 (atoi)

请你来实现一个 atoi 函数,使其能将字符串转换成整数。
首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。
当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。
该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0。

说明:
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−2 ^31, 2 ^31 − 1]。如果数值超过这个范围,qing返回 INT_MAX (2 ^31 − 1) 或 INT_MIN (−2 ^31) 。

示例:

示例 1:
输入: “42”
输出: 42

示例 2:
输入: " -42"
输出: -42
解释: 第一个非空白字符为 ‘-’, 它是一个负号。
我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。

示例 3:
输入: “4193 with words”
输出: 4193
解释: 转换截止于数字 ‘3’ ,因为它的下一个字符不为数字。

示例 4:
输入: “words and 987”
输出: 0
解释: 第一个非空字符是 ‘w’, 但它不是数字或正、负号。
因此无法执行有效的转换。

示例 5:
输入: “-91283472332”
输出: -2147483648
解释: 数字 “-91283472332” 超过 32 位有符号整数范围。
因此返回 INT_MIN (−231) 。

假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−2^31, ^231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。

思路:

使用符号字典和数字字典储存符号和数字,整个函数的流程分为三个阶段:1.寻找第一个符合条件的首字符, 注意区分前一个字符为0还是不为0,2.连接数字字符,遇到第一个不符合要求的字符停止(不是数字的字符)3.检查值是否溢出

代码:

class Solution(object):
    def myAtoi(self, str):
        """
        :type str: str
        :rtype: int
        """
        if str == "":
            return 0

        num = 0
        symnol = 0   # 符号位
        pre_0 = 0    # 前一个字符是否为0
        char_num = {"0":0, "1":1, "2":2, "3":3, "4":4, "5":5, "6":6, "7":7, "8":8, "9":9}
        char_symbol = ["+", "-"]

        index = 0
        length = len(str)

        # 先寻找第一个符合条件的字符
        while index < length:
            char = str[index]

            if pre_0 == 0:      # 前一个字符不为"0"的情况下
                if char == " ":
                    index += 1
                    continue
                if char == "0":
                    pre_0 = 1
                    index += 1
                    continue
                if char not in char_num and char not in char_symbol:
                    return num
                if char == "+":
                    symnol = 1
                if char == "-":
                    symnol = -1
                if char in char_num:
                    symnol = 1
                    num = char_num[char]
                index += 1
                break
            else:
                if char not in char_num:
                    return num
                elif char == "0":
                    index += 1
                    continue
                else:
                    symnol = 1
                    num = char_num[char]
                index += 1
                break

        # 连接后后续的数字字符
        while index < length:
            char = str[index]
            if char not in char_num:
                break
            num = num * 10 + char_num[char]
            index += 1

        # 输出最后的结果,需要判断范围
        high = 2 ** 31 - 1
        low = - 2 ** 31
        if symnol * num > high:
            result = high
        elif symnol * num < low:
            result = low
        else:
            result = symnol * num

        return result

分析:

时间复杂度:O(n)扫描一遍字符串
空间复杂度:O(n)储存数值,提前加入溢出判断,可以是空间复杂度降为O(1)

9. 回文数

判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

示例:

示例 1:
输入: 121
输出: true

示例 2:
输入: -121
输出: false
解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

示例 3:
输入: 10
输出: false
解释: 从右向左读, 为 01 。因此它不是一个回文数。

进阶:
你能不将整数转为字符串来解决这个问题吗?

思路:

对于整数问题:1.负数不是回文数,2.计算正数的反向数值,反向数值与原数相等则是回文数,否者不是
对于字符串问题:两个指针分别从字符串左右扫描即可

代码:

class Solution(object):
    def isPalindrome(self, x):
        """
        :type x: int
        :rtype: bool
        """
        if x < 0:
            return False
        reverse_x = 0
        tmp = x
        while tmp != 0:
            reverse_x = reverse_x * 10 + tmp % 10
            tmp = tmp // 10
        return True if reverse_x == x else False

分析:

时间复杂度:O(n)
空间复杂度:O(n)

10. 正则表达式匹配

给定一个字符串 (s) 和一个字符模式 §。实现支持 ‘.’ 和 ‘*’ 的正则表达式匹配。
‘.’ 匹配任意单个字符。
‘*’ 匹配零个或多个前面的元素。
匹配应该覆盖整个字符串 (s) ,而不是部分字符串。

说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。

示例:

示例 1:
输入:
s = “aa”
p = “a”
输出: false
解释: “a” 无法匹配 “aa” 整个字符串。

示例 2:
输入:
s = “aa”
p = “a*”
输出: true
解释: ‘*’ 代表可匹配零个或多个前面的元素, 即可以匹配 ‘a’ 。因此, 重复 ‘a’ 一次, 字符串可变为 “aa”。

示例 3:
输入:
s = “ab”
p = “.*”
输出: true
解释: "." 表示可匹配零个或多个(’’)任意字符(’.’)。

示例 4:
输入:
s = “aab”
p = “c*a*b”
输出: true
解释: ‘c’ 可以不被重复, ‘a’ 可以被重复一次。因此可以匹配字符串 “aab”。

示例 5:
输入:
s = “mississippi”
p = “mis*is*p*.”
输出: false

思路:

这个问题比较难,属于动态规划的区间模型,类似的问题还有构建字符的回文字符等,我们需要用一个矩阵表示s和p的匹配过程,想清楚矩阵中每个元素的构建过程是比较重要的,对于长度为n的s和长度为m的p,我们构建一个(n+1, m+1)的矩阵,矩阵M的行索引为[0, n],列索引为[0, m],矩阵中的每个元素(i, j),表示s的[0,i)和p的[0,j)子串是否匹配,矩阵的(0, 0)位置是1(即s和p的空白开头是匹配的),先填充矩阵第0行和第0列(这是边界情况,条件与矩阵内部的条件不太一样),然后填充矩阵的内部元素,最终的[n, m]即使能否匹配的结果。我们设置转移方程的时候,原则是匹配的优先级最高,也就是说想出所有可以匹配的情况,除此之外才是不匹配。
注意:
1.对于特殊字符“.”和“*”的处理,“.”的处理比较简单,“*”的处理复杂一些,需要进行分情况讨论
2.矩阵和字符串的索引问题,有一点绕,简单的讲矩阵i,j元素,对应的字符串元素为s[i-1]和p[j-1],如果字符串的索引是[1, len(str)]就会好理解很多。
具体逻辑见代码

代码:

import numpy as np

class Solution(object):
    def isMatch(self, s, p):
        """
        :type s: str
        :type p: str
        :rtype: bool
        """
        if s == "" and p == "":
            return True
		
		# 矩阵中s是列,p是行
        dynamic_matrix = np.zeros(shape=(len(s)+1, len(p)+1))
        dynamic_matrix[0][0] = 1

        # 填写矩阵的第0行
        for j in range(1, len(p)+1):
            if p[j-1] == "*" and dynamic_matrix[0][j-2] == 1:
                dynamic_matrix[0][j] = 1
            else:
                dynamic_matrix[0][j] = 0

        # 填写矩阵的第0列
        for i in range(1, len(s)+1):
            dynamic_matrix[i][0] = 0

        # 填写内部矩阵
        for i in range(1, len(s)+1):
            for j in range(1, len(p)+1):
                if p[j-1] == "*":   
                    # dynamic_matrix[i][j-2]是*将前一个字符重复0次,dynamic_matrix[i-1][j] and (s[i-1] == p[j-2] or p[j-2] == ".")是*将前一个字符重复1至多次,
                    # 问题是.*可以匹配任何字符,属于题中的一个漏洞,解决办法是当dynamic_matrix[i][j-2]为0,dynamic_matrix[i-1][j] and (s[i-1] == p[j-2] or p[j-2] == ".")为1时,让p[j-2]的值为s[i-1]
                    dynamic_matrix[i][j] = dynamic_matrix[i][j-2] or (dynamic_matrix[i-1][j] and (s[i-1] == p[j-2] or p[j-2] == "."))
                else:
                    dynamic_matrix[i][j] = dynamic_matrix[i-1][j-1] and (s[i-1] == p[j-1] or p[j-1] == ".")
        return True if dynamic_matrix[len(s)][len(p)] else False

分析:

时间复杂度:O(ps), 计算一个ps规模的矩阵
空间复杂度:O(ps), 构建一个p
s规模的矩阵

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值