LeetCode 分类整理(01) DFS 草稿

subset

// solution 2 version B

// a slightly different version from version A.

// make a slight optimization while doing right shift.

public class Solution {

   public List<List<Integer>> subsets(int[] nums) {

       List<List<Integer>> listOfList = new ArrayList<List<Integer>> ();

       for (int i = 0; i < Math.pow(2, nums.length); ++i) {

           List<Integer> oneList = new ArrayList<Integer>();

           //ERROR1: should operate on the copy of i in the inner loop, pay attention

           // to where to write the statment of saving the copy.

           int copyI = i;

           for (int position = 0; position < nums.length; ++position) {

               if ((1 & copyI) == 1) {

                   oneList.add(nums[position]);

               }

               copyI = (copyI>>1);

           }

           Collections.sort(oneList);

           listOfList.add(oneList);

       }

       return listOfList;

   }

}


// solution 2 version A

public class Solution {

   public List<List<Integer>> subsets(int[] nums) {

       List<List<Integer>> listOfList = new ArrayList<List<Integer>> ();

       for (int i = 0; i < Math.pow(2, nums.length); ++i) {

           List<Integer> oneList = new ArrayList<Integer>();

           //ERROR1: should operate on the copy of i in the inner loop, pay attention

           // to where to write the statment of saving the copy.

           //int copyI = i; // Wrong place

           for (int position = 0; position < nums.length; ++position) {

               int copyI = i; // Right place

               copyI = (copyI>>position);

               if ((1 & copyI) == 1) {

                   oneList.add(nums[position]);

               }

           }

           Collections.sort(oneList);

           listOfList.add(oneList);

       }

       return listOfList;

   }

}



/*   

// Solution 1

public class Solution {

void subsetsHelper(int[] nums, List<Integer> each,  List<List<Integer> > arrList, int start , int len) {

   

   // WRONG : arrList.add(each);

   // each is only a reference, should use the new operation to instantiate a new array.

// NOTE: something different from the normal DFS template.

// NOTE: we need to walk throught every node of the tree, including both the leaf node and the non leaf node, hence we do not use the normal "if (star == len) {... return ;}".

// NOTE:  if Foo is a subtype (subclass or subinterface) of Bar, and G is some generic type declaration, it is not the case that G<Foo> is a subtype of G<Bar>. This is probably the hardest thing you need to learn about generics, because it goes against our deeply held intuitions.

// https://docs.oracle.com/javase/tutorial/extra/generics/subtype.html

arrList.add(new ArrayList<Integer> (each));

for (int i = start; i < len; ++i) { // DFS

each.add(nums[i]);

subsetsHelper(nums, each, arrList, i + 1, len);

each.remove(each.size() - 1);

}

};

   public List<List<Integer>> subsets(int[] nums) {

       

       // WRONG: List<List<Integer> > result = new ArrayList<List<Integer> > ();

       // if you had a List<List<Integer>> then you'd be able to add a LinkedList<Integer> to it.

       //But you can't do this for an ArrayList<ArrayList<Integer>>, so the latter can't possibly be a type of List<List<Integer>>.

       

       //The reason is that generics are not covariant.

       // Consider simpler case:

       

       // List<Integer> integers = new ArrayList<Integer>();

       // List<Number> numbers = integers; // cannot do this

       // numbers.add(new Float(1337.44));

       // Now List holds a Float, which is certainly bad.

       

       // Same for your case.

       

       // List<ArrayList<Integer>> al = new ArrayList<ArrayList<Integer>>();

       // List<List<Integer>> ll = al; // cannot do this

       // ll.add(new LinkedList<Integer>())

       // Now you have a list ll which holds LinkedList, but the al is declared as a List of ArrayLists.

       

   List<List<Integer> > result = new ArrayList<List<Integer> > ();

   ArrayList<Integer> each = new ArrayList<Integer>();

   Arrays.sort(nums);

   subsetsHelper(nums, each, result, 0, nums.length);

   return result;

   }

//public static void main(String[] args) {

//// TODO Auto-generated method stub

//  Solution subsets = new Solution();

//  //int [] arr = new int []{2, 3, 1};

//  int [] arr = new int []{0};

//  List<List<Integer> > arrArr = subsets.subsets(arr);

//  System.out.println(arrArr.size());

//}

}

*/


