LeetCode习题整理(中等)II

煎饼排序

给定数组 A,我们可以对其进行煎饼翻转:我们选择一些正整数 k <= A.length,然后反转 A 的前 k 个元素的顺序。我们要执行零次或多次煎饼翻转(按顺序一次接一次地进行)以完成对数组 A 的排序。

返回能使 A 排序的煎饼翻转操作所对应的 k 值序列。任何将数组排序且翻转次数在 10 * A.length 范围内的有效答案都将被判断为正确。

示例 1:

输入:[3,2,4,1]
输出:[4,2,4,3]
解释:
我们执行 4 次煎饼翻转,k 值分别为 4,2,4,和 3。
初始状态 A = [3, 2, 4, 1]
第一次翻转后 (k=4): A = [1, 4, 2, 3]
第二次翻转后 (k=2): A = [4, 1, 2, 3]
第三次翻转后 (k=4): A = [3, 2, 1, 4]
第四次翻转后 (k=3): A = [1, 2, 3, 4],此时已完成排序。
示例 2:

输入:[1,2,3]
输出:[]
解释:
输入已经排序,因此不需要翻转任何内容。
请注意,其他可能的答案,如[3,3],也将被接受。

提示:

1 <= A.length <= 100
A[i] 是 [1, 2, …, A.length] 的排列

class Solution(object):
    def pancakeSort(self, A):
        """
        :type A: List[int]
        :rtype: List[int]
        """
        def tranv(A,index):#反转前k个数
            k=[]
            for i in range(index+1):
                k.append(A[i])
            for i in range(index+1):
                A[i]=k.pop()
            return None
        n=len(A)
        ans=[]
        for i in range(n):
            if n>1:
                index,_=max(enumerate(A[:n]),key=lambda x:x[1])#找到前n个数的最大的索引
                if index >0:
                    tranv(A,index)#前index+1个数反转
                    ans.append(index+1)
                tranv(A,n-1)
                ans.append(n)
                n-=1
            else:break
        return ans

复制带随机指针的链表

给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。

要求返回这个链表的 深拷贝。

我们用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:

val:一个表示 Node.val 的整数。
random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。

示例 1:
在这里插入图片描述

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
示例 2:

在这里插入图片描述

输入:head = [[1,1],[2,1]]
输出:[[1,1],[2,1]]
示例 3:
在这里插入图片描述

输入:head = [[3,null],[3,0],[3,null]]
输出:[[3,null],[3,0],[3,null]]
示例 4:

输入:head = []
输出:[]
解释:给定的链表为空(空指针),因此返回 null。

提示:

-10000 <= Node.val <= 10000
Node.random 为空(null)或指向链表中的节点。
节点数目不超过 1000 。

"""
# Definition for a Node.
class Node:
    def __init__(self, x, next=None, random=None):
        self.val = int(x)
        self.next = next
        self.random = random
"""

class Solution(object):
    def copyRandomList(self, head):
        """
        :type head: Node
        :rtype: Node
        """
        p = head
        result = None
        pre = None
        D = {}
        while p != None:
            node = Node(p.val, random=p.random)
            D[p] = node
            if pre != None:
                pre.next = node
            else:
                result = node
            pre = node
            p = p.next
        
        q = result
        while q != None:
            if q.random != None:
                q.random = D[q.random]
            q = q.next
        
        #print(result.val)
        return result

最长重复子数组

给两个整数数组 A 和 B ,返回两个数组中公共的、长度最长的子数组的长度。

示例 1:

输入:
A: [1,2,3,2,1]
B: [3,2,1,4,7]
输出: 3
解释:
长度最长的公共子数组是 [3, 2, 1]。
说明:

1 <= len(A), len(B) <= 1000
0 <= A[i], B[i] < 100

class Solution(object):
    def findLength(self, A, B):
        """
        :type A: List[int]
        :type B: List[int]
        :rtype: int
        """
        
        m = len(A)
        n = len(B)

        if m>n:
            m, n, A, B = n, m, B, A

        tmp_list = []
        result = 0
        # 利用','.join([str(i) for i in B])将B转化为字符串且任意两个元素之间用逗号间隔
        str_B = ',' + ','.join([str(i) for i in B]) + ','
        #print(type(str_B))

        for r in A:
            tmp_list.append(str(r))

            if ',' + ','.join(tmp_list) + ',' in str_B:
                result = max(result, len(tmp_list))

            else:
                tmp_list = tmp_list[1:]

        return result

数组中的第k个最大元素

在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例 1:

输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
示例 2:

输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4
说明:

你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。

