Python-Leetcode-剑指offer(五月下做题整理)

以下题目都来自Leetcode,题解和评论中的一些优秀代码,我改成了python。如有侵权,请联系博主。

5-16-面试题43. 1~n整数中1出现的次数

 考点:找规律和面试题44. 数字序列中某一位的数字有点像

5-17-面试题60. n个骰子的点数

考点:二维DP题

二维DP题中的状态方程,是和上一行所在的状态和此时刻所在的状态相关的。

dp[n][s] 表示共有n个骰子 当其总和为s时,具有的方案数。

dp[i][s] =  dp[i][s] + dp[i-1][s-j] 当前i个骰子总和 = 当前i个骰子总和 + 上一个筛子(i-1)中可以正好凑到s-j的方案数。j当前筛子可以的数字。

一共有三个骰子, dp[3][7] = dp[2][2] + dp[2][3] + dp[2][4]+dp[2][5] +dp[2][6]  表示的是  s-j 得在i-1个筛子可以的总和数内。

当前两个骰子是2时,最后一个骰子可以是5。 最后一个骰子只有一种方案。

当前两个骰子是3时,最后一个骰子可以是4。 最后一个骰子只有一种方案。

当前两个骰子是4时,最后一个骰子可以是3。 最后一个骰子只有一种方案。

当前两个骰子是5时,最后一个骰子可以是2。 最后一个骰子只有一种方案。.....

题解来自此处

class Solution:
    def twoSum(self, n: int) -> List[float]:
        
        L = [[ 0 for _ in range(0,6*n+1)] for _ in range(0,n+1)] # 建立 (n+1)*(6n+1)
        for i in range(1,7):
            L[1][i] = 1 # n=1 时候6个骰子方案都是1
        
        for i in range(2,n+1): # 控制几个骰子
            for j in range(i,6*i+1): #控制总和
                for k in range(1,7): #控制每个骰子的点数
                    if j-k >= 1: # 保证前i-1个骰子可以出来这个总和且最起码要剩一个点数给最后一个骰子
                        L[i][j] = L[i][j] + L[i-1][j-k] # j-k 前i-1个骰子的总和 
        
        ans = []   # 最后记录

        for i in range(n,6*n+1):
            ans.append((L[n][i]*1.0)/pow(6,n))
        return ans

5-18-面试题65. 不用加减乘除做加法

考点:位运算  python 负数补码的问题 

将a,b上的从右到左每一位 异或操作 (0+0) =0 (1+0) = 1 (0+1) = 1 (1+1) = (1)0 => n

当a,b两位均是1时[&],要向前进一位(<<)。 => c 这样将n+c也可以得到正确的加法。但是题目不让用加法,因此再将n和c当做a,b继续做加法,直至c进位为0。即把累加结果全部累加到了n中。

注意:在计算机系统中,数值一律用 补码 来表示和存储。补码的优势: 加法、减法可以统一处理(CPU只有加法器)。因此,以上方法 同时适用于正数和负数的加法 。

class Solution:
    def add(self, a: int, b: int) -> int:
        x = 0xffffffff
        a, b = a & x, b & x
        while b != 0:
            a, b = (a ^ b), (a & b) << 1 & x
        return a if a <= 0x7fffffff else ~(a ^ x)

这个题涉及到了python补码和原码的形式,所以为了搞清楚,从开了一篇博客

5-19-面试题67. 把字符串转换成整数

考点:逻辑?我觉得逻辑清楚的,应该能够比较容易的写出。首先判断最前面的空格,然后判断+,-,然后再算数。

自己的代码: O(N) O(N)

