Leetcode數據結構與算法(四)

[0049]二進制中1的個數

請實現一個函數,輸入一個整數,輸出該數二進制表示中 1 的個數。例如,把 9 表示成二進制是 1001,有 2 位是 1。因此,如果輸入 9,則該函數輸出 2。

示例 1:

輸入:00000000000000000000000000001011
輸出:3
解釋:輸入的二進制串 00000000000000000000000000001011 中,共有三位爲 '1'。

示例 2:

輸入:00000000000000000000000010000000
輸出:1
解釋:輸入的二進制串 00000000000000000000000010000000 中,共有一位爲 '1'。

示例 3:

輸入:11111111111111111111111111111101
輸出:31
解釋:輸入的二進制串 11111111111111111111111111111101 中,共有 31 位爲 '1'。

方法一:循環和位移動

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int bits = 0;
        int mask = 1;
        for (int i = 0; i < 32; i++) {
            if( (n & mask) != 0) bits++;
            mask <<= 1;
        }
        return bits;
    }
}

方法 2:位操作的小技巧

public class Solution {
    // you need to treat n as an unsigned value
    public int hammingWeight(int n) {
        int sum = 0;
        while (n != 0) {
            sum++;
            n &= (n - 1);
        }
        return sum;
    }
}

[0050]高度檢查器

學校在拍年度紀念照時,一般要求學生按照 非遞減 的高度順序排列。

請你返回能讓所有學生以 非遞減 高度排列的最小必要移動人數。

注意,當一組學生被選中時,他們之間可以以任何可能的方式重新排序,而未被選中的學生應該保持不動。

示例:

輸入:heights = [1,1,4,2,1,3]
輸出:3 
解釋:
當前數組:[1,1,4,2,1,3]
目標數組:[1,1,1,2,3,4]
在下標 2 處(從 0 開始計數)出現 4 vs 1 ,所以我們必須移動這名學生。
在下標 4 處(從 0 開始計數)出現 1 vs 3 ,所以我們必須移動這名學生。
在下標 5 處(從 0 開始計數)出現 3 vs 4 ,所以我們必須移動這名學生。

示例 2:

輸入:heights = [5,1,2,3,4]
輸出:5

示例 3:

輸入:heights = [1,2,3,4,5]
輸出:0

提示:

1 <= heights.length <= 100
1 <= heights[i] <= 100

實際上是:對比排序後和排序前位置不一樣的個數

方法一:計數算法

class Solution {
    public int heightChecker(int[] heights) {
       // 值的範圍是1 <= heights[i] <= 100,因此需要1,2,3,...,99,100,共101個桶
        int[] arr = new int[101];
        // 遍歷數組heights,計算每個桶中有多少個元素,也就是數組heights中有多少個1,多少個2,。。。,多少個100
        // 將這101個桶中的元素,一個一個桶地取出來,元素就是有序的
        for (int height : heights) {
            arr[height]++;
        }

        int count = 0;
        for (int i = 1, j = 0; i < arr.length; i++) {
            // arr[i],i就是桶中存放的元素的值,arr[i]是元素的個數
            // arr[i]-- 就是每次取出一個,一直取到沒有元素,成爲空桶
            while (arr[i]-- > 0) {
                // 從桶中取出元素時,元素的排列順序就是非遞減的,然後與heights中的元素比較,如果不同,計算器就加1
                if (heights[j++] != i) count++;
            }
        }
        return count;
    }
}

時間複雜度:O(n)

空間複雜度:O(1)

方法二:排序

class Solution {
    public int heightChecker(int[] heights) {
        int[] temp = heights.clone();

        Arrays.sort(temp);
        int cnt=0;
        for (int i = 0; i <heights.length ; i++) {
            if (temp[i]!=heights[i]) cnt++;
        }
        return cnt;
    }
}

時間複雜度:O(NlogN)

空間複雜度:O(N)

[0051]自除數

自除數 是指可以被它包含的每一位數除盡的數。

