dp 刷题记录

仅为记录,某些图片可以自行粘贴gitee网址查看,需要密码就…算了😂

一、 动态规划

原问题可以分解成规模较小的两个子问题,且子问题的解可以复用

2022.1.18 斐波那契

一、 剑指 Offer 10- I. 斐波那契数列

写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项(即 F(N))。斐波那契数列的定义如下:

F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。

答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

/**
 * @param {number} n
 * @return {number}
 */
var fib = function(n) {
    // 暴力
    // const MOD = 1e9+7;
    // if(n === 0) return 0;
    // if(n === 1 || n === 2) return 1;
    // return  (fib (n-1) + fib (n-2))%MOD;

    // // 带备忘录的DP,时间复杂度 O(n)
    // if(n === 0) return 0;
    // const arr = new Array(n+1);
    // return  dp(arr, n);

    // dp数组的迭代
    const MOD = 1e9+7;
    if(n < 2) return n;
    if(n==2) return 1;
    const dp = new Array(n+1);
    dp[1] = dp[2] = 1;
    for(let i = 3; i <= n; i++){
        dp[i] = (dp[i-1] +dp[i-2])%MOD;
    }
    return dp[n];
};

// const dp =(arr, n) =>{
//      const MOD = 1e9+7;
//     if(n == 1 || n == 2) return 1;
//     if(arr[n] != 0) return arr[n];
//     arr[n] = (dp(arr, n-1) + dp(arr, n-2))%MOD;
//     return arr[n];
// }

image-20220118092102571

// 题解时间复杂度O(1)
// 状态压缩,从N缩小为2
var fib = function(n) {
    const MOD = 1000000007;
    if (n < 2) {
        return n;
    }
    let p = 0, q = 0, r = 1;
    for (let i = 2; i <= n; ++i) {
        p = q; 
        q = r; 
        r = (p + q) % MOD;
    }
    return r;
};

二、 509. 斐波那契数

斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 。该数列由 01 开始,后面的每一项数字都是前面两项数字的和。也就是:

```
F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1
```

给你 `n` ,请计算 `F(n)` 。 

2022.1.19

一、 322. 零钱兑换

给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。

计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。

你可以认为每种硬币的数量是无限的。

cccccccccccccccccccccc

二、

2022.1.20

一、 674. 最长连续递增序列

给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。

连续递增的子序列 可以由两个下标 l 和 r(l < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], …, nums[r - 1], nums[r]] 就是连续递增子序列。

/**
 * @param {number[]} nums
 * @return {number}
 */
var findLengthOfLCIS = function(nums) {
   let ans = 0;
   let start = 0;
    for(let i = 0 ; i < nums.length; i++){
        if(i>0 && nums[i] <= nums[i-1])
            start = i;
        ans = Math.max(ans, i - start + 1);
    }
    return ans;
};

image-20220121123746252

二、 300. 最长递增子序列

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

2-1 动态规划
/**
 * @param {number[]} nums
 * @return {number}
 */
var lengthOfLIS = function(nums) {
    // 对dp数组初始化为1
    const numsLen = nums.length;
    const dp = new Array(numsLen).fill(1);
    for(let  i= 0;i < numsLen;i++){
        for(let j =0;j<i;j++){
            if(nums[i] > nums[j]){
                // dp[i]存储的是以nums[i]为最大值的最长递增子序列的个数
                dp[i] = Math.max(dp[i],dp[j]+1);
            }
        }
    }
    let max = 1;
    for(key in dp){
        max = Math.max(dp[key],max);

    }
    return max;
};
2-2 二分搜索法

正常人想不到,更何况,我还是普通人

2022.1.24 二维递增子序列:信封嵌套问题

一、 354. 俄罗斯套娃信封问题

给你一个二维整数数组 envelopes ,其中 envelopes[i] = [wi, hi] ,表示第 i 个信封的宽度和高度。

当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。