import heapq
class Solution(object):
    def findKthLargest(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        result = heapq.nlargest(k,nums)
        return result[-1]

无重复字符的最长子串

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

示例 1:

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

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

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

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        '''
        if s == '':
            return 0
        s_list = list(s)
        Subs = []
        for j in range(1, len(s_list)+1):
            for i in range(j-1):
                Subs.append(s_list[i:j])
        
        #print(Subs)
        Lengest = 1
        for i in range(len(Subs)):
            L = len(set(Subs[i]))
            #print(L)
            if L == len(Subs[i]) and L > Lengest:
                #print(Subs[i])
                Lengest = L
        
        return Lengest
        '''
        # 哈希集合,记录每个字符是否出现过
        occ = set()
        n = len(s)
        # 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
        rk, ans = 0, 0
        for i in range(n):
            if i != 0:
                # 左指针向右移动一格,移除一个字符
                occ.remove(s[i - 1])
            while rk < n and s[rk] not in occ:
                # 不断地移动右指针
                occ.add(s[rk])
                rk += 1
            # 第 i 到 rk 个字符是一个极长的无重复字符子串
            ans = max(ans, rk - i)
        return ans


两个字符串的删除操作

给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符。

示例:

输入: “sea”, “eat”
输出: 2
解释: 第一步将"sea"变为"ea",第二步将"eat"变为"ea"

提示:

给定单词的长度不超过500。
给定单词中的字符只含有小写字母。

class Solution(object):
    def minDistance(self, word1, word2):
        """
        :type word1: str
        :type word2: str
        :rtype: int
        """
        n, m = len(word1),len(word2)
        dp = [[0 for _ in range(m+1)] for _ in range(n+1)]
        for i in range(1,n+1):
            for j in range(1,m+1):
                if word1[i-1] == word2[j-1]:
                    dp[i][j] = dp[i-1][j-1] + 1
                else:
                    dp[i][j] = max(dp[i-1][j],dp[i][j-1])# 最终回溯到dp[k][k],故跳过k到i和k到j之间的不等部分。
        return n+m-2*dp[n][m]

破坏回文字符串

给你一个回文字符串 palindrome ,请你将其中 一个 字符用任意小写英文字母替换,使得结果字符串的字典序最小,且 不是 回文串。

请你返回结果字符串。如果无法做到,则返回一个空串。

示例 1:

输入:palindrome = “abccba”
输出:“aaccba”
示例 2:

输入:palindrome = “a”
输出:""

提示:

1 <= palindrome.length <= 1000
palindrome 只包含小写英文字母。

class Solution(object):
    def symmetry(self, L, Len):
        if Len == 0:
            return False

        i = 0
        j = Len-1

        if Len % 2 == 0:
            while i < j:
                if L[i] != L[j]:
                    break
                i += 1
                j -= 1

            
        else:    
            while i <= j:
                if L[i] != L[j]:
                    break
                i += 1
                j -= 1

        if i > j:
            return True
        else: return False



    def breakPalindrome(self, palindrome):
        """
        :type palindrome: str
        :rtype: str
        """
        n = len(palindrome)
        if n == 1:
            return ''
        for i in range(n):
            if palindrome[i] > 'a':
                sub = palindrome[:i]+'a'+palindrome[i+1:]
                if not self.symmetry(sub, n):
                    return sub
        if self.symmetry(palindrome, n):
            palindrome = palindrome[:-1]+'b'
        return palindrome

有效的括号字符串

给定一个只包含三种字符的字符串:( ,) 和 *,写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:

任何左括号 ( 必须有相应的右括号 )。
任何右括号 ) 必须有相应的左括号 ( 。
左括号 ( 必须在对应的右括号之前 )。

  • 可以被视为单个右括号 ) ,或单个左括号 ( ,或一个空字符串。
    一个空字符串也被视为有效字符串。
    示例 1:

输入: “()”
输出: True
示例 2:

输入: “(*)”
输出: True
示例 3:

输入: “(*))”
输出: True
注意:

字符串大小将在 [1,100] 范围内。

class Solution(object):
    def checkValidString(self, s):
        """
        :type s: str
        :rtype: bool
        """
        stack = []                         #第一个栈用来记录所有(的index
        star_stack = []                    #第二个栈用来记录所有*的index
        for i in range(len(s)):
            if s[i] == "(":
                stack.append(i)
            elif s[i] == "*":
                star_stack.append(i)
            else:
                if not stack and not star_stack:
                    return False                        #如果直接读到),直接return False
                if stack:
                    stack.pop()
                elif star_stack:
                    star_stack.pop()                    #先用(来消),再用*来消)
        while stack and star_stack:
            if stack.pop() > star_stack.pop():          #在所有)都处理了之后,只需要考虑(和*的index,此时的*全部当作)来考虑,比较index即可
                return False
        return not stack                   #判断是否有多余的(

最大加号标志

(第一次写思路,有错误望指正)
动态规划:
因为判断是否形成加法标志需要上下左右四个臂的长度,所以不能单一的变量表示不了这个状态;
我这边是用四个变量表示状态,分别为上下左右的连续臂展长度;
上左状态变量在正序遍历数组的时候确定,下右状态变量用逆序遍历数组的时候确定;
状态转移方程为 dp[i+1][j+1][0]=dp[i][j+1][0]+1 (上状态);
最后加法的阶数为四个状态中最下的那个确定;

class Solution:
    def orderOfLargestPlusSign(self, N: int, mines: List[List[int]]) -> int:
        l=[[1 for _ in range(N)] for _ in range(N)]
        for i in mines:
            l[i[0]][i[1]]=0
        # 四个位置分别记录上左下右四个方向上的1的个数,且dp[i+1][j+1]记录的是以[i,j]为中心点。
        dp = [[[0,0,0,0] for _ in range(N+2)] for _ in range(N+2)]
        for i in range(N): #先正向遍历
            for j in range(N):
                if l[i][j]==0:
                    continue
                else:
                    dp[i+1][j+1][0]=dp[i][j+1][0]+1
                    dp[i+1][j+1][1]=dp[i+1][j][1]+1
        for i in range(N-1,-1,-1):
            for j in range(N-1,-1,-1): #逆向遍历
                if l[i][j]==0:
                    continue
                else:
                    dp[i + 1][j + 1][2] = dp[i+2][j + 1][2]+1
                    dp[i + 1][j + 1][3] = dp[i + 1][j+2][3]+1
        m=max([max([min(i) for i in j]) for j in dp])
        return m