permutation I

public class Solution {

   

   private void swap (int [] nums, int a, int b) {

       int temp = nums[a];

       nums[a] = nums[b];

       nums[b] = temp;

   }

   private void dfs(int[] nums, List<List<Integer>> result, int start, int end) {

       if (start == end - 1) {

           Integer[] nums2 = new Integer[nums.length];

           for (int index = 0; index < nums.length; ++index) {

               nums2[index] = nums[index];

           }

           result.add(new ArrayList<Integer>(Arrays.asList(nums2)));

       }

       //for ( int i = start + 1;  i < end; ++i) {

       for ( int i = start;  i < end; ++i) {       //NOTE: this dfs switch begins from itself.

           swap(nums, start, i);

           dfs(nums, result, start + 1, end); // NOTE: here it should be start + 1, not i + 1.

           swap(nums, start, i);

       }

   }

   public List<List<Integer>> permute(int[] nums) {

       List<List<Integer>> result = new ArrayList<List<Integer>>();

       dfs(nums, result, 0, nums.length);

       return result;

   }

}


permutation II

public class Solution {

   

   private void swap (int [] nums, int a, int b) {

       int temp = nums[a];

       nums[a] = nums[b];

       nums[b] = temp;

   }

   

   private boolean isRepeated(int [] nums, int begin, int target) {

       for (int i = begin; i <target ; ++i) {

           if (nums[target] == nums[i]) {

               return true;

           }

       }

       return false;

   }

   

   private void dfsUnique(int[] nums, List<List<Integer>> result, int start, int end) {

       if (start == end - 1) {

           //System.out.println("start=" + start + ", end=" + end + "," + Arrays.toString(nums));

           Integer[] nums2 = new Integer[nums.length];

           for (int index = 0; index < nums.length; ++index) {

               nums2[index] = nums[index];

           }

           result.add(Arrays.asList(nums2));

       }

       for ( int i = start;  i < end; ++i) {

           

           // ERROR1:

           /*this will only deal with repeatence if in the first steps of the iteration.

           in the later stages of the iteration, the permutaion will change the orders of the numbers, making

           them not sorted, thus invalidating the condition below.

           To solve this, we should use the isRepeated()function below, to search for repeatence and filter them out.

           if (i != start && nums[i] == nums[start]) {

                continue;

            }

           */

           

           if (isRepeated(nums, start, i)) {

               continue;

           }

           swap(nums, start, i);

           dfsUnique(nums, result, start + 1, end);

           swap(nums, start, i);

       }

   }


   public List<List<Integer>> permuteUnique(int[] nums) {

       Arrays.sort(nums);

       List<List<Integer>> result = new ArrayList<List<Integer>>();

       dfsUnique(nums, result, 0, nums.length);

       return result;

   }


}


Combination Sum

public class Solution {

   public void dfs(int[] candidates, int target, List<Integer> each, List<List<Integer>> all, int start) {

       if (target < 0 ) {

           return;

       } else if (target == 0) {

           //ERROR1:

           // should not use all.add(each);

           // should remember to instantiate a new ArrayList.

           all.add(new ArrayList<Integer> (each));

       } else {

           for (int i = start; i < candidates.length; ++i) {

               each.add(candidates[i]);

               // ERROR2:

               // should remember to filter out the repetence in the result.

               // if with out the "int start" parameter, then there will be repetence left in the result.

               dfs(candidates, target - candidates[i], each, all, i);

               each.remove(each.size() - 1);

           }

       }

   }

   

   public List<List<Integer>> combinationSum(int[] candidates, int target) {

       Arrays.sort(candidates);

       List<Integer> each = new ArrayList<Integer>();

       List<List<Integer>> all = new ArrayList<List<Integer>>();

       dfs(candidates, target, each, all, 0);

       return all;

   }

}