class Solution:
    def strToInt(self, string: str) -> int:
        flag = 0
        for i in range(0,len(string)):
            if string[i] == ' ':
                flag += 1
            else:
                break #找出所有前空格
        
        string = string[flag:]

        def t(st,ans):
            if st == '1':
                ans.append(1)
            if st == '2':
                ans.append(2)
            if st == '3':
                ans.append(3)
            if st == '4':
                ans.append(4)
            if st == '5':
                ans.append(5)
            if st == '6':
                ans.append(6)
            if st == '7':
                ans.append(7)
            if st == '8':
                ans.append(8)
            if st == '9':
                ans.append(9)
            if st == '0':
                ans.append(0)
            if st not in ['0','1','2','3','4','5','6','7','8','9']:
                return ans 
            return ans

        def change(ans,flag):
            x = 1
            an = 0
            for j in ans[::-1]:
                an += j*x
                x *= 10
            if flag == '1' or flag == '+':
                return an
            else: return an*(-1)


        if len(string) == 0 : return 0
        ans = [] 
        if string[0] in ['+','-']:
            i = 0
            for st in string[1:]:
                i += 1
                ans = t(st,ans)
                if len(ans) < i:
                    break
            
            ans = change(ans,string[0])
            if ans > 2**31-1:return 2**31-1
            elif ans < -2**31 :return -2**31 
            return ans 
        i = 0
        ans = []
        for st in string:
            i += 1
            ans = t(st,ans)
            if len(ans) <i:
                break
        #print(ans)
        ans = change(ans,'1')
        if ans > 2**31-1:return 2**31-1
        return ans

不足点:(1)字符串转int型变量时,可以利用 str(i) - str('0')来实现转换。相当于用 i的ASCII码值减'0'的ASCII。

(2)算数的时候,不用非要从后往前算,也可以从前往后算。

a = [1,3,4,6] #从前往后
ans = 0 
for i in a:
    ans = ans*10 + i

a = [1,3,4,6] #从后往前
ans,j = 0,1 
for i in a[::-1]:
    ans += j*i
    j *= 10

(3)由于python是可以不考虑溢出的,所以可以放在最后进行是否在32位有效范围内,但是如果在计算数字过程中[每一次都进行一次判断],那么会节省一部分的时间。

根据题解,溢出有两种。(一),累计之前res>bndry ,直接跳出。因为在往下走的时候,是res*10 > 21474836500

因为bndry 是 214748364 那么大于它的最小的是 214748365, 乘以10之后,肯定溢出。

(二)res=bndry,因为下一步要做 res*10+i,如果i>7那么也是溢出的情况。因为复数是取到'9'时,溢出。正数是'8'溢出。

综合上述三点不足,代码如下。[来自题解]

class Solution:
    def strToInt(self, string: str) -> int:        
        if len(string) ==0:return 0
        i,flag,ans = 0,0,0
        while( i < len(string) and string[i]== ' ' ): i+=1
        if i == len(string) : return 0
        if string[i] == '-':flag=1
        if string[i] in ['-','+']: i+=1
        min_ = 2**31 
        max_ = 2**31-1 
        bndry= (2**31-1)//10
        for c  in string[i::]:
            if c >'9' or c <'0' : break
            if ans>bndry or (ans ==bndry and c>'7'):return min_*(-1) if flag else max_ 
            ans = ans*10 + (ord(c)-ord('0'))
        return ans*(-1) if flag else ans

5-19-面试题53 - I. 在排序数组中查找数字 I

考点:二分查找及其变形 O(logN) 排序数组中的搜索问题 二分边界处理问题

双指针 O(N)

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        # dic O(N) O(N)
        # 二分查找 O(logN) O(1)
        i,j = 0,len(nums)-1
            
        while(i<j and nums[i]<target):i+=1
        while(i<j and nums[j]>target):j-=1
        if i==j:
            if nums[i] == target:
                return 1
            else:
                return 0
        return j-i+1