三数之和

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        n=len(nums)
        res=[]
        if(not nums or n<3):
            return []
        nums.sort()
        res=[]
        for i in range(n):
            if(nums[i]>0):
                return res
            if(i>0 and nums[i]==nums[i-1]):
                continue
            L=i+1
            R=n-1
            while(L<R):
                if(nums[i]+nums[L]+nums[R]==0):
                    res.append([nums[i],nums[L],nums[R]])
                    while(L<R and nums[L]==nums[L+1]):
                        L=L+1
                    while(L<R and nums[R]==nums[R-1]):
                        R=R-1
                    L=L+1
                    R=R-1
                elif(nums[i]+nums[L]+nums[R]>0):
                    R=R-1
                else:
                    L=L+1
        return res

分数排名

编写一个 SQL 查询来实现分数排名。

如果两个分数相同,则两个分数排名(Rank)相同。请注意,平分后的下一个名次应该是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。

±—±------+
| Id | Score |
±—±------+
| 1 | 3.50 |
| 2 | 3.65 |
| 3 | 4.00 |
| 4 | 3.85 |
| 5 | 4.00 |
| 6 | 3.65 |
±—±------+
例如,根据上述给定的 Scores 表,你的查询应该返回(按分数从高到低排列):

±------±-----+
| Score | Rank |
±------±-----+
| 4.00 | 1 |
| 4.00 | 1 |
| 3.85 | 2 |
| 3.65 | 3 |
| 3.65 | 3 |
| 3.50 | 4 |
±------±-----+

select Score, dense_rank() over (order by Score desc)  as `Rank`
from Scores;

字母位移

有一个由小写字母组成的字符串 S,和一个整数数组 shifts。

我们将字母表中的下一个字母称为原字母的 移位(由于字母表是环绕的, ‘z’ 将会变成 ‘a’)。

例如·,shift(‘a’) = ‘b’, shift(‘t’) = ‘u’,, 以及 shift(‘z’) = ‘a’。

对于每个 shifts[i] = x , 我们会将 S 中的前 i+1 个字母移位 x 次。

返回将所有这些移位都应用到 S 后最终得到的字符串。

示例:

输入:S = “abc”, shifts = [3,5,9]
输出:“rpl”
解释:
我们以 “abc” 开始。
将 S 中的第 1 个字母移位 3 次后,我们得到 “dbc”。
再将 S 中的前 2 个字母移位 5 次后,我们得到 “igc”。
最后将 S 中的这 3 个字母移位 9 次后,我们得到答案 “rpl”。
提示:

1 <= S.length = shifts.length <= 20000
0 <= shifts[i] <= 10 ^ 9

import numpy as np
class Solution(object):
    def shiftingLetters(self, S, shifts):
        """
        :type S: str
        :type shifts: List[int]
        :rtype: str
        """
        '''动态规划法
        m = len(S)
        n = len(shifts)
        if n > m:
            return

        S = list(S)
        
        # dp[j][i] 表示第j次位移后S[i]的值
        dp = [[S[i] for i in range(n)] for j in range(n)]
        
        for j in range(1, n+1):
            for i in range(j):
                if j == 1:
                    dp[j-1][i] = chr((ord(dp[j-1][i]) - 97 + shifts[j-1]) % 26 + 97)
                    #print(dp[0])
                else:
                    dp[j-1][i] = chr((ord(dp[j-2][i]) - 97 + shifts[j-1]) % 26 + 97)
        
        if m == n:
            return ''.join(dp[-1][:])
        
        return ''.join(dp[-1][:]) + ''.join(S[n+1])
        '''
        res=[]
        total=sum(shifts)
        for i in range(len(S)):
            x=(ord(S[i])+total-97)%26+97
            res.append(chr(x))   
            total-=shifts[i]
        return ''.join(res)

索引处的解码字符串

给定一个编码字符串 S。为了找出解码字符串并将其写入磁带,从编码字符串中每次读取一个字符,并采取以下步骤:

如果所读的字符是字母,则将该字母写在磁带上。
如果所读的字符是数字(例如 d),则整个当前磁带总共会被重复写 d-1 次。
现在,对于给定的编码字符串 S 和索引 K,查找并返回解码字符串中的第 K 个字母。

示例 1:

输入:S = “leet2code3”, K = 10
输出:“o”
解释:
解码后的字符串为 “leetleetcodeleetleetcodeleetleetcode”。
字符串中的第 10 个字母是 “o”。
示例 2:

输入:S = “ha22”, K = 5
输出:“h”
解释:
解码后的字符串为 “hahahaha”。第 5 个字母是 “h”。
示例 3:

输入:S = “a2345678999999999999999”, K = 1
输出:“a”
解释:
解码后的字符串为 “a” 重复 8301530446056247680 次。第 1 个字母是 “a”。

提示:

2 <= S.length <= 100
S 只包含小写字母与数字 2 到 9 。
S 以字母开头。
1 <= K <= 10^9
解码后的字符串保证少于 2^63 个字母。

思路:
如果S=‘vk3u5xhq2v’, 这种时候需要找到每一个操作的原始和解码字符索引, 记为(x, y), x表示decode(S)中的位置(从1开始计算), y表示S中的位置(从0开始计算)
最终的字符为’vkuxhqv’
索引记录表对应的就是[v(1,0), k(2,1), 3(6,1), u(7,2), 5(35,2), x(36,3), h(37,4), q(38,5), 2(76,5), v(77,6)]
可以根据K值提前结束索引记录过程, 比如假设K=50, 上面的S在2(76,5)的时候由于76>=50, 跳出循环
然后开始逆向找K对应的应该是原始S中的哪个字符, 类似于进制转换, 把K与每个decode(S)取余, 结果为0的时候说明答案就是对应操作中的原始位置.