/*

//error: fail to filter out the repeatence in the results.

public class Solution {

   public void dfs(int[] candidates, int target, List<Integer> each, List<List<Integer>> all) {

       if (target < 0 ) {

           return;

       } else if (target == 0) {

           //all.add(each);

           all.add(new ArrayList<Integer> (each));

       } else {

           for (int i = 0; i < candidates.length; ++i) {

               each.add(candidates[i]);

               dfs(candidates, target - candidates[i], each, all);

               each.remove(each.size() - 1);

           }

       }

   }

   

   public List<List<Integer>> combinationSum(int[] candidates, int target) {

       Arrays.sort(candidates);

       List<Integer> each = new ArrayList<Integer>();

       List<List<Integer>> all = new ArrayList<List<Integer>>();

       dfs(candidates, target, each, all);

       return all;

   }

}

*/



Combination Sum II

// ERROR 1: refere to Combination Sum I

public class Solution {

   public void dfs(int[] candidates, int target, List<Integer> each, List<List<Integer>> all, int start) {

       if (target < 0 ) {

           return;

       } else if (target == 0) {

           all.add(new ArrayList<Integer> (each));

       } else {

           //ERROR 2: note the "plus 1" should be put in the dfs() part, not int the for loop .

           //for (int i = start + 1; i < candidates.length; ++i) {

           for (int i = start; i < candidates.length; ++i) {

               // ERROR3: should filter out repetencen in the for loop, since this is a collection of numbers, not a set of numbers in Combiation Sum I.

               if (i != start && candidates[i] == candidates[i - 1]) {

                   continue;

               }

               each.add(candidates[i]);

               dfs(candidates, target - candidates[i], each, all, i + 1);

               each.remove(each.size() - 1);

           }

       }

   }

   

   public List<List<Integer>> combinationSum2(int[] candidates, int target) {

       Arrays.sort(candidates);

       List<Integer> each = new ArrayList<Integer>();

       List<List<Integer>> all = new ArrayList<List<Integer>>();

       dfs(candidates, target, each, all, 0);

       return all;

   }

}



Combination Sum III

public class Solution {

   

   private void dfs(int start, int length, int target, List<List<Integer>> all, List<Integer> each, boolean[] isUsed) {

           if (start == length ) {

               if (target == 0) {

                   // ERROR 3:

                   // Should use new keyword to add the instantiation of the list to all, else it will cause problem as below:

                   // Input:

                   // 2, 6

                   // Output:

                   // [[],[]]

                   // Expected:

                   // [[1,5],[2,4]]

                   // all.add(each);

                   all.add(new ArrayList<Integer> (each));

               }

               return;

           }

           for (int i = 1; i < 10; ++i) {

               if (isUsed[i]) {

                   continue;

               }

               // ERROR1: java list uses size() == 0 to determ if it is empty

               //if (!each.empty() && each.get(each.size() - 1) > i) {

               if (each.size() != 0 && each.get(each.size() - 1) > i) {

                   continue;

               }

               each.add(i);

               isUsed[i] = true;

               dfs(start + 1, length, target - i, all, each, isUsed);

               each.remove(each.size() - 1);

               isUsed[i] = false;

           }

   }

   

   public List<List<Integer>> combinationSum3(int k, int n) {

       List<List<Integer> > all = new ArrayList<List<Integer>> ();

       List<Integer> each = new ArrayList<Integer>();

       boolean[] isUsed = new boolean[10];

       dfs(0, k, n, all, each, isUsed);

       //ERROR2: missing return statement;

       return all;

   }

}



Combinations

//ERROR2 :TLE

//Last executed input: 13, 13

public class Solution {

   private void dfs (int start, int number, int length, List<Integer> each, List<List<Integer>>  all) {

       //NOTE1 : note the finish condition, uses "each.size()" instead of a single variable.

       if(each.size() == length) {

           all.add(new LinkedList<Integer>(each));

           return;

       }

       for (int i = start; i <= number; ++i) {

           each.add(i);

           //NOTE2: use "i + 1" as a way to filer out repetence.

           dfs(i + 1, number, length, each, all);

           each.remove(each.size() - 1);

       }

   }


   public List<List<Integer>> combine(int n, int k) {

       //ERROR 1: List is abstract, cannot be instantiated.

       //List<Integer> each = new List<Integer> ();

       List<Integer> each = new LinkedList<Integer> ();

       List<List<Integer>> all = new LinkedList<List<Integer>> ();

       if (n < k || n == 0 || k == 0) {

           return all;

       }

       dfs(1, n, k, each, all);

       return all;

   }

}