此题二分法不在于找元素,而在于找边界。在普通二分法中,找的是nums[m] = target的 m。

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        # 二分查找 O(logN) O(1)
        # 两次二分,找出最左边界和最右边界
        def left(l,r): #找左边界
            while(l<=r):
                mid = l+(r-l)//2
                if nums[mid] > target:
                    r = mid-1
                elif nums[mid]<target:
                    l = mid+1
                elif nums[mid] == target:
                    r = mid-1 #在左边继续找i
            if l >= len(nums) or target != nums[l] :return -1 #未找到左边界,即值不在里面
            return l #if target == nums[l] return l else l 
        
        def right(l,r):
            while(l<=r):
                mid = l+(r-l)//2
                if nums[mid] > target:
                    r = mid-1
                if nums[mid] < target:
                    l = mid+1
                elif nums[mid] == target:
                    l = mid+1
            if r == -1 or target != nums[r] :return -1 #左边界不存在
            return r


        if len(nums) == 0:return 0
        i = left(0,len(nums)-1)
        if i ==-1 :return 0  # 不存在左边界
        j = right(0,len(nums)-1)

        return j-i+1
          

5-20-面试题06. 从尾到头打印链表

考点:链表

class Solution:
    def reversePrint(self, head: ListNode) -> List[int]:
        l = []
        while head:
            l.append(head.val)
            head = head.next
        return l[::-1]
        
        # 原地翻转 O(1)
        i,j = 0,len(l)-1
        while(i<j):
            temp = l[i]
            l[i] = l[j]
            i += 1
            l[j]  = temp
            j -= 1
        return l

5-21-面试题24. 反转链表

考点:链表的基本使用

(1)先按照顺序存储到栈[先进后出],再重新构造

(2)直接在原链表上操作 pre=None cur=head 将cur指向pre指针,构造第一个指针指向None


class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        pre = None
        cur = head
        next_ = None
        while(cur):
            next_ = cur.next
            cur.next = pre
            pre = cur
            cur = next_
        return pre

5-22-面试题18. 删除链表的节点

考点链表的基本操作,这个题和剑指offer上不太一样。先以链接的为主。

我写的:(1)最简单的就是用一个栈来存节点,然后再拼接。时间复杂度O(2N) 空间复杂度O(2N)

(2)不用栈存,直接在原链表上做。O(N)空间复杂度O(N)

class Solution:
    def deleteNode(self, head: ListNode, val: int) -> ListNode:
        if head.val == val:return head.next #直接 在原链表上做
        H = ListNode(0)
        H_1 = H
        while (head):
            if head.val != val:
                H_1.next = head
                H_1 = H_1.next
            else:
                H_1.next = head.next #跳过该节点,否则head后面的全在H_1后面
            head = head.next
        return H.next

        ''' 题解中我认为比我写得好的样子
        if head == None: return None
        if head.val == val:return head.next
        P = head
        while(P.next.val != val): P = P.next
        P.next = P.next.next
        return head '''

5-23-面试题52. 两个链表的第一个公共节点

考点:链表的基本常识

(1)相交指的是地址相同而不是值相同。 headA == headB not headA.val == headB.val

(2)想的是将链表反转后,比较从头开始。那么遇到不同的时候,那么就结束了。

但是这样比较的思想是不对的,因为[2,3,4,5],[2,3,1,0] headA != headB 因为他们节点是不同的。只能说

headA.val = headB.val。 

(3)题目要求不改变原结构,利用head = head.next 会更改原结构,只剩下最后一个节点。所以利用node=headA来做。?这种情况为什么不会改变原链表结构,这个按照道理来说应该也是浅拷贝问题。

 class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:       
        dic = {} ##用字典去直接存A的所有节点,然后再继续做  O(N) O(N)
        node1 = headA
        node2 = headB
        while(node1):
            dic[node1] = 1
            node1 = node1.next
        while(node2):
            if dic.get(node2,0) : return node2
            node2 = node2.next
        return  None 

 上面的思路来自题解1,下面这种思路来自题解2。 两个链表长度分别为L1+C、L2+C, C为公共部分的长度,做法: 第一个人走了L1+C步后,回到第二个人起点走L2步;第2个人走了L2+C步后,回到第一个人起点走L1步。 当两个人走的步数都为L1+L2+C时就两个就相遇了。摘自:题解二评论 @eatalot

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:        
        # A:m+n+k B:n+m+k 如果有相同的节点,以这样的方式走,那么肯定会有重合 
        node1,node2  = headA,headB

        while(node1 != node2):
            node1 = node1.next if node1 else headB
            node2 = node2.next if node2 else headA
        return node1