class Solution(object):
    def decodeAtIndex(self, S, K):
        """
        :type S: str
        :type K: int
        :rtype: str
        """
        i = cnt = 0
        c = ''
        x = []# x[i] = [解码后的位置(从1开始),解码前的位置(从0开始)]
        while i < len(S) and cnt < K:
            if S[i].isdigit():# S[i]是数字
                cnt *= int(S[i])
                if S[i-1].isdigit(): x[-1][0] = cnt# 若上一个也是数字,则修改上一次的解码后位置。
                else: x.append([cnt, len(c) - 1])# 若上一个不是数字,则记录这次的位置。即上一个字母经过复制在当下的位置。
            else:# S[i]是字母
                c += S[i]
                cnt += 1
                x.append([cnt, len(c) - 1])
            i += 1
        ret = ''
        while x:
            t = x.pop()
            K %= t[0]
            if K == 0:
                ret = c[t[1]]
                break
        return ret

模式匹配

你有两个字符串,即pattern和value。 pattern字符串由字母"a"和"b"组成,用于描述字符串中的模式。例如,字符串"catcatgocatgo"匹配模式"aabab"(其中"cat"是"a",“go"是"b”),该字符串也匹配像"a"、"ab"和"b"这样的模式。但需注意"a"和"b"不能同时表示相同的字符串。编写一个方法判断value字符串是否匹配pattern字符串。

示例 1:

输入: pattern = “abba”, value = “dogcatcatdog”
输出: true
示例 2:

输入: pattern = “abba”, value = “dogcatcatfish”
输出: false
示例 3:

输入: pattern = “aaaa”, value = “dogcatcatdog”
输出: false
示例 4:

输入: pattern = “abba”, value = “dogdogdogdog”
输出: true
解释: “a”=“dogdog”,b="",反之也符合规则
提示:

0 <= len(pattern) <= 1000
0 <= len(value) <= 1000
你可以假设pattern只包含字母"a"和"b",value仅包含小写字母。

思路:
存在以下几种情况:
1)pattern和value都为空,返回True
2)仅pattern为空: 返回False
3)仅value为空,这时候分两种情况:如果pattern中只存在a或者b一种,那么令a或者b为空,符合条件,返回True;否则,由于不同pattern不能表示同一字符串,返回False
4)都不为空的情况下:如果pattern中只有a或者b一种,那意味这value全由一种字符串构成。它需满足以下两个条件:首先,value的长度需要被pattern的长度整除;其次,value中的每一个字符串需要都是a,根据value长度和pattern长度很容易计算出a的长度,然后顺次取出看是否相同即可。
5)如果pattern中同时含有a和b,也有两种情况。第一种,其中一个pattern只有一个,假设a只有一个,那么只需要令a= value, b=“”,即可,所以直接返回True
6)另一种情况,同时含有a, b且个数都大于1。这时候,我们先统计pattern中a, b各有多少个,然后遍历a的所有可能长度,对于某个确定的a的长度,结合a的个数和b的个数以及value的长度,我们即可以确定b的长度。这时候需要满足以下条件:首先b的长度也必须是整数;其次,value只能由a, b结合而成。