Letter Combination of a Phone Number

public class Solution {

   

   private void dfs (String digits, int start, int length, String [] dict, StringBuilder each, List<String> all) {

       if (start == length) {

           all.add(new String(each.toString()));

           return;

       }

       int index = digits.charAt(start) - '0';

       for (int i = 0; i<dict[index].length(); ++i) {

           // ERROR2: incorrectly messed up "start" and "index"

           each.append(dict[index].charAt(i));

           //each.append(dict[start].charAt(i));

           dfs(digits, start + 1, length, dict, each, all);

           each.deleteCharAt(each.length() - 1);

       }

   }

   public List<String> letterCombinations(String digits) {

       //ERORR1 Grammar Error

       //String [10] dict = new String[] {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};

       String[] dict = new String[] {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};

       StringBuilder each = new StringBuilder();

       List<String> all = new ArrayList<String>();

       //ERROR3 the should deal with the "empty input" edge case.

       if (digits.isEmpty()) {

           return all;

       }

       dfs (digits, 0, digits.length(), dict, each, all);

       return all;

   }

}




Palindrome Partitioning

//ERROR1: TLE

// Last executed input: "ab"

public class Solution {

   private boolean isPalindrome(String s, int start, int end) {

       // ERROR1: TLE

       // The while loop below caused a TLE, the loop will just run infinitely.

       // while (start < end) {

       //     if(s.charAt(start) == s.charAt(end)){

           while (start <= end && s.charAt(start) == s.charAt(end)) {        

               ++start;

               //ERROR2

               //++end;

               --end;

           }

       return start >= end;

   }

   private void dfs(String s, int start, int end, ArrayList<String> each, List<List<String>> all) {

       if ( start == end) {

           all.add(new ArrayList<String> (each));

           return;

       }

       for (int i = start; i <end; ++i) {

           if (isPalindrome(s, start, i)) {

               each.add(s.substring(start, i + 1));

               dfs(s, i + 1, end, each, all);

               each.remove(each.size() - 1);

           }

       }

   }

   

   public List<List<String>> partition(String s) {

       ArrayList<String> each = new ArrayList<String>();

       List<List<String>> all = new ArrayList<List<String>>();

       if (s.isEmpty())  {

           return all;

       }

       dfs(s, 0, s.length(), each, all);

       return all;

   }

}




restore IP address

//ERROR1

/*

Input:

"010010"

Output:

["0.1.0.010","0.1.00.10","0.1.001.0","0.10.0.10","0.10.01.0","0.100.1.0","01.0.0.10","01.0.01.0","01.00.1.0","010.0.1.0"]

Expected:

["0.10.0.10","0.100.1.0"]

*/

public class Solution {

   private void dfs(List<String> each, List<String> all, String s, int start, int end) {

       if(each.size() == 4 && start == end){

           StringBuilder sb = new StringBuilder();

           for (String item : each) {

               sb.append(item);

               sb.append(".");

           }

           sb.deleteCharAt(sb.length() - 1);

           all.add(sb.toString());

           return;

       }

       for (int i = start ; i < start + 3 && i < end; ++i) {

           //ERROR1:

           //see the error case above. this line is added, aiming at the error case above "010010"

           if (s.charAt(start) == '0' && i - start > 0) {

               continue;

           }

           int thisSection = Integer.parseInt(s.substring(start, i + 1));

           if (thisSection > 255) {

               continue;

           }

           each.add(s.substring(start, i + 1));

           dfs(each, all, s, i + 1, end);

           each.remove(each.size() - 1);

       }

   }


   public List<String> restoreIpAddresses(String s) {

       List<String> restoredList = new ArrayList<String>();

       if (s.length() < 4 || s.length() > 12) {

           return restoredList;

       }

       List<String> each = new ArrayList<String> ();

       dfs(each, restoredList, s, 0, s.length());

       return restoredList;

   }


   // public static void main (String [] args) {

   //     Solution s = new Solution();

   //     List<String> res = s.restoreIpAddresses("25525511135");

   //     //NOTE1: print list in one line.

   //     System.out.println(Arrays.toString(res.toArray()));

   // }

}






Generate Parenthesis

public class Solution {