例如,128 是一個自除數,因爲 128 % 1 == 0,128 % 2 == 0,128 % 8 == 0。

還有,自除數不允許包含 0 。

給定上邊界和下邊界數字,輸出一個列表,列表的元素是邊界(含邊界)內所有的自除數。

示例 1:

輸入: 
上邊界left = 1, 下邊界right = 22
輸出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 15, 22]

注意:

每個輸入參數的邊界滿足 1 <= left <= right <= 10000。

方法一:

class Solution {
    public List<Integer> selfDividingNumbers(int left, int right) {
        List<Integer> ans = new ArrayList();
        for (int n = left; n <= right; ++n) {
            if (selfDividing(n)) ans.add(n);
        }
        return ans;
    }
    public boolean selfDividing(int n) {
        for (char c: String.valueOf(n).toCharArray()) {
            if (c == '0' || (n % (c - '0') > 0))
                return false;
        }
        return true;
    }
    /*
    Alternate implementation of selfDividing:
    public boolean selfDividing(int n) {
        int x = n;
        while (x > 0) {
            int d = x % 10;
            x /= 10;
            if (d == 0 || (n % d) > 0) return false;
        }
        return true;
    */
}

[0052]二叉搜索樹中的搜索

給定二叉搜索樹(BST)的根節點和一個值。 你需要在BST中找到節點值等於給定值的節點。 返回以該節點爲根的子樹。 如果節點不存在,則返回 NULL。

例如,

給定二叉搜索樹:

    4
   / \
  2   7
 / \
1   3

和值: 2
你應該返回如下子樹:

  2     
 / \   
1   3

在上述示例中,如果要找的值是 5,但因爲沒有節點值爲 5,我們應該返回 NULL。

方法一:遞歸

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
        if (root == null || val == root.val) return root;
        return val < root.val ? searchBST(root.left, val) : searchBST(root.right, val);
    }
}

時間複雜度:O(H),其中 H 是樹高。平均時間複雜度爲 O(logN),最壞時間複雜度爲 O(N)。

空間複雜度:O(H),遞歸棧的深度爲H。平均情況下深度爲 O(logN),最壞情況下深度爲 O(N)。

方法二:迭代


時間複雜度:O(H),其中 H 是樹高。平均時間複雜度爲 O(logN),最壞時間複雜度爲 O(N)。

空間複雜度:O(1),恆定的額外空間。

[0053]N叉樹的後序遍歷

給定一個 N 叉樹,返回其節點值的後序遍歷。

例如,給定一個 3叉樹 :

img

返回其後序遍歷: [5,6,3,2,4,1].

說明: 遞歸法很簡單,你可以使用迭代法完成此題嗎?

方法一:

/*
// Definition for a Node.
class Node {
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, List<Node> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
    List<Integer> res = new ArrayList<Integer>();
    public List<Integer> postorder(Node root) {
        dfs(root);
        return res;
    }
    public void dfs(Node root) {
        if(root == null)    return;
        for(Node child : root.children)
            dfs(child);
        res.add(root.val);
    }
}

方法二:

class Solution {
    public List<Integer> postorder(Node root) {
        LinkedList<Node> stack = new LinkedList<>();
        LinkedList<Integer> output = new LinkedList<>();
        if (root == null) {
            return output;
        }

      stack.add(root);
      while (!stack.isEmpty()) {
          Node node = stack.pollLast();
          output.addFirst(node.val);	//在第一個位置add
          for (Node item : node.children) {
              if (item != null) {
                  stack.add(item);    
              } 
          }
      }
      return output;
    }
}

[0054]二叉樹的最大深度

給定一個二叉樹,找出其最大深度。

二叉樹的深度爲根節點到最遠葉子節點的最長路徑上的節點數。

說明: 葉子節點是指沒有子節點的節點。

示例:
給定二叉樹 [3,9,20,null,null,15,7],

		3
   / \
  9  20
    /  \
   15   7

返回它的最大深度 3 。

方法一:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        } else {
            int left_height = maxDepth(root.left);
            int right_height = maxDepth(root.right);
            return Math.max(left_height, right_height) + 1;
        }
    }
}

方法二:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        // bfs
        Queue<TreeNode> queue = new LinkedList<>();
        int depth = 0;
        queue.add(root);
        while (!queue.isEmpty()) {
            int size = queue.size();
            depth++;
            for (int i = 0; i < size; i++) {
                TreeNode temp = queue.poll();
                if (temp.left != null) {
                    queue.add(temp.left);
                }
                if (temp.right != null) {
                    queue.add(temp.right);
                }
            }
        }
        return depth;
    }
}

[0055]N叉樹的前序遍歷

給定一個 N 叉樹,返回其節點值的前序遍歷

例如,給定一個 3叉樹 :

img

返回其前序遍歷: [1,3,5,6,2,4]

方法一:

/*
// Definition for a Node.
class Node {
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, List<Node> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
    List<Integer> res = new ArrayList<Integer>();
    public List<Integer> preorder(Node root) {
        dfs(root);
        return res;
    }

    public void dfs(Node root) {
        if(root == null)    return;
        res.add(root.val);
        for(Node child : root.children)
            dfs(child);
    }
}

方法二:

class Solution {
    public List<Integer> preorder(Node root) {
        LinkedList<Node> stack = new LinkedList<>();
        LinkedList<Integer> output = new LinkedList<>();
        if (root == null) {
            return output;
        }

        stack.add(root);
        while (!stack.isEmpty()) {
            Node node = stack.pollLast();
            output.add(node.val);
            Collections.reverse(node.children);
            for (Node item : node.children) {
                stack.add(item);
            }
        }
        return output;
    }
}

[0056] 判定字符是否唯一

實現一個算法,確定一個字符串 s 的所有字符是否全都不同。

示例 1:

輸入: s = "leetcode"
輸出: false 

示例 2:

輸入: s = "abc"
輸出: true

限制:

0 <= len(s) <= 100
如果你不使用額外的數據結構,會很加分。

方法一:

class Solution {
    public boolean isUnique(String astr) {
        Set set = new HashSet();
        for (int i = 0; i <astr.length() ; i++) {
            set.add(astr.charAt(i));
            if(set.size() < i +1 ) return false;
        }
        return set.size() == astr.length(); 
    }
}

方法二:

class Solution {
    public boolean isUnique(String astr) {
        long low64 = 0;
        long high64 = 0;

        for (char c : astr.toCharArray()) {
            if (c >= 64) {
                long bitIndex = 1L << c - 64;
                if ((high64 & bitIndex) != 0) {
                    return false;
                }

                high64 |= bitIndex;
            } else {
                long bitIndex = 1L << c;
                if ((low64 & bitIndex) != 0) {
                    return false;
                }

                low64 |= bitIndex;
            }

        }

        return true;
    }
}

[0057]二叉搜索樹的第k大節點

給定一棵二叉搜索樹,請找出其中第k大的節點。

示例 1:

輸入: root = [3,1,4,null,2], k = 1
   3
  / \
 1   4
  \
   2
輸出: 4

示例 2:

輸入: root = [5,3,6,2,4,null,null,1], k = 3
       5
      / \
     3   6
    / \
   2   4
  /
 1
輸出: 4

限制:

1 ≤ k ≤ 二叉搜索樹元素個數

方法一:遞歸

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    
    int res, k;
    public int kthLargest(TreeNode root, int k) {
        this.k = k;
        dfs(root);
        return res;
    }
    void dfs(TreeNode root) {
        if(root == null) return;
        dfs(root.right);
        if(k == 0) return;
        if(--k == 0) res = root.val;
        dfs(root.left);
    }
}

方法二:迭代

class Solution {
    public int kthLargest(TreeNode root, int k) {
        int count = 1;
        Stack<TreeNode> stack = new Stack<>();
        while (Objects.nonNull(root) || !stack.empty()) {
            while (Objects.nonNull(root)) {
                stack.push(root);
                root = root.right;
            }
            TreeNode pop = stack.pop();
            if (count == k) {
                return pop.val;
            }
            count++;
            root = pop.left;
        }
        return 0;
    }
}
class Solution {
    public int kthLargest(TreeNode root, int k) {
        List<Integer> result = new LinkedList<>();
        Stack<TreeNode> stack = new Stack<>();
        TreeNode cur = root;
        while (cur != null || !stack.isEmpty()) {
            while (cur != null) {
                stack.push(cur);
                cur = cur.right;
            }
            cur = stack.pop();
            result.add(cur.val);
            if(result.size() == k){
                return cur.val;
            }
            cur = cur.left;
        }
        return result.get(k - 1);
    }
}

[0058]用兩個棧實現隊列

用兩個棧實現一個隊列。隊列的聲明如下,請實現它的兩個函數 appendTail 和 deleteHead ,分別完成在隊列尾部插入整數和在隊列頭部刪除整數的功能。(若隊列中沒有元素,deleteHead 操作返回 -1 )

示例 1:

輸入:
["CQueue","appendTail","deleteHead","deleteHead"]
[[],[3],[],[]]
輸出:[null,null,3,-1]

示例 2:

輸入:
["CQueue","deleteHead","appendTail","appendTail","deleteHead","deleteHead"]
[[],[],[5],[2],[],[]]
輸出:[null,-1,null,null,5,2]

提示:

1 <= values <= 10000
最多會對 appendTail、deleteHead 進行 10000 次調用

方法一:

class CQueue {
    Stack<Integer> stack1;
    Stack<Integer> stack2;
    int size;

    public CQueue() {
        stack1 = new Stack<Integer>();
        stack2 = new Stack<Integer>();
        size = 0;
    }
    
    public void appendTail(int value) {
        while (!stack1.isEmpty()) {
            stack2.push(stack1.pop());
        }
        stack1.push(value);
        while (!stack2.isEmpty()) {
            stack1.push(stack2.pop());
        }
        size++;
    }
    
    public int deleteHead() {
        if (size == 0) {
            return -1;
        }
        size--;
        return stack1.pop();
    }
}

/**
 * Your CQueue object will be instantiated and called as such:
 * CQueue obj = new CQueue();
 * obj.appendTail(value);
 * int param_2 = obj.deleteHead();
 */