请计算 最多能有多少个 信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mFODkLA1-1645370197776)(https://gitee.com/hannah_bingo/yyy/raw/master/image-20220124111602343.png)]

/**
 * @param {number[][]} envelopes
 * @return {number}
 */

 // 时间复杂度O(n方)
var maxEnvelopes = function(envelopes) {
    const enLen = envelopes.length;

    if(enLen === 0){
        return 0;
    }
    // 二维数组arr[i][0]升序排列,arr[i][1]降序
    envelopes.sort((arr1, arr2) =>{
        return arr1[0] !== arr2[0] ? arr1[0] - arr2[0] : arr2[1] - arr1[1];
    })

    // 查找arr[i][1]的LIS
    let max = 1;
    
    // const dp = new Array[enLen].fill(1);
    const dp = new Array(enLen).fill(1);
    for(let i = 1; i<enLen; ++i){
        for(let j = 0 ; j<i;++j){
            if(envelopes[i][1] > envelopes[j][1]) {
                dp[i] = Math.max(dp[i], dp[j]+1);
            }
        }
        max = Math.max(max, dp[i]); 
    }
    return max;
};

image-20220124111627004

二、 673. 最长递增子序列的个数

细节问题

var findNumberOfLIS = function(nums) {
    let n = nums.length, maxLen = 0, ans = 0;
    const dp = new Array(n).fill(0);
    const cnt = new Array(n).fill(0);
    for (let i = 0; i < n; ++i) {
        dp[i] = 1;
        cnt[i] = 1;
        for (let j = 0; j < i; ++j) {
            if (nums[i] > nums[j]) {
                if (dp[j] + 1 > dp[i]) {
                    dp[i] = dp[j] + 1;
                    cnt[i] = cnt[j]; // 重置计数
                } else if (dp[j] + 1 === dp[i]) {
                    cnt[i] += cnt[j];
                }
            }
        }
        if (dp[i] > maxLen) {
            maxLen = dp[i];
            ans = cnt[i]; // 重置计数
        } else if (dp[i] === maxLen) {
            ans += cnt[i];
        }
    }
    return ans;
};

image-20220124204755572

2022.1.26

一、 53. 最大子数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
    const numsLen = nums.length;
    const dp = new Array(numsLen);
    let max = -Infinity;
    for(let i =0; i< numsLen;i++){
        if(i>0){
            dp[i] = (dp[i-1]+nums[i]) > nums[i] ? (dp[i-1]+nums[i]) : nums[i];
        }else dp[0] = nums[0];
        max = Math.max(max, dp[i]);
    }
    return max;
};

image-20220126221035709

2022.2.10

一、1143. 最长公共子序列

给定两个字符串 text1 和 text2,返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 ,返回 0 。

一个字符串的 子序列 是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。

例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。
两个字符串的 公共子序列 是这两个字符串所共同拥有的子序列。

/**
 * @param {string} text1
 * @param {string} text2
 * @return {number}
 */
var longestCommonSubsequence = function(text1, text2) {
    const t1L =  text1.length,t2L = text2.length;
    // base case
    const dp = new Array(t1L + 1).fill(0).map(() => new Array(t2L + 1).fill(0));
    // 状态转移
    // 正向遍历
    for(let i = 1; i <= t1L; i++){
        for(let j = 1; j<=t2L; j++){
            if(text1[i-1] === text2[j-1]){
                dp[i][j] = dp[i-1][j-1] +1;
            }else{
                dp[i][j] = Math.max(dp[i][j-1],dp[i-1][j]);
            }
        }
    }
    return dp[t1L][t2L];
};


二、 72. 编辑距离

给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

插入一个字符
删除一个字符
替换一个字符

/**
 * @param {string} word1
 * @param {string} word2
 * @return {number}
 */
 // 超时
// var minDistance = function(word1, word2) {
//     const len1 = word1.length;
//     const len2 = word2.length;

//     const dp = (i,j) =>{
//         // base case
//         // word1先换到头
//         if(i===-1) return j+1;
//         // word2 先走到头,删除word1剩余的 
//         if(j===-1) return i+1;

//         // 选择
//         if(word1[i] === word2[j]){
//             return dp(i-1,j-1);
//         } else {
//             return Math.min(
//                 dp(i,j-1) + 1,   // 插入
//                 dp(i -1 ,j) + 1,   // 删除
//                 dp(i-1,j-1) + 1    // 替换
//             )
//         }
//     } 
//     return dp(len1-1,len2-1);
// };

//  备忘录优化
var minDistance = function(word1, word2) {
    const w1L = word1.length;
    const w2L = word2.length;
    // 备忘录
    let memo = new Array(w1L+1).fill(-1).map(() => new Array(w2L+1).fill(-1));
    const dp = (i,j) => {
             // base case
        // w1,w2走完
       
         if (i === -1) return j+1;
        if (j === -1) return i+1;
        // 先查备忘录
        if(memo[i][j] !== -1) return memo[i][j];
   

        if(word1[i] === word2[j]){
            memo[i][j] = dp(i-1,j-1);
        } else{
            memo[i][j] = Math.min(
                dp(i-1,j) + 1,  // 删除
                dp(i,j-1) + 1,  // 插入
                dp(i-1,j-1)+1
            )
        }
        return memo[i][j];
    }
    return dp(w1L-1,w2L-1);
};