class Solution(object):
    def patternMatching(self, pattern, value):
        """
        :type pattern: str
        :type value: str
        :rtype: bool
        """
        if not value and not pattern: return True
        if not pattern: return False
        if not value:
            if len(pattern)==1: return True
            else: return False
        if len(set(pattern))==1: # 如果只有一种pattern
            if len(value)%len(pattern)!=0:
                return False
            length = len(value) // len(pattern)
            return all([value[i:i+length]==value[0:length] for i in range(0, len(value),length)])

        if pattern.count('a')==1 or pattern.count('b')==1:# 两种pattern但是其中一种只有一个,只需要另这个为value,另外一个为空即可
            return True
        
        cnt_a = pattern.count('a')
        cnt_b = pattern.count('b')
        for i in range(len(value)//cnt_a): # 遍历a的所有可能长度
            remain = len(value) - i * cnt_a 
            if remain % cnt_b != 0:
                continue
            j = remain // cnt_b
            set_a = set()
            set_b = set()
            p = 0
            for s in pattern:
                if s=='a':
                    set_a.add(value[p:p+i])
                    p += i
                else:
                    set_b.add(value[p:p+j])
                    p += j
            if len(set_a)==len(set_b)==1:
                return True
        return False

二倍数对数组

给定一个长度为偶数的整数数组 A,只有对 A 进行重组后可以满足 “对于每个 0 <= i < len(A) / 2,都有 A[2 * i + 1] = 2 * A[2 * i]” 时,返回 true;否则,返回 false。

示例 1:

输入:[3,1,3,6]
输出:false
示例 2:

输入:[2,1,2,6]
输出:false
示例 3:

输入:[4,-2,2,-4]
输出:true
解释:我们可以用 [-2,-4] 和 [2,4] 这两组组成 [-2,-4,2,4] 或是 [2,4,-2,-4]
示例 4:

输入:[1,2,4,16,8,4]
输出:false

提示:

0 <= A.length <= 30000
A.length 为偶数
-100000 <= A[i] <= 100000

from collections import Counter
class Solution(object):
    def canReorderDoubled(self, A):
        """
        :type A: List[int]
        :rtype: bool
        """
        count = Counter(A)#对于不存在的key,count[key]=0
        # 注意是对count进行排序
        # sorted(count, key=abs)等价于sorted(count.keys(),key = abs)
        for i in sorted(count, key=abs):
            if count[i] > count[i*2]:
                return False
            count[i*2] -= count[i]
        return True

链表随机节点

给定一个单链表,随机选择链表的一个节点,并返回相应的节点值。保证每个节点被选的概率一样。

进阶:
如果链表十分大且长度未知,如何解决这个问题?你能否使用常数级空间复杂度实现?

示例:

// 初始化一个单链表 [1,2,3].
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
Solution solution = new Solution(head);

// getRandom()方法应随机返回1,2,3中的一个,保证每个元素被返回的概率相等。
solution.getRandom();

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

    def __init__(self, head):
        """
        @param head The linked list's head.
        Note that the head is guaranteed to be not null, so it contains at least one node.
        :type head: ListNode
        """
        assert head is not None
        self.head = head        
        self.length = self.Length()

    def Length(self):
        p = self.head
        L = 0
        while p != None:
            L += 1
            p = p.next
        return L

    def getRandom(self):
        """
        Returns a random node's value.
        :rtype: int
        """
        
        k = random.randint(0, self.length-1)
        #print(k)
        p = self.head
        L = 0
        while p != None:
            if L == k:
                break
            L += 1
            p = p.next
        if p == None:
            print(k, self.length)
        return p.val


# Your Solution object will be instantiated and called as such:
# obj = Solution(head)
# param_1 = obj.getRandom()

有序数组中的单一元素

给定一个只包含整数的有序数组,每个元素都会出现两次,唯有一个数只会出现一次,找出这个数。

示例 1:

输入: [1,1,2,3,3,4,4,8,8]
输出: 2
示例 2:

输入: [3,3,7,7,10,11,11]
输出: 10
注意: 您的方案应该在 O(log n)时间复杂度和 O(1)空间复杂度中运行。

import collections
class Solution(object):
    def singleNonDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        count = collections.Counter(nums)
        result = 0
        for key, value in count.items():
            if value == 1:
                result = key
        return result

等差数列划分

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

例如,以下数列为等差数列:

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

1, 1, 2, 5, 7

数组 A 包含 N 个数,且索引从0开始。数组 A 的一个子数组划分为数组 (P, Q),P 与 Q 是整数且满足 0<=P<Q<N 。

如果满足以下条件,则称子数组(P, Q)为等差数组:

元素 A[P], A[p + 1], …, A[Q - 1], A[Q] 是等差的。并且 P + 1 < Q 。

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

示例:

A = [1, 2, 3, 4]

返回: 3, A 中有三个子等差数组: [1, 2, 3], [2, 3, 4] 以及自身 [1, 2, 3, 4]。

思路:
首先遍历原数组 nums,用数组 diffs 存储相邻两个元素之间的差值。

然后遍历 diffs,用数组 cons 存储其中连续相同的差值的数目,比如有 33 个 33 连在一起,意味着原数组中这个位置存在一个最大长度为 44 的等差数列。

然后遍历 cons,对于长度为 n 的等差数列,其所有的长度大于等于 33 的子数列都是等差数列,则一共有 (n-2)(n-1)/2 个等差数列。
全部相加得到结果。

比如:

nums = [1,2,3,4,5,6,12,14,16]
diffs = [1,1,1,1,1,6,2,2]
cons = [5,1,2]
将 1 舍去,nums 中有长度为 5+1 和 2+1 的等差数列
result = (6-2)(6-1)/2 + (3-2)(3-1)/2

class Solution(object):
    def numberOfArithmeticSlices(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
         # 第一次遍历
        diffs = []
        for i in range(len(nums) - 1):
            diffs.append(nums[i + 1] - nums[i])
            
        # 第二次遍历
        cons = []
        a = 1
        for i in range(1, len(diffs)):
            if diffs[i] == diffs[i - 1]:
                a += 1
            else:
                cons.append(a)
                a = 1
        cons.append(a)
        
        # 第三次遍历
        res = 0
        for num in cons:
            res += int(self.calc(num))
        return res
        
    # 用于计算cons内每个数代表的等差数列个数
    def calc(self, n):
        if n == 1:
            return 0
        n += 1
        return (n-2)*(n-1)/2

最长回文子串(连续子串)

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

示例 1:

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

输入: “cbbd”
输出: “bb”

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        
        n = len(s)
        dp = [[False for j in range(n)] for i in range(n)]

        begin_idx = 0
        MaxL = 0

        for j in range(n):
            for i in range(j+1):
                L = j - i + 1
                if s[i] == s[j]:
                    if L <= 3:
                        dp[i][j] = True
                    else:
                        dp[i][j] = dp[i+1][j-1]
                
                if dp[i][j] and L > MaxL:
                    #print(i, j)
                    begin_idx = i
                    MaxL = L
        #print(dp)

        return s[begin_idx:begin_idx+MaxL]

最长回文子串(不连续)

给定一个字符串s,找到其中最长的回文子序列,并返回该序列的长度。可以假设s的最大长度为1000。

示例 1:
输入:

“bbbab”
输出:

4
一个可能的最长回文子序列为 “bbbb”。

示例 2:
输入:

“cbbd”
输出:

2
一个可能的最长回文子序列为 “bb”。

class Solution(object):
    def longestPalindromeSubseq(self, s):
        """
        :type s: str
        :rtype: int
        """
        # 使用dp思想
        n = len(s)
        dp = [[0]*n for i in range(n)]
        # 注意basecase
        for i in range(n):
            dp[i][i] = 1
        # 倒着遍历
        for i in range(n-2,-1,-1):
            for j in range(i+1,n):
                if s[i] == s[j]:
                    dp[i][j] = dp[i+1][j-1] + 2
                else:
                    dp[i][j] = max(dp[i+1][j],dp[i][j-1])
        return dp[0][n-1]

搜索旋转排序数组

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。

搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。

你可以假设数组中不存在重复的元素。

你的算法时间复杂度必须是 O(log n) 级别。

示例 1:

输入: nums = [4,5,6,7,0,1,2], target = 0
输出: 4
示例 2:

输入: nums = [4,5,6,7,0,1,2], target = 3
输出: -1

思路:分成两段,分别进行二分查找,平均时间复杂度O(logn)
各种查找和排序算法的时间和空间复杂度

class Solution(object):
    def BinarySearch(self, nums, start, end, target, n):
        if end < 0 or start > n-1 or (start == end and nums[start] != target) or end < start:
            return -1

        mid = (start + end) // 2
        if nums[mid] == target:
            return mid
        elif nums[mid] > target:
            return self.BinarySearch(nums, start, mid-1, target, n)
        else:
            return self.BinarySearch(nums, mid+1, end, target, n)

    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        boundary = 0
        n = len(nums)

        for i in range(n-1):
            if nums[i] > nums[i+1]:
                boundary = i+1
        
        answer1 = self.BinarySearch(nums, 0, boundary, target, n)
        answer2 = self.BinarySearch(nums, boundary, n, target, n)

        if answer1 == answer2 == -1:
            return -1
        elif answer1 != -1:
            return answer1
        else:
            return answer2

分隔数组以得到最大和

给出整数数组 A,将该数组分隔为长度最多为 K 的几个(连续)子数组。分隔完成后,每个子数组的中的值都会变为该子数组中的最大值。

返回给定数组完成分隔后的最大和。

示例:

输入:A = [1,15,7,9,2,5,10], K = 3
输出:84
解释:A 变为 [15,15,15,9,10,10,10]

提示:

1 <= K <= A.length <= 500
0 <= A[i] <= 10^6

思路:动态规划
在这里插入图片描述

class Solution(object):
    def maxSumAfterPartitioning(self, A, K):
        """
        :type A: List[int]
        :type K: int
        :rtype: int
        """
        n=len(A)
        res=[0]*(n+1)
        for i in range(1,n+1) :
            j=i-1
            mx=float("-inf")
            while i-j <= K and j >= 0 :
                #由于不知道lastSubA的大小,因此对lastSubA的所有可能都进行计算,取最大的
                mx=max(mx,A[j])
                res[i]=max(res[i],res[j]+mx*(i-j)) 
                j-=1
        return res[n]

摆动排序

给你一个无序的数组 nums, 将该数字 原地 重排后使得 nums[0] <= nums[1] >= nums[2] <= nums[3]…。

示例:

输入: nums = [3,5,2,1,6,4]
输出: 一个可能的解答是 [3,5,1,6,2,4]

from heapq import *
class Solution(object):
    def wiggleSort(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        n = len(nums)
        if n <= 1:
            return nums
        
        a = n // 2

        new_nums = zip(nums, [i for i in range(n)])
        lar = nlargest(a, new_nums)
        laridx = [t[1] for t in lar]

        #print(lar)
        smal = [nums[t] for t in range(n) if t not in laridx]
        
        lar = [nums[m] for m in laridx]

        nums[1:n:2] = lar
        nums[0:n:2] = smal
        return nums

排序链表

在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。

示例 1:

输入: 4->2->1->3
输出: 1->2->3->4
示例 2:

输入: -1->5->3->4->0
输出: -1->0->3->4->5

思路:
解答一:归并排序(递归法)
题目要求时间空间复杂度分别为O(nlogn)O(nlogn)和O(1)O(1),根据时间复杂度我们自然想到二分法,从而联想到归并排序;

对数组做归并排序的空间复杂度为 O(n)O(n),分别由新开辟数组O(n)O(n)和递归函数调用O(logn)O(logn)组成,而根据链表特性:

数组额外空间:链表可以通过修改引用来更改节点顺序,无需像数组一样开辟额外空间;
递归额外空间:递归调用函数将带来O(logn)O(logn)的空间复杂度,因此若希望达到O(1)O(1)空间复杂度,则不能使用递归。
通过递归实现链表归并排序,有以下两个环节:

分割 cut 环节: 找到当前链表中点,并从中点将链表断开(以便在下次递归 cut 时,链表片段拥有正确边界);
我们使用 fast,slow 快慢双指针法,奇数个节点找到中点,偶数个节点找到中心左边的节点。
找到中点 slow 后,执行 slow.next = None 将链表切断。
递归分割时,输入当前链表左端点 head 和中心节点 slow 的下一个节点 tmp(因为链表是从 slow 切断的)。
cut 递归终止条件: 当head.next == None时,说明只有一个节点了,直接返回此节点。
合并 merge 环节: 将两个排序链表合并,转化为一个排序链表。
双指针法合并,建立辅助ListNode h 作为头部。
设置两指针 left, right 分别指向两链表头部,比较两指针处节点值大小,由小到大加入合并链表头部,指针交替前进,直至添加完两个链表。
返回辅助ListNode h 作为头部的下个节点 h.next。
时间复杂度 O(l + r),l, r 分别代表两个链表长度。
当题目输入的 head == None 时,直接返回None。

在这里插入图片描述

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

class Solution(object):
    def sortList(self, head):
        """
        :type head: ListNode
        :rtype: ListNode
        """
        if not head or not head.next: return head # termination.
        # cut the LinkedList at the mid index.
        slow, fast = head, head.next
        while fast and fast.next:
            fast, slow = fast.next.next, slow.next
        mid, slow.next = slow.next, None # save and cut.
        # recursive for cutting.
        left, right = self.sortList(head), self.sortList(mid)
        # merge `left` and `right` linked list and return it.
        h = res = ListNode(0)
        while left and right:
            if left.val < right.val: h.next, left = left, left.next
            else: h.next, right = right, right.next
            h = h.next
        h.next = left if left else right
        return res.next

岛屿的最大面积

给定一个包含了一些 0 和 1 的非空二维数组 grid 。

一个 岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。

找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为 0 。)

示例 1:

[[0,0,1,0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,1,1,0,1,0,0,0,0,0,0,0,0],
[0,1,0,0,1,1,0,0,1,0,1,0,0],
[0,1,0,0,1,1,0,0,1,1,1,0,0],
[0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,0,1,1,0,0,0,0]]
对于上面这个给定矩阵应返回 6。注意答案不应该是 11 ,因为岛屿只能包含水平或垂直的四个方向的 1 。

示例 2:

[[0,0,0,0,0,0,0,0]]
对于上面这个给定的矩阵, 返回 0。

注意: 给定的矩阵grid 的长度和宽度都不超过 50。

class Solution(object):
    def maxAreaOfIsland(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        m = len(grid)
        if m == 0: return 0
        n = len(grid[0])
        ans = 0
        def dfs(i, j):
            if i < 0 or i >= m or j < 0 or j >= n: return 0
            if grid[i][j] == 0: return 0
            grid[i][j] = 0
            top = dfs(i + 1, j)
            bottom = dfs(i - 1, j)
            left = dfs(i, j - 1)
            right = dfs(i, j + 1)
            return 1 + sum([top, bottom, left, right])
        for i in range(m):
            for j in range(n):
                ans = max(ans, dfs(i, j))
        return ans

合并区间

给出一个区间的集合,请合并所有重叠的区间。

示例 1:

输入: [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
示例 2:

输入: [[1,4],[4,5]]
输出: [[1,5]]
解释: 区间 [1,4] 和 [4,5] 可被视为重叠区间。

class Solution(object):
    def merge(self, intervals):
        """
        :type intervals: List[List[int]]
        :rtype: List[List[int]]
        """
        intervals.sort()
        m = len(intervals)
        
        i = 0

        while i < m-1:
            if intervals[i][1] >= intervals[i+1][0]:
                # 合并区间
                intervals[i][1] = max(intervals[i][1], intervals[i+1][1])
                del intervals[i+1]
                m -= 1
            else:
                i += 1
        
        return intervals

整数替换

给定一个正整数 n,你可以做如下操作:

  1. 如果 n 是偶数,则用 n / 2替换 n。
  2. 如果 n 是奇数,则可以用 n + 1或n - 1替换 n。
    n 变为 1 所需的最小替换次数是多少?

示例 1:

输入:
8

输出:
3

解释:
8 -> 4 -> 2 -> 1
示例 2:

输入:
7

输出:
4

解释:
7 -> 8 -> 4 -> 2 -> 1

7 -> 6 -> 3 -> 2 -> 1

思路:每遇偶数除以2,没什么好说。
遇到奇数,应变换使其成为4的倍数,目的是使该数下一步变成能连续两次除以2的偶数
因此mod41时减1,mod43时加1
有个例外是3, 3——2——1 比 3——4——2——1更快

class Solution(object):
    def integerReplacement(self, n):
        """
        :type n: int
        :rtype: int
        """
        count = 0
        while n>1:
            if n==3:
                n-=1
            elif n%4==1:
                n-=1
            elif n%4==3:
                n+=1
            else:
                n/=2
            count+=1
        return count

分割数组

给定一个数组 A,将其划分为两个不相交(没有公共元素)的连续子数组 left 和 right, 使得:

left 中的每个元素都小于或等于 right 中的每个元素。
left 和 right 都是非空的。
left 要尽可能小。
在完成这样的分组后返回 left 的长度。可以保证存在这样的划分方法。

示例 1:

输入:[5,0,3,8,6]
输出:3
解释:left = [5,0,3],right = [8,6]
示例 2:

输入:[1,1,1,0,6,12]
输出:4
解释:left = [1,1,1,0],right = [6,12]

提示:

2 <= A.length <= 30000
0 <= A[i] <= 10^6
可以保证至少有一种方法能够按题目所描述的那样对 A 进行划分。

class Solution(object):
    def partitionDisjoint(self, A):
        """
        :type A: List[int]
        :rtype: int
        """
        tmp,pos,m = A[0],0,A[0]
        for i in range(1,len(A)):
            m = max(m,A[i])
            if A[i]<tmp:
                pos = i
                tmp = m
        return pos+1

从英文中重建数字

给定一个非空字符串,其中包含字母顺序打乱的英文单词表示的数字0-9。按升序输出原始的数字。

注意:

输入只包含小写英文字母。
输入保证合法并可以转换为原始的数字,这意味着像 “abc” 或 “zerone” 的输入是不允许的。
输入字符串的长度小于 50,000。
示例 1:

输入: “owoztneoer”

输出: “012” (zeroonetwo)
示例 2:

输入: “fviefuro”

输出: “45” (fourfive)

class Solution(object):
    def originalDigits(self, s):
        """
        :type s: str
        :rtype: str
        """
        res = {}
        for i in s:
            if res.get(i):
                res[i] += 1
            else:
                res[i] = 1
        if res.get('z'):             #0 : z
            res['r'] -= res['z']
            res['o'] -= res['z']
        if res.get('w'):             #2 : w
            res['t'] -= res['w']
            res['o'] -= res['w']
        if res.get('u'):             #4 : u; 1 : o; 3 : r; 5 : f; 
            res['f'] -= res['u']
            res['o'] -= res['u']
            res['r'] -= res['u']
        if res.get('o') and res['o'] > 0:
            res['n'] -= res['o']
        if res.get('f') and res['f'] > 0:   #7 : v
            res['v'] -= res['f']
        if res.get('r') and res['r'] > 0:   #8 : t
            res['t'] -= res['r']
        if res.get('v') and res['v'] > 0:   #6 : s; 9 : n
            res['s'] -= res['v']
            res['n'] -= res['v']
        num = ''
        if res.get('z'):
            num += '0'*res['z']
        if res.get('o'):
            num += '1'*res['o']
        if res.get('w'):
            num += '2'*res['w']
        if res.get('r'):
            num += '3'*res['r']
        if res.get('u'):
            num += '4'*res['u']
        if res.get('f'):
            num += '5'*res['f']
        if res.get('s'):
            num += '6'*res['s']
        if res.get('v'):
            num += '7'*res['v']
        if res.get('t'):
            num += '8'*res['t']
        if res.get('n'):
            num += '9'*(res['n']//2)
        return num

克隆图

给你无向 连通 图中一个节点的引用,请你返回该图的 深拷贝(克隆)。

图中的每个节点都包含它的值 val(int) 和其邻居的列表(list[Node])。

class Node {
public int val;
public List neighbors;
}

测试用例格式:

简单起见,每个节点的值都和它的索引相同。例如,第一个节点值为 1(val = 1),第二个节点值为 2(val = 2),以此类推。该图在测试用例中使用邻接列表表示。

邻接列表 是用于表示有限图的无序列表的集合。每个列表都描述了图中节点的邻居集。

给定节点将始终是图中的第一个节点(值为 1)。你必须将 给定节点的拷贝 作为对克隆图的引用返回。

示例 1:

输入:adjList = [[2,4],[1,3],[2,4],[1,3]]
输出:[[2,4],[1,3],[2,4],[1,3]]
解释:
图中有 4 个节点。
节点 1 的值是 1,它有两个邻居:节点 2 和 4 。
节点 2 的值是 2,它有两个邻居:节点 1 和 3 。
节点 3 的值是 3,它有两个邻居:节点 2 和 4 。
节点 4 的值是 4,它有两个邻居:节点 1 和 3 。
示例 2:

输入:adjList = [[]]
输出:[[]]
解释:输入包含一个空列表。该图仅仅只有一个值为 1 的节点,它没有任何邻居。
示例 3:

输入:adjList = []
输出:[]
解释:这个图是空的,它不含任何节点。
示例 4:

输入:adjList = [[2],[1]]
输出:[[2],[1]]

提示:

节点数不超过 100 。
每个节点值 Node.val 都是唯一的,1 <= Node.val <= 100。
无向图是一个简单图,这意味着图中没有重复的边,也没有自环。
由于图是无向的,如果节点 p 是节点 q 的邻居,那么节点 q 也必须是节点 p 的邻居。
图是连通图,你可以从给定节点访问到所有节点。

"""
# Definition for a Node.
class Node(object):
    def __init__(self, val = 0, neighbors = []):
        self.val = val
        self.neighbors = neighbors
"""

class Solution(object):
    def cloneGraph(self, node):
        """
        :type node: Node
        :rtype: Node
        """
        lookup = {}

        def dfs(node):
            #print(node.val)
            if not node: return
            if node in lookup:
                return lookup[node]
            clone = Node(node.val, [])
            lookup[node] = clone
            for n in node.neighbors:
                clone.neighbors.append(dfs(n))
            
            return clone

        return dfs(node)

分割链表

给你一个链表和一个特定值 x ,请你对链表进行分隔,使得所有小于 x 的节点都出现在大于或等于 x 的节点之前。

你应当保留两个分区中每个节点的初始相对位置。

示例:

输入:head = 1->4->3->2->5->2, x = 3
输出:1->2->2->4->3->5

解一:将小于x的都交换到前面

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

class Solution:
    def partition(self, head: ListNode, x: int) -> ListNode:
        first = True
        head_flag = False
        new_head = ListNode(x-1)
        new_head.next = head

        p = new_head
        q = p.next
        while q:
            print(q.val)
            change = False

            if q.val >= x and first:
                flag = p
                first = False
                if flag == new_head:
                    head_flag = True
            elif q.val < x and not first:
                change = True
                now = p
                p.next = q.next
                q.next = flag.next
                flag.next = q
                flag = flag.next
                
            if change:
                q = now.next
                p = now
            else:
                p = q
                q = q.next
               
        return new_head.next

解二:
用两个链表分别存储小于x和大于等于x的节点

class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        ListNode* small = new ListNode(0);
        ListNode* smallHead = small;
        ListNode* large = new ListNode(0);
        ListNode* largeHead = large;
        while (head != nullptr) {
            if (head->val < x) {
                small->next = head;
                small = small->next;
            } else {
                large->next = head;
                large = large->next;
            }
            head = head->next;
        }
        large->next = nullptr;
        small->next = largeHead->next;
        return smallHead->next;
    }
};

两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

你可以按任意顺序返回答案。
示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]
示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

提示:

2 <= nums.length <= 103
-109 <= nums[i] <= 109
-109 <= target <= 109
只会存在一个有效答案

解法一:暴力穷举

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        n = len(nums)
        #dp = [[0 for j in range(n)] for i in range(n)]
        re = []

        for i in range(n):
            for j in range(n):
                if i != j and nums[i] + nums[j] == target:
                    re = [i,j]
        return re
``
解法二:Hash表

```python
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hashtable = dict()
        for i, num in enumerate(nums):
            if target - num in hashtable:
                return [hashtable[target - num], i]
            hashtable[nums[i]] = i
        return []
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值