[0059]兩個數組間的距離值

給你兩個整數數組 arr1 , arr2 和一個整數 d ,請你返回兩個數組之間的 距離值 。

「距離值」 定義爲符合此描述的元素數目:

對於元素 arr1[i] ,不存在任何元素 arr2[j] 滿足 |arr1[i]-arr2[j]| <= d 。

示例 1:

輸入:arr1 = [4,5,8], arr2 = [10,9,1,8], d = 2
輸出:2
解釋:
對於 arr1[0]=4 我們有:
|4-10|=6 > d=2 
|4-9|=5 > d=2 
|4-1|=3 > d=2 
|4-8|=4 > d=2 
對於 arr1[1]=5 我們有:
|5-10|=5 > d=2 
|5-9|=4 > d=2 
|5-1|=4 > d=2 
|5-8|=3 > d=2
對於 arr1[2]=8 我們有:
|8-10|=2 <= d=2
|8-9|=1 <= d=2
|8-1|=7 > d=2
|8-8|=0 <= d=2

示例 2:

輸入:arr1 = [1,4,2,3], arr2 = [-4,-3,6,10,20,30], d = 3
輸出:2

示例 3:

輸入:arr1 = [2,1,100,3], arr2 = [-5,-2,10,-3,7], d = 6
輸出:1

提示:

1 <= arr1.length, arr2.length <= 500
-10^3 <= arr1[i], arr2[j] <= 10^3
0 <= d <= 100

方法一:暴力

class Solution {
     private int getCount(int num1, int[] arr2, int d) {
        for (int num2 : arr2) {
            if (Math.abs(num1 - num2) <= d) {
                return 0;
            }
        }
        return 1;
    }