// DP Table
// var minDistance = function (word1, word2) {
//   let dp = Array.from(Array(word1.length + 1), () =>
//     Array(word2.length + 1).fill(0)
//   );
//   /* base case 是i走完word1或j走完word2,可以直接返回另一个字符串剩下的长度 */
//   // j走完word2 如果i还没走完word1,那么只能用删除操作把word1缩短为word2,也就是直接返回另一个字符串剩下的长度
//   for (let i = 1; i <= word1.length; i++) {
//     dp[i][0] = i;
//   }
//   // 同理  如果i走完word1时j还没走完了word2,那就只能用插入操作把word2剩下的字符全部插入word1
//   for (let j = 1; j <= word2.length; j++) {
//     dp[0][j] = j;
//   }

//   for (let i = 1; i <= word1.length; i++) {
//     for (let j = 1; j <= word2.length; j++) {
//       if (word1[i - 1] === word2[j - 1]) {
//         // 啥也不做
//         dp[i][j] = dp[i - 1][j - 1];
//       } else {
//         // 三选一  哪个操作最后得到的编辑距离最小,就选谁
//         dp[i][j] = Math.min(
//           // 删除
//           // 直接把word1[i]这个字符删掉,前移i继续跟j对比   操作数+1
//           dp[i - 1][j] + 1,
//           // 插入
//           // 直接在word1[i]插入一个和word2[j]一样的字符,那么word2[j]就被匹配了,前移j继续跟i对比
//           dp[i][j - 1] + 1,
//           // 替换
//           // 直接把word1[i]替换成word2[j] 这样它俩就匹配了,同时前移i,j继续对比
//           dp[i - 1][j - 1] + 1
//         );
//       }
//     }
//   }

//   return dp[word1.length][word2.length];
// };

2022.2.12

一、 516. 最长回文子序列

给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。

子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。

/**
 * @param {string} s
 * @return {number}
 */
var longestPalindromeSubseq = function(s) {
    const sL = s.length;
    const dp = new Array(sL+1).fill(0).map(() => new Array(sL+1).fill(0));
    // base case
    for(let i = 0; i < sL; i++){
        dp[i][i] = 1;
    }

    // 状态转移,反向遍历,求dp[0][j]
    for(let i = sL-2; i >= 0; i--){
        for(let j = i+1;j<sL;j++){
            if(s[i] === s[j]){
                dp[i][j] = dp[i+1][j-1] + 2;
            }else {
                dp[i][j] = Math.max(dp[i][j-1],dp[i+1][j]);
            }
        }
    }
    return dp[0][sL -1];

};

image-20220212100913121

CCCCCCCCC,调试时什么奇奇怪怪的问题

二、 最长回文字串

给你一个字符串 s,找到s中最长回文子串

class Solution {
   public String longestPalindrome(String s) {
    int n = s.length();
    String res = "";
    boolean[][] dp = new boolean[n][n];
    for (int i = n - 1; i >= 0; i--) {
        for (int j = i; j < n; j++) {
            dp[i][j] = s.charAt(i) == s.charAt(j) && (j - i < 2 || dp[i + 1][j - 1]); //j - i 代表长度减去 1        
            if (dp[i][j] &&  j - i + 1 > res.length()) {
                res = s.substring(i, j + 1);
            }
        }
    }
    return res;
}

}

三、 1312. 让字符串成为回文串的最少插入次数

给你一个字符串 s ,每一次操作你都可以在字符串的任意位置插入任意字符。

请你返回让 s 成为回文串的 最少操作次数

image-20220212154847621

/**
 * @param {string} s
 * @return {number}
 */
var minInsertions = function(s) {
    const sL = s.length;
        const dp = new Array(sL+1).fill(0).map(()=>new Array(sL+1).fill(0));
        // base case  i==j时dp[i][j]=0
        // 状态转移,斜向遍历
        for(let i = sL-2; i >= 0; i--){
            for(let j = i+1; j <sL; j++){
                if(s[i] === s[j]){
                    dp[i][j] = dp[i+1][j-1]; 
                } else {
                    // 选择代价最小的插入1
                    dp[i][j] = Math.min(dp[i+1][j],dp[i][j-1])+1;
                }
            }
        }
        return dp[0][sL-1];

};