   public void dfs(int leftRem, int rightRem, StringBuilder each, List<String> all) {

       if (leftRem == 0 && rightRem == 0) {

           all.add(each.toString());

       } else {

           if (leftRem > 0) {

               each.append("(");

               dfs(leftRem - 1, rightRem, each, all);

               each.deleteCharAt(each.length() - 1);

           }

           if (rightRem > leftRem) {

               each.append(")");

               dfs(leftRem, rightRem - 1, each, all);

               each.deleteCharAt(each.length() - 1);

           }

       }

   }

   public List<String> generateParenthesis(int n) {

       List<String> all = new ArrayList<String> ();

       dfs(n, n, new StringBuilder(), all);

       return all;

   }

}



Binary Tree Paths

解法一: 现在也不知道错在哪里

错得太2了,啊啊啊。因为treeNode.val 可能是1位,2位,或者n位数,所以这个解法无法知道删除的时候删掉几个字符。

/**

* Definition for a binary tree node.

* public class TreeNode {

*     int val;

*     TreeNode left;

*     TreeNode right;

*     TreeNode(int x) { val = x; }

* }

*/

public class Solution {

   public void dfs (TreeNode root, StringBuilder each, List<String> all) {

       if (root == null) {return;}

       each.append("->");

       each.append(Integer.toString(root.val));

       if (root.left == null && root.right == null) {

           // each.deleteCharAt(0);

           // each.deleteCharAt(1);            

           all.add(each.toString().substring(2));

           return;

       }

       if (root.left != null) {

           dfs(root.left, each, all);

           each.deleteCharAt(each.length() - 1);

           each.deleteCharAt(each.length() - 1);

           each.deleteCharAt(each.length() - 1);            

       }

       if (root.right != null) {

           dfs(root.right, each, all);

           each.deleteCharAt(each.length() - 1);

           each.deleteCharAt(each.length() - 1);

           each.deleteCharAt(each.length() - 1);

       }

   }

   public List<String> binaryTreePaths(TreeNode root) {

       List<String> all = new ArrayList<String> ();

       if (root == null) {

           return all;

       }

       StringBuilder each = new StringBuilder();

       //each.append(Integer.toString(root.val));

       dfs(root, each, all);

       return all;

   }

}

解法二:正确

/**

* Definition for a binary tree node.

* public class TreeNode {

*     int val;

*     TreeNode left;

*     TreeNode right;

*     TreeNode(int x) { val = x; }

* }

*/

public class Solution {

   public void dfs (TreeNode root, List<TreeNode> each, List<String> all) {

       if (root == null) {return;}

       each.add(root);

       if (root.left == null && root.right == null) {

           StringBuilder sb = new StringBuilder();

           for (TreeNode node : each) {

               sb.append("->");

               sb.append(node.val);

           }

           all.add(sb.substring(2));

           return;

       }

       if (root.left != null) {

           dfs(root.left, each, all);

           each.remove(each.size() - 1);

       }

       if (root.right != null) {

           dfs(root.right, each, all);

           each.remove(each.size() - 1);            

       }

   }

   public List<String> binaryTreePaths(TreeNode root) {

       List<String> all = new ArrayList<String> ();

       List<TreeNode> each = new ArrayList<TreeNode> ();

       if (root == null) {

           return all;

       }

       dfs(root, each, all);

       return all;

   }

}




Sum root to leaf numbers

/**

* Definition for a binary tree node.

* public class TreeNode {

*     int val;

*     TreeNode left;

*     TreeNode right;

*     TreeNode(int x) { val = x; }

* }

*/

//第三种,jiuzhang答案, improvement over 第二种方式

public class Solution {

   public int sumNumbers(TreeNode root) {

       return dfs(root, 0);

   }


   private int dfs(TreeNode root, int prev){

       if (root == null) {

           return 0;

       }

       int sum = root.val + prev * 10;

       if(root.left == null && root.right == null) {

           return sum;

       }

       return dfs(root.left, sum) + dfs(root.right, sum);

   }

}

// //第二种,使用return int方式

// public class Solution {

//     public int helper (TreeNode root, int sum) {

//         int total = 0;

//         if (root.left == null && root.right == null) {

//             total = sum * 10 + root.val;

//             return total;

//         }

//         if (root.left != null) {