    public int findTheDistanceValue(int[] arr1, int[] arr2, int d) {
        int ans = 0;
        for (int num1 : arr1) {
            ans += getCount(num1, arr2, d);
        }
        return ans;
    }
}

其他題解:

https://leetcode-cn.com/problems/find-the-distance-value-between-two-arrays/solution/1385java-liang-chong-fang-fa-er-fen-shuang-zhi-zhe/

[0060]增減字符串匹配

給定只含 “I”(增大)或 “D”(減小)的字符串 S ,令 N = S.length。

返回 [0, 1, …, N] 的任意排列 A 使得對於所有 i = 0, …, N-1,都有:

如果 S[i] == "I",那麼 A[i] < A[i+1]
如果 S[i] == "D",那麼 A[i] > A[i+1]

示例 1:

輸出:"IDID"
輸出:[0,4,1,3,2]

示例 2:

輸出:"III"
輸出:[0,1,2,3]

示例 3:

輸出:"DDI"
輸出:[3,2,0,1]

提示:

1 <= S.length <= 10000
S 只包含字符 “I” 或 “D”。

方法一:

class Solution {
    public int[] diStringMatch(String S) {
       int N = S.length();
       int start = 0;
       int end = N;
       int[] res = new int[N+1]; 
       for(int i = 0; i < N; ++i){
           if (S.charAt(i) == 'I'){
               res[i] = start++;
           }else{
               res[i] = end--;
           }
       }
       res[N] = end;
       return res;
    }
}

[0061]有序數組的平方

給定一個按非遞減順序排序的整數數組 A,返回每個數字的平方組成的新數組,要求也按非遞減順序排序。

示例 1:

輸入:[-4,-1,0,3,10]
輸出:[0,1,9,16,100]

示例 2:

輸入:[-7,-3,2,3,11]
輸出:[4,9,9,49,121]

提示:

1 <= A.length <= 10000
-10000 <= A[i] <= 10000
A 已按非遞減順序排序。

方法一:

class Solution {
    public int[] sortedSquares(int[] A) {
        int N = A.length;
        int[] ans = new int[N];
        for (int i = 0; i < N; ++i)
            ans[i] = A[i] * A[i];

        Arrays.sort(ans);
        return ans;
    }
}

方法二:雙指針

class Solution {
    public int[] sortedSquares(int[] A) {
        int N = A.length;
        int j = 0;      // j 正向讀取非負數部分
        while (j < N && A[j] < 0)
            j++;
        int i = j-1;    // i 反向讀取負數部分

        int[] ans = new int[N];
        int t = 0;

        while (i >= 0 && j < N) {
            if (A[i] * A[i] < A[j] * A[j]) {
                ans[t++] = A[i] * A[i];
                i--;
            } else {
                ans[t++] = A[j] * A[j];
                j++;
            }
        }

        while (i >= 0) {
            ans[t++] = A[i] * A[i];
            i--;
        }
        while (j < N) {
            ans[t++] = A[j] * A[j];
            j++;
        }

        return ans;
    }
}

[0062]矩陣中的幸運數

給你一個 m * n 的矩陣,矩陣中的數字 各不相同 。請你按 任意 順序返回矩陣中的所有幸運數。

幸運數是指矩陣中滿足同時下列兩個條件的元素:

在同一行的所有元素中最小
在同一列的所有元素中最大

示例 1:

輸入:matrix = [[3,7,8],[9,11,13],[15,16,17]]
輸出:[15]
解釋:15 是唯一的幸運數,因爲它是其所在行中的最小值,也是所在列中的最大值。

示例 2:

輸入:matrix = [[1,10,4,2],[9,3,8,7],[15,16,17,12]]
輸出:[12]
解釋:12 是唯一的幸運數,因爲它是其所在行中的最小值,也是所在列中的最大值。

示例 3:

輸入:matrix = [[7,8],[1,2]]
輸出:[7]

提示:

m == mat.length
n == mat[i].length
1 <= n, m <= 50
1 <= matrix[i][j] <= 10^5
矩陣中的所有元素都是不同的

方法一:

class Solution {
    public List<Integer> luckyNumbers (int[][] matrix) {
        List<Integer> res = new ArrayList<>();
        for (int i = 0; i < matrix.length; i++) {
            int min = Integer.MAX_VALUE;
            int idx = -1;
            for (int j = 0; j < matrix[0].length; j++) {
                if (min > matrix[i][j]) {
                    idx = j;
                    min = matrix[i][j];
                }
            }
            boolean flag = true;
            for (int j = 0; j < matrix.length; j++) {
                if (min < matrix[j][idx] && j != i) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                res.add(min);
            }
        }
        return res;
    }
}

方法二:

class Solution {
    public List<Integer> luckyNumbers (int[][] matrix) {
        int m = matrix.length;
        int n = matrix[0].length;
        int[] min = new int[m];
        int[] max = new int[n];
        Arrays.fill(min, Integer.MAX_VALUE);
        Arrays.fill(max, Integer.MIN_VALUE);
        for (int i = 0; i < m; i++){
            for (int j = 0; j < n; j++){
                min[i] = Math.min(min[i], matrix[i][j]);// 第i行最小值
                max[j] = Math.max(max[j], matrix[i][j]);// 每一列最大值與當前值比較
            }
        }

        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < m; i++){
            for (int j = 0; j < n; j++){
                if (min[i] == max[j])
                    list.add(min[i]);
            }
        }

        return list;
    }
}

[0063]生成每種字符都是奇數個的字符串

給你一個整數 n,請你返回一個含 n 個字符的字符串,其中每種字符在該字符串中都恰好出現 奇數次 。

返回的字符串必須只含小寫英文字母。如果存在多個滿足題目要求的字符串,則返回其中任意一個即可。

示例 1:

輸入:n = 4
輸出:"pppz"
解釋:"pppz" 是一個滿足題目要求的字符串,因爲 'p' 出現 3 次,且 'z' 出現 1 次。當然,還有很多其他字符串也滿足題目要求,比如:"ohhh" 和 "love"。

示例 2:

輸入:n = 2
輸出:"xy"
解釋:"xy" 是一個滿足題目要求的字符串,因爲 'x' 和 'y' 各出現 1 次。當然,還有很多其他字符串也滿足題目要求,比如:"ag" 和 "ur"。

示例 3:

輸入:n = 7
輸出:"holasss"

提示:

  • 1 <= n <= 500

方法一:

class Solution {
    public String generateTheString(int n) {
        StringBuilder sb = new StringBuilder();
        if (n % 2 == 0) {
            for (int i = 0; i < n - 1; i++)
                sb.append('a');
            sb.append('b');
        } else {
            for (int i = 0; i < n; i++)
                sb.append('a');
        }
        return sb.toString();
    }
}

[0064]最近的請求次數

寫一個 RecentCounter 類來計算最近的請求。

它只有一個方法:ping(int t),其中 t 代表以毫秒爲單位的某個時間。

返回從 3000 毫秒前到現在的 ping 數。

任何處於 [t - 3000, t] 時間範圍之內的 ping 都將會被計算在內,包括當前(指 t 時刻)的 ping。

保證每次對 ping 的調用都使用比之前更大的 t 值。

示例:

輸入:inputs = ["RecentCounter","ping","ping","ping","ping"], inputs = [[],[1],[100],[3001],[3002]]
輸出:[null,1,2,3,3]

提示:

每個測試用例最多調用 10000 次 ping。
每個測試用例會使用嚴格遞增的 t 值來調用 ping。
每次調用 ping 都有 1 <= t <= 10^9。

方法一:

class RecentCounter {
    Queue<Integer> q;
    public RecentCounter() {
        q = new LinkedList();
    }

    public int ping(int t) {
        q.add(t);
        while (q.peek() < t - 3000)
            q.poll();
        return q.size();
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章