5-24-面试题35. 复杂链表的复制

考点:深拷贝和浅拷贝[引用] 这个题目中的复制,意在实现深拷贝,即开辟另外一块内存空间来存储复制样本。

注意点:(1) head 要每次重建,Node(head.val) 但是 head.random 不能重建,因为他要指向 已建立的节点的内存地址。所以都重新创建,然后再分别指向这种想法是错误的。

那么要做的就是重建head,然后head.random如果存在直接指向,如果不存在在建立。

5-25-面试题30. 包含min函数的栈

考点:如何将min()缩小到O(1),因为排序算法时间复杂度最低为O(NlogN)。所以得想到用空间换时间。

所以 用S2去维护一个最小栈,当pop()时,只要不涉及到最小值弹出,那么栈的最小值,不会改变。当push()时,只要push()进来元素没有最小值大,那么就不用更新最小值,因为无论增加多少,最小值依旧不变。这也是单调栈的思路。

class MinStack:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.S1 = []
        self.S2 = []
    def push(self, x: int) -> None:
        self.S1.append(x)
        if len(self.S2) == 0 or x <= self.S2[-1]: self.S2.append(x)

    def pop(self) -> None:
        if len(self.S1) != 0: a =  self.S1.pop(-1)
        else: return None
        if a == self.S2[-1]:
            self.S2.pop(-1)

    def top(self) -> int:
        if len(self.S1) != 0 :return self.S1[-1]
        else:return None

    def min(self) -> int:
        if len(self.S2) != 0 : return self.S2[-1]
        else:return None

5-26-面试题27. 二叉树的镜像

考点:二叉树的知识,主要是如何保留交换前的左右子树

class Solution:
    def mirrorTree(self, root: TreeNode) -> TreeNode:
        if not root:return None
        q = [root]
        ans = root
        while(q):
            node = q.pop(0)
            if node.left:
                q.append(node.left)
            if node.right:
                q.append(node.right) ##先把交换前的状态保存
            node.left,node.right = node.right,node.left
        return ans 
        ##递归
        if not root:return None
        root.left,root.right = self.mirrorTree(root.right),self.mirrorTree(root.left)
        return root

5-27-面试题58 - II. 左旋转字符串

考点:字符串操作  我认为考点在于如何原地操作->如何利用索引进行原地操作。

(1)字符串切片  O(N) O(N)  list和dic的切片复杂度查看此处

class Solution:
    def reverseLeftWords(self, s: str, n: int) -> str:
        return s[n:]+s[0:n]
        ##  第二种比较妙的
        ##ss = s+s
        ##return ss[n:n+len(s)]

(2)列表遍历拼接 在不能用切片的情况下。

class Solution:
    def reverseLeftWords(self, s: str, n: int) -> str:
        L = '' #字符串  O(N) O(N)
        for i in range(n:len(s)):
            L+=s[i]
        for i in range(0,n):
            L+=s[i]
        return L


        L = [] ##列表拼接 
        for i in range(n,len(s)):
            L.append(s[i])
        for i in range(0,n):
            L.append(s[i])
        return ''.join(L)

        res = ""       ##O(N) O(N)   
        for i in range(n, n + len(s)): #### 求余 来自 Leetcode @Krahets
            res += s[i % len(s)]
        return res

利用求余简化for循环,题解来自Leetcode @Krahets

由于python中字符串是不可变对象,即不能实现s[i] = s[j],因此python代码应该是没办法进行原地操作的[不确定]。

所以基于c有原地操作。[不知道如何写函数了,忘光了,暂且先这样吧]

char* reverseLeftWords(char* s, int n){
    int len = strlen(s);
    int i = 0;
    int j = n-1;
    char temp;
    while(i<j){ // 一次交换
        temp = s[i];
        s[i] = s[j];
        s[j] = temp;
        i++;
        j--;
    }
    i= n;
    j = len-1;
    while(i<j){ // 二次交换
        temp = s[i];
        s[i] = s[j];
        s[j] = temp;
        i++;
        j--;
    }
    i = 0;
    j = len-1;
        while(i<j){ // 三次交换
        temp = s[i];
        s[i] = s[j];
        s[j] = temp;
        i++;
        j--;
    }
    return s;
}