四、 10. 正则表达式匹配

面试题19. 正则表达式匹配

请实现一个函数用来匹配包含’. ‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但与"aa.a"和"ab*a"均不匹配。

/**
 * @param {string} s
 * @param {string} p
 * @return {boolean}
 */
var isMatch = function(s, p) {
    const sL = s.length;
    const pL = p.length;
    
    dp = (s,i,p,j) => {
        // base case,s和p走完一个了
        if(j === pL) {
            return i === sL;
        } else if (i === sL){
            // 匹配规则没走完--->
            // 剩余不是 a* 
            if((pL - j)%2 === 1 ){
                return false;
            }
            // 剩余x*y*z*
            while(j+1 < pL){
                if(p[j+1] != '*'){
                    return false;
                }
                j += 2;
            }
            return true;
        }

        let res = false;
        // 状态转移
        // 匹配
        if(s[i] === p[j] || p[j] === '.'){
            if(j<pL-1 && p[j+1] === '*'){
                // 匹配0或多次
                res =  dp(s,i,p,j+2) || dp(s,i+1,p,j);
            } else {
                // 正常匹配
                res = dp(s,i+1,p,j+1);
            }
        }
        else {
            // 匹配0次
            if(j < pL-1 && p[j+1] === '*'){
                res = dp(s,i,p,j+2);
            } else {
                res = false;
            }
        }
    
        return res;
    }
    dp(s,0,p,0);
};
  • 如果我有罪,请不要让我检查了小十遍代码,undefined,undefined,undefined,undefined,undefined…
  • wacaowocao---------------------------------------------------------哇哇哇哇哇哇哇

五、 887. 鸡蛋掉落

给你 k 枚相同的鸡蛋,并可以使用一栋从第 1 层到第 n 层共有 n 层楼的建筑。

已知存在楼层 f ,满足 0 <= f <= n ,任何从 高于 f 的楼层落下的鸡蛋都会碎,从 f 楼层或比它低的楼层落下的鸡蛋都不会破。

每次操作,你可以取一枚没有碎的鸡蛋并把它从任一楼层 x 扔下(满足 1 <= x <= n)。如果鸡蛋碎了,你就不能再次使用它。如果某枚鸡蛋扔下后没有摔碎,则可以在之后的操作中 重复使用 这枚鸡蛋。

请你计算并返回要确定 f 确切的值 的 最小操作次数 是多少?

// /**
//  * @param {number} k
//  * @param {number} n
//  * @return {number}
//  */
//  // 递归超时
// var superEggDrop = function(k, n) {
//     const memo = new Map();
//     function dp (k, n) {
//         if (k === 1) return n; // 当k为1时,只能线性扫描所有楼层
//         if (n === 0) return 0;
//         if (memo.has(k + '' + n)) {
//             return memo.get(k + '' + n)
//         }
//         let res = Infinity;
//         for (let i = 1; i <= n; i++) {
//             res = Math.min(
//                 res,
//                 Math.max(
//                     dp(k, n - i),
//                     dp(k - 1, i - 1)
//                 ) + 1
//             )
//         }
//         memo.set(k + '' + n, res)
//         return res;
//     }
//     return dp(k, n)
// };

var superEggDrop= function(k, n) {
    const dp = new Array(k + 1).fill(0).map(() => new Array(n + 1).fill(0));
    let m = 0;
    while (dp[k][m] < n) {
        m++;
        for (let i = 1; i <= k; i++) {
            dp[i][m] = dp[i][m - 1] + dp[i - 1][m - 1] + 1;
        }
    }
    return m;
};


2022.2.15

第一章 背包问题

1-1 0-1背包问题
一、 474. 一和零

给你一个二进制字符串数组 strs 和两个整数 m 和 n 。

请你找出并返回 strs 的最大子集的长度,该子集中 最多 有 m 个 0 和 n 个 1 。

如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。

/**
 * @param {string[]} strs
 * @param {number} m
 * @param {number} n
 * @return {number}
 */