//             total += helper(root.left, sum * 10 + root.val);

//         }

//         if (root.right != null) {

//             total += helper(root.right, sum * 10 + root.val);

//         }

//         return total;

//     }

//     public int sumNumbers(TreeNode root) {

//         if (root == null) {

//             return 0;

//         }

//         return helper(root, 0);

//     }

// }

//第一种,使用private var

// public class Solution {

//     private int total;

//     public void helper (TreeNode root, int sum) {

//         if (root.left == null && root.right == null) {

//             total = total + sum * 10 + root.val;

//         }

//         if (root.left != null) {

//             helper(root.left, sum * 10 + root.val);

//         }

//         if (root.right != null) {

//             helper(root.right, sum * 10 + root.val);

//         }

//     }

//     public int sumNumbers(TreeNode root) {

//         if (root == null) {

//             return 0;

//         }

//         helper(root, 0);

//         return total;

//     }

// }




Word Search

/*

ERROR1: example:  ["a"], "a"

注意这两句顺序不能换,否则出现上面错误

       if (index == word.length()) {

           return true;

       }

       if (i >= height || i < 0 || j >= width || j< 0) {

           return false;

       }

ERROR2:    Input:  ["aa"], "aaa"   Output: true   Expected: false

需要记录已经用过的字符,需要满足no more than once条件。

*/

public class Solution {

   public boolean dfs(char[][] board, boolean used[][], String word, int i, int j, int height, int width, int index)  {

       if (index == word.length()) {

           return true;

       }

       if (i >= height || i < 0 || j >= width || j< 0) {

           return false;

       }

       if (used[i][j] == false && word.charAt(index) == board[i][j]) {

           used[i][j] = true;

           if(dfs(board, used, word, i + 1, j, height, width, index + 1) ||

                 dfs(board, used, word, i - 1, j, height, width, index + 1) ||

                 dfs(board, used, word, i, j + 1, height, width, index + 1) ||

                 dfs(board, used, word, i, j - 1, height, width, index + 1)) {

               return true;

           }

           used[i][j] = false;

       }

       return false;

   }

   public boolean exist(char[][] board, String word) {

       if (board.length == 0 || board[0].length == 0 || word.equals("")) {

           return false;

       }        

       boolean [][] used = new boolean[board.length][board[0].length];

       for (int i = 0; i <board.length; ++i) {

           for (int j = 0; j <board[0].length; ++j) {

               if (dfs(board, used, word, i, j, board.length, board[0].length, 0)) {

                   return true;

               }

           }

       }

       return false;

   }

}

还有一个减少空间使用的办法是,不用used[][]数组,直接在board[][]上修改。比如,假设board[0][1] = ‘a’正好匹配word中的一个字符,那么就在DFS之前修改board为board[0][1] = ’#‘等等任意一个不会在word中出现的字符。




Number of Islands

Solution 1 DFS

public class Solution {

   public void dfs(char[][] grid, int i, int j, int rows, int cols) {

           grid[i][j] = '#';

           if (i - 1 >= 0 && grid[i - 1][j] == '1') {

               dfs(grid, i - 1, j, rows, cols);    

           }

           if (i + 1 < rows && grid[i + 1][j] == '1') {

               dfs(grid, i + 1, j, rows, cols);    

           }

           if (j - 1 >= 0 && grid[i][j - 1] == '1') {

               dfs(grid, i, j - 1, rows, cols);    

           }

           if (j + 1 < cols && grid[i][j + 1] == '1') {

               dfs(grid, i, j + 1, rows, cols);    

           }            

               

       }

   

   public int numIslands(char[][] grid) {

       if (grid.length == 0 || grid[0].length == 0) {

           return 0;

       }

       int rows = grid.length;

       int cols = grid[0].length;

       int count = 0;

       for (int i = 0; i < rows; ++i) {

           for (int j = 0; j < cols; ++j) {

               if (grid[i][j] == '1') {

                   ++count;

                   dfs(grid, i, j, rows, cols);

               }

           }

       }

       return count;

   }

}

Solution 2 Union Find

 



--

 



--

 



--

 



--

 



--

 



--

 



--

 



--

 



--

 



--

 



--

 



--

 



--

 



--

 



--

 



--

 



--

 



--

 





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值