5-28-面试题28. 对称的二叉树

考点:感觉二叉树的题目,多半能用递归来做,不能用递归的一般都是层次遍历的变形题。

这个评论中 @Tai_Park写个很好,整理了一下递归思路。

递归三件事:

(1)题目想要得到什么 ->判断是否为镜像 那么return 的就应该是 true/fasle     判断的树的左右两棵树,那么传入最起码是两个参数left right

(2)递归终止条件 即【return】的是什么

(3)层次传递之间的关系是什么 

做递归思考三步:

  1. 递归的函数要干什么?
  • 函数的作用是判断传入的两个树是否镜像。
  • 输入:TreeNode left, TreeNode right
  • 输出:是:true,不是:false
  1. 递归停止的条件是什么?
  • 左节点和右节点都为空 -> 倒底了都长得一样 ->true
  • 左节点为空的时候右节点不为空,或反之 -> 长得不一样-> false
  • 左右节点值不相等 -> 长得不一样 -> false
  1. 从某层到下一层的关系是什么?
  • 要想两棵树镜像,那么一棵树左边的左边要和二棵树右边的右边镜像,一棵树左边的右边要和二棵树右边的左边镜像
  • 调用递归函数传入左左和右右
  • 调用递归函数传入左右和右左
  • 只有左左和右右镜像且左右和右左镜像的时候,我们才能说这两棵树是镜像的
  1. 调用递归函数,我们想知道它的左右孩子是否镜像,传入的值是root的左孩子和右孩子。这之前记得判个root==null。
class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        
        def t(L,R): ## O(N) O(N)
            if not L and not R:return True
            if not L or not R or L.val != R.val:return False
            return t(L.left,R.right) and t(L.right,R.left)
        if not root :return True
        else:
            return t(root.left, root.right) 

除了递归之外,还有其他方法:利用中序遍历每个节点保存成一个list,然后判断这个list是否是回文结构。

5-29-面试题32 - II. 从上到下打印二叉树 II

BFS 队列实现,层次遍历。

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root : return []
        L = []
        q = [root]

        while(q): #O(N) O(3N)
            size = len(q)
            ans = []
            for i in range(0,size):
                cur = q.pop(0) ## 用pop()来选择pop()出几个
                ans.append(cur.val)
                if cur.left :
                    q.append(cur.left)
                if cur.right:
                    q.append(cur.right)
            L.append(ans) ##O(N)
        return L 

DFS实现

DFS说白了就是递归实现,那么思考几个问题:

(1)最后需要的是什么?每一层的节点信息。如何实现每一层?得用一个depth统计每一层。

(2)什么时候返回,停止递归?node是空时。返回什么?不用返回什么,因为用其他去存储想要的东西了

(3)递归传递关系是什么?传递node的左右子树和对应的深度信息(+1)。

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:        
        ## DFS 
        ## 
        dic = {} ## depth: []
        ## 如何向每一层添加 ?
        def t(node,depth): # 递归是想要获取每一层的节点,那么就要设置一个depth
            if not node :return  ##递归返回条件
            if depth in dic.keys():
                dic[depth].append(node.val) # 每一层存入相同的深度中,用了字典
            else:
                dic[depth] = [node.val]
            if node.left:
                t(node.left,depth+1) ##向下传递
            if node.right:
                t(node.right,depth+1)        
        t(root,0)
        return [[val for val in dic[depth] ] for depth in dic.keys()]

看了评论之后,发现还是有地方可以更改的:

(1)存储结构,可以不用dic,直接用list