//0-1背包
var findMaxForm = function(strs, m, n) {
    // m,n看作背包的W和N
    // dp[i][j] 表示 对于 还剩i个0和j个1 ,这种情况下 strs 的最大子集 的长度
    const dp = new Array(m+1).fill(0).map(() => new Array(n+1).fill(0));
    // base case
    // for(let i = 0; i < m;i++){
    //     dp[i][0] = 0;
    // }
    // for(let j = 0; j < n; j++){
    //     dp[0][j] = 0;
    // }

    for(let p= 0; p < strs.length; p++){
        let zeroNum = 0,oneNum = 0;
        const str = strs[p];
        for(let s = 0; s <str.length;s++ ){
            console.log(str[s]);
            if(str[s] === '0') ++zeroNum;
            else ++oneNum;
        }
        for(let i = m; i >= zeroNum; i--){
            for(let j = n; j >= oneNum; j--){
                dp[i][j] = Math.max(dp[i][j],dp[i-zeroNum][j-oneNum] + 1);
            }
        }
         
    }
     return dp[m][n];
  
};

image-20220215125208322

二、 494. 目标和

给你一个整数数组 nums 和一个整数 target 。

向数组中的每个整数前添加 ‘+’ 或 ‘-’ ,然后串联起所有整数,可以构造一个 表达式 :

例如,nums = [2, 1] ,可以在 2 之前添加 ‘+’ ,在 1 之前添加 ‘-’ ,然后串联起来得到表达式 “+2-1” 。
返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。

image-20220215224902970

三、 416. 分割等和子集

给你一个 只包含正整数非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

/**
 * @param {number[]} nums
 * @return {boolean}
 */
var canPartition = function(nums) {
    // 
    let sum = 0;
    nums.forEach(item => sum += item);
    if(sum %2 !== 0) return false;

    // dp[i][i] : 对于前i个物品,是否能够装满容量为j;
    const dp = new Array(nums.length+1).fill(0).map(()=>new Array(sum / 2 +1) );
    // base case
    for(let i = 0; i< nums.length;i++){
        dp[i][0] = true;
    }
    // 状态装一
    for(let i = 1; i<= nums.length;i++){
        for(let  j =1 ;j <= sum /2;j++){
            if(j-nums[i-1] <0){
                dp[i][j] = dp[i-1][j];
            }else {
                dp[i][j] = dp[i-1][j] || dp[i-1][j-nums[i-1]];
            }
        }
    }

    // 求dp[nums.length-1][sum/2];
    return dp[nums.length][sum/2];
};

image-20220215234042247

心态有些炸

四、1049. 最后一块石头的重量 II

我不会!!这TM题解咋感觉是子集背包的题解???

1-2-14-3 完全背包 问题
一、[bug]322. 零钱兑换

给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。

计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1 。

你可以认为每种硬币的数量是无限的。

/**
 * @param {number[]} coins
 * @param {number} amount
 * @return {number}
 */


var coinChange = function(coins, amount) {
    // dp[i][j] : 对于前i个硬币,背包容量为j时,装满背包所需最少的硬币数量
    const dp = new Array(coins.length +1).fill(0).map(()=>new Array(amount+1).fill(0));
    // base case

    // 状态转移
    for(let i = 1; i <= coins.length;++i){
        for(let j = 1; j<=amount;++j){
            if(j-coins[i-1] < 0){
                dp[i][j] = dp[i-1][j];
            } else{
                dp[i][j] = Math.min(dp[i-1][j-coins[i-1]]+1 ,dp[i][j-coins[i-1]]+1);
            }
        }
    }
    //求 dp[coins.length][amout]

  return dp[coins.length][amount];
};

image-20220216115347678

二、 518. 零钱兑换 II

给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。

请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。

假设每一种面额的硬币有无限个。

题目数据保证结果符合 32 位带符号整

/**
 * @param {number} amount
 * @param {number[]} coins
 * @return {number}
 */
var change = function(amount, coins) {
// dp[i][j] : 对于前i个硬币,背包容量为j时,有dp[i][j]种凑法
    const dp = new Array(coins.length +1).fill(0).map(()=>new Array(amount+1).fill(0));
    // base case
    for(let  i = 0; i <= coins.length;i++){
        dp[i][0] = 1;
    } 
    // 状态转移
    for(let i = 1; i <= coins.length;++i){
        for(let j = 1; j<=amount;++j){
            if(j-coins[i-1] < 0){
                dp[i][j] = dp[i-1][j];
            } else{
                dp[i][j] = dp[i-1][j] + dp[i][j-coins[i-1]];
            }
        }
    }
    //求 dp[coins.length][amout]

  return dp[coins.length][amount];
};

image-20220216113600390

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值