(2)不用判断 node.left是否存在,因为如果不存在就直接return了,那么省掉了大量的判断过程。

 来自此题评论中的@MoffySto

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:      
        L = [] 
        ## 如何向每一层添加 ?
        def t(node,depth): # 递归是想要获取每一层的节点,那么就要设置一个depth
            if node: ##省略每一层 node==None 判断
            #if depth in dic.keys():
                if depth >= len(L): # L = [[1],[2,3]]
                    #dic[depth].append(node.val) # 每一层存入相同的深度中
                    L.append([]) #再多创建一层            
                L[depth].append(node.val) # 深度和L中的index对应的
                t(node.left,depth+1)
                t(node.right,depth+1)        
        t(root,0)
        return L

5-30-面试题32 - I. 从上到下打印二叉树

考点:简单的层次遍历

       看了题解,发现一个知识点:q.pop(0)的时间复杂度是O(N),因为 list 是列表,也就是 java c++ 中的数组移除头部元素的方式 是把后面的元素全部往前移动一位,所以复杂度是 O(N) ; deque 是双端队列,底层是链表,因此头部和尾部是等价的,插入删除都是 O(1)。

因此可以用双端队列,代替list结构,来实现层次遍历。

        if not root:return []
        ans = []
        q = collections.deque() #双端队列
        q.append(root)
        while(q):
            node = q.popleft() 
            ans.append(node.val)
            if node.left:
                q.append(node.left)
            if node.right:
                q.append(node.right)
        return ans

5-31-面试题32 - III. 从上到下打印二叉树 III

考点:二叉树的层次遍历的变种

class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        if not root:return []
        q,depth = [root],0
        ans = []
        while(q):
            size = len(q)
            s = []
            for i in range(0,size):
                node = q.pop(0)
                if depth%2 == 0:## 冗余判断
                    s.append(node.val)
                else:
                    s.insert(0,node.val)
                if node.left :
                    q.append(node.left)
                if node.right:
                    q.append(node.right)
            ans.append(s)
            depth+=1
        return ans

分析一下:(1)list.insert()时间复杂度是O(N) (2)每个节点都要判断一次 depth的奇偶性 (3)用ans长度来判断奇偶性,减少变量的使用

改进方法1:用双端队列代替list,实现左插入和右插入,从而实现O(1)的复杂度。

        if not root:return []
        q,ans = collections.deque(),[]  ##改成双端队列
        q.append(root)
        while(q):
            size = len(q)
            s = collections.deque()
            for i in range(0,size):
                node = q.popleft() ##O(1) 
                if len(ans)%2 == 0:## 右插入 
                    s.append(node.val)  #O(1) 
                else:
                    s.appendleft(node.val) #左插入  #O(1) 
                if node.left : 
                    q.append(node.left) #O(1) 
                if node.right:
                    q.append(node.right)
            ans.append(list(s)) # 时间复杂度  O(N)
        return ans

改进方法2:由于每一个节点都要进行一次判断,可以写两遍for来实现奇偶层,从而节省每次判断。

        if not root:return []
        q,ans = collections.deque(),[]
        q.append(root)
        while(q):
            s = []
            for i in range(0,len(q)): #偶数层 
                node = q.popleft() 
                s.append(node.val) #左读
                if node.left :
                    q.append(node.left) # 又插入
                if node.right:
                    q.append(node.right)
            ans.append(list(s)) 
            if not q :break 
            s = [] #奇数层 
            for i in range(0,len(q)):
                node = q.pop() # 右读  
                s.append(node.val)
                if node.right:
                    q.appendleft(node.right) # 左插入 
                if node.left :
                    q.appendleft(node.left)
            ans.append(s) 
        return ans

方法3:先输出正常的每层节点,在判断的的时候,在奇数层添加list[::-1],倒序结构就行了。

        if not root:return []
        q,ans = collections.deque(),[]
        q.append(root)
        while(q):
            s = []
            for _ in range(len(q)):
                node = q.popleft()
                s.append(node.val)
                if node.left: q.append(node.left) 
                if node.right: q.append(node.right)
            ans.append( s[::-1] if len(ans)%2 ==1 else s) ##这里使用
        return ans   

以上三种额外的解法来自此处

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Foneone

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

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

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

打赏作者

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

抵扣说明:

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

余额充值