编程合集: https://www.cnblogs.com/jssj/p/12002760.html

前言:不仅仅要实现,更要提升性能,精益求精,用尽量少的时间复杂度和空间复杂度解决问题。

【程序48】
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标

import java.util.HashMap;
import java.util.Map; /**
* 【程序48】
* 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标
*/
public class Subject48 {
public static void main(String[] args) {
int[] nums = new int[]{1,4,5,6,7,9,76,43,22,11};
int target = 11;
int[] result = twoSum(nums,target);
for (int i = 0; i < result.length; i++) {
System.out.println(result[i]);
}
} /**
* 获取满足条件的数组下标
* @param nums
* @param target
*/
private static int[] twoSum(int[] nums, int target) {
int[] temp = new int[2];
Map<Integer,Integer> map = new HashMap<>();
//遍历查找
for(int i = 0; i < nums.length; i++){
int a = nums[i];
//判断键值是否存在
if(map.containsKey(target - a)){
temp[0] = map.get(target - a);
temp[1] = i;
return temp;
}else {//如果找不到则存进去
map.put(nums[i], i);
}
}
return null;
}
}

时间复杂度为 O(n)。

运行结果:

【程序49】
给出两个非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0开头。

public class ListNode {
int val;
ListNode next;
ListNode(){ }
ListNode(int x) { val = x; }
}
/**
* 【程序49】
* 给出两个非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。
* 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
* 您可以假设除了数字 0 之外,这两个数都不会以 0开头。
*
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
}
*/
public class Subject49 {
public static void main(String[] args) {
ListNode l1 = new ListNode(2);
ListNode l12 = new ListNode(4);
ListNode l13 = new ListNode(3);
l1.next = l12;
l12.next = l13; ListNode l2 = new ListNode(5);
ListNode l21 = new ListNode(6);
ListNode l22 = new ListNode(4);
l2.next = l21;
l21.next = l22; ListNode listNode = addTwoNumbers(l1,l2);
StringBuilder stringBuilder = null;
while(listNode !=null){ //指向位置是否为空
if(stringBuilder == null){
stringBuilder = new StringBuilder();
stringBuilder.append(listNode.val);
}else{
stringBuilder.append(" -> "+ listNode.val);
}
listNode = listNode.next; // 指向下一个节点
}
System.out.println(stringBuilder.toString());
} /**
* 链表输出和
* @param l1
* @param l2
* @return
*/
public static ListNode addTwoNumbers(ListNode l1, ListNode l2){
int carry = 0; //进位
ListNode newListNode = new ListNode(0);
ListNode tmpListNode ;
tmpListNode = newListNode;
while(true){
ListNode listNode = new ListNode(0);
int tmp = l1.val + l2.val + carry;
if(tmp < 10){
listNode.val = tmp;
carry = 0;
}else{
listNode.val = tmp%10;
carry = 1;
}
tmpListNode.next = listNode;
tmpListNode = listNode;
if(l1.next ==null && l2.next == null &&carry == 0){
break;
}
if(l1.next != null){
l1 = l1.next;
}else{
l1 = new ListNode(0);
}
if( l2.next != null){
l2 = l2.next;
}else{
l2 = new ListNode(0);
}
}
return newListNode.next;
}
}

时间复杂度:O(\max(m, n))

运行结果:

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

import java.util.ArrayList;
import java.util.List; /**
* 给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
*/
public class Subject50 {
public static void main(String[] args) {
String Str = "aabcdfffwwesdwhjkl";
int count = lengthOfLongestSubstring(Str);
System.out.println(count);
} /**
* 获取字符最大长度
* @param s
* @return
*/
public static int lengthOfLongestSubstring(String s) {
char[] arr = s.toCharArray();
List<Character> list = new ArrayList<>();
int maxCount = 0;
int count;
for (int i = 0; i < arr.length; i++) {
if(list.contains(arr[i])){
count = list.size();
if(count> maxCount){
maxCount = count;
}
for (int j = 0; j < list.size(); j++) {
if(list.get(j) != arr[i]){
list.remove(j);
j--;
}else{
list.remove(j);
break;
}
}
list.add(arr[i]);
}else{
list.add(arr[i]);
}
}
if(list.size() > maxCount){
return list.size();
}else{
return maxCount;
}
}
}

时间复杂度:O(n)

运行结果:

【程序51】
给定两个大小为 m 和 n 的有序数组nums1 和nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为O(log(m + n))。
你可以假设nums1和nums2不会同时为空

/**
* 给定两个大小为 m 和 n 的有序数组nums1 和nums2。
* 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为O(log(m + n))。
* 你可以假设nums1和nums2不会同时为空
*/
public class Subject51 {
public static void main(String[] args) {
int[] nums1 = new int[]{1,2,3};
int[] nums2 = new int[]{1,2};
double arr = findMedianSortedArrays(nums1,nums2);
System.out.println(arr);
} public static int PartSort(int arr[], int low, int high) {
int data = arr[low];
/**一次遍历的方法:插空法 定义一个data将arr[low]存起来,并把这个位置挖空*/
while (low < high) {
while (low < high && arr[high] >= data) {
high--;
}
arr[low] = arr[high];
/**从high,也就是后面往前遍历 找到比键值小的数据 插入到前面留下的空中 high位再次留下空来*/
while (low < high && arr[low] <= data) {
low++;
}
arr[high] = arr[low];
}
arr[low] = data;
/**循环退出后 low和high重合 将将键值赋给第low,并将low返回*/
return low;
} /**
* 快速排序法
* @param arr
* @param low
* @param high
*/
public static void quickSort(int arr[], int low, int high) {
if(low<high) {
//防止发生栈溢出异常
int index = PartSort(arr, low, high);
quickSort(arr, low, index - 1);
quickSort(arr, index + 1, high);
}
} /**
* 寻找中位数
* @param nums1
* @param nums2
* @return
*/
public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
int a = nums1.length;
int b = nums2.length;
int[] arr = new int[a+b];
double result = 0.0;
if(a >= 2 && b >=2 ){
if(nums1[0] <= nums1[1] && nums2[0] <= nums2[1] ){
if(nums1[0] >= nums2[0]){
for (int i = 0; i < b; i++) {
arr[i] = nums2[i];
}
for (int i = 0; i < a; i++) {
arr[i+b] = nums1[i];
}
}else{
for (int i = 0; i < a; i++) {
arr[i] = nums1[i];
}
for (int i = 0; i < b; i++) {
arr[i+a] = nums2[i];
}
}
}else if(nums1[0] >= nums1[1] && nums2[0] >= nums2[1]){
if(nums1[a-1] <= nums2[b-1]){
for (int i = 0; i < a; i++) {
arr[i] = nums1[a-i-1];
}
for (int i = 0; i < b; i++) {
arr[i+a] = nums2[b-i-1];
}
}else{
for (int i = 0; i < b; i++) {
arr[i] = nums1[b-i-1];
}
for (int i = 0; i < a; i++) {
arr[i+b] = nums2[a-i-1];
}
}
}else if(nums1[0] <= nums1[1] && nums2[0] >= nums2[1]){
if(nums1[0] <= nums2[b-1]){
for (int i = 0; i < a; i++) {
arr[i] = nums1[i];
}
for (int i = 0; i < b; i++) {
arr[i+a] = nums2[b-i-1];
}
}else{
for (int i = 0; i < b; i++) {
arr[i] = nums2[i];
}
for (int i = 0; i < a; i++) {
arr[i+b] = nums1[a-1-i];
}
}
}else if(nums1[0] >= nums1[1] && nums2[0] <= nums2[1]){
if(nums1[a-1] <= nums2[0]){
for (int i = 0; i < a; i++) {
arr[i] = nums1[a-1-i];
}
for (int i = 0; i < b; i++) {
arr[i+a] = nums2[i];
}
}else{
for (int i = 0; i < b; i++) {
arr[i] = nums2[i];
}
for (int i = 0; i < a; i++) {
arr[i+b] = nums1[a-1-i];
}
}
}
}else{
for (int i = 0; i < a; i++) {
arr[i] = nums1[i];
}
for (int i = 0; i < b; i++) {
arr[i+a] = nums2[i];
}
}
int right = arr.length-1;
int left = 0; quickSort(arr,left,right); int tmp = arr.length;
if(tmp % 2 == 0){
result = (arr[tmp/2] + arr[tmp/2 - 1]) / 2.0;
}else{
result = arr[tmp/2];
}
return result;
}
}

时间复杂度:O(log(min(m,n)))

运行结果:

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

/**
* 【程序52】
* 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
*/
public class Subject52 {
public static void main(String[] args) {
String str = "sdffttrrgfddfh";
String result= longestPalindrome(str);
System.out.println(result);
result = longestPalindrome1(str);
System.out.println(result);
} /**
* Manacher算法
* @param str
* @return
*/
private static String longestPalindrome1(String str) {
char[] cStr = str.toCharArray();
//插入特殊符号
StringBuffer sBuffer = new StringBuffer();
sBuffer.append("#");
for (int i = 0; i < cStr.length; i++) {
sBuffer.append(cStr[i]);
sBuffer.append("#");
}
int id =0; //回文的中心。
int max = 0; //回文最大长度。
//辅助数组
int[] p= new int[sBuffer.length()];
for (int i = 1; i < sBuffer.length(); i++) { if (i<max) {
p[i] = Math.min(p[2*id-i], max-i);
}else {
p[i]= 1;
}
//判断中心两边是否回文,是则++;
while (i-p[i]>=0&&i+p[i]<sBuffer.length()&&sBuffer.charAt(i-p[i])==sBuffer.charAt(i+p[i])) {
p[i]++;
}
if (i+p[i]>max) {
max = i+p[i];
id = i;
}
}
int maxl = 0 ;
int maxid =0 ;
for(int i =0 ;i<p.length;i++){
if(maxl<p[i]){
maxl=p[i];
maxid = i;
}
}
//半径包括id本身。id到第一个元素,id-r+1
int r = maxl-1;
int start = maxid-r+1;
int end = maxid+maxl-1;
StringBuffer out = new StringBuffer();
for (int i = start; i < end; i++) {
if (sBuffer.charAt(i)!='#') {
out.append(sBuffer.charAt(i));
}
}
return out.toString();
} /**
* 获取最长回文数
* @param s
* @return
*/
public static String longestPalindrome(String s) {
String result = "";
char[] arr = s.toCharArray();
for(int i = 0 ; i < arr.length; i++){
for (int j = 0; j <= i; j++) {
//判断是否回文。
result = palindromeStr(s,arr,i,j);
if(!"".equals( result) ){
return result;
}
}
}
return result;
} /**
* 判断字符串是否是回文字符串
* @param s
* @param arr
* @param i
* @param j
* @return
*/
private static String palindromeStr(String s,char[] arr, int i, int j) {
String result = "";
int start = j;
int end = arr.length-(i-j)-1;
while(start <= end){
if(arr[start] == arr[end]){
if(start+1 >= end){
result = s.substring(j,arr.length-(i-j));
return result;
}
start++;
end--;
}else{
break;
}
}
return result;
}
}

时间复杂度:O(n)

运行结果:

【程序53】
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 |\| 字形排列

import java.util.ArrayList;
import java.util.List; /**
* 【程序53】
* 将一个给定字符串根据给定的行数,以从上往下、从左到右进行 字形排列
*
* 输入: s = "LEETCODEISHIRING", numRows =4
* 输出:"LDREOEIIECIHNTSG"
* 解释:
* L D R
* E O E I I
* E C I H N
* T S G
*/
public class Subject53 {
public static void main(String[] args) {
String s = "LEETCODEISHIRING";
int numRows = 4;
String str = convert(s,numRows);
System.out.println(str);
} /**
*
* @param s
* @param numRows
* @return
*/
public static String convert(String s,int numRows){
if(numRows <= 1){
return s;
}
char[] arr = s.toCharArray();
//创建numRows个字符串
List<StringBuilder> list = new ArrayList<>();
for (int i = 0; i < numRows; i++) {
StringBuilder stringBuffer = new StringBuilder();
list.add(stringBuffer);
} int flag = 0; // 0表示顺序,1表示逆序。
int size = 1; //在第几行
for (int i = 0; i < arr.length; i++) {
if(size == numRows){
flag = 1;
}
if(size == 1){
flag = 0;
}
list.get(size-1).append(arr[i]); if(flag == 0){
size++;
}
if(flag == 1){
size--;
}
} StringBuilder newStringBuffer = new StringBuilder(); for (int i = 0; i < numRows; i++) {
newStringBuffer.append(list.get(i));
}
return newStringBuffer.toString();
}
}

时间复杂度:O(n)

运行结果:

【程序54】
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。

/**
* 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
*/
public class Subject54 {
public static void main(String[] args) {
int x= 2147483641;
int result = reverse(x);
System.out.println(result);
result = reverse2(x);
System.out.println(result);
} /**
* 反转
* @param x
* @return
*/
public static int reverse(int x){
String str = x+"";
char[] arr = str.toCharArray();
StringBuilder stringBuilder = new StringBuilder();
if(arr[0] == '-'){
stringBuilder.append('-');
for (int i = arr.length-1; i >= 1; i--) {
stringBuilder.append(arr[i]);
}
}else{
for (int i = arr.length-1; i >= 0; i--) {
stringBuilder.append(arr[i]);
}
} int result = 0;
try {
result = Integer.parseInt(stringBuilder.toString());
}catch (Exception e){
result = 0;
}
return result;
} /**
* 反转2
* @param x
* @return
*/
public static int reverse2(int x){
int rev = 0;
while (x != 0) {
int pop = x % 10;
x /= 10;
if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0;
if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0;
rev = rev * 10 + pop;
}
return rev;
}
}

时间复杂度:O(\log(x))

运行结果:

【程序55】
请你来实现一个 atoi 函数,使其能将字符串转换成整数。

/**
* 【程序55】
* 请你来实现一个 atoi 函数,使其能将字符串转换成整数。
*/
public class Subject55 {
public static void main(String[] args) {
String str = " -2147483649ww";
int i= myAtoi(str);
System.out.println(i);
}
public static int myAtoi(String str) {
int radix = 10;
if (str == null) {
return 0;
}else{
str = str.trim();
} int result = 0;
boolean negative = false;
int i = 0, len = str.length();
int limit = -Integer.MAX_VALUE;
int multmin;
int digit; if (len > 0) {
char firstChar = str.charAt(0);
if (firstChar < '0') { // Possible leading "+" or "-"
if (firstChar == '-') {
negative = true;
limit = Integer.MIN_VALUE;
} else if (firstChar != '+')
return 0; if (len == 1) // Cannot have lone "+" or "-"
return 0;
i++;
}
multmin = limit / radix;
while (i < len) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit(str.charAt(i++),radix);
if (digit < 0) {
break;
}
if (result < multmin) {
result = limit;
break;
}
result *= radix;
if (result < limit + digit) {
result = limit;
break;
}
result -= digit;
}
} else {
return 0;
}
return negative ? result : -result;
}
}

时间复杂度:O(n)

运行结果:

【程序56】
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
考虑负数。

/**
* 【程序56】
* 判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
*/
public class Subject56 {
public static void main(String[] args) {
int x = 1;
boolean flag = isPalindrome(x);
System.out.println(flag);
} /**
* 判断x是否是回文数
* @param x
* @return
*/
public static boolean isPalindrome(int x) {
if(x < 0){
return false;
}
if(x < 10){
return true;
}
int newi = 0;
int num = x;
while(true){
if(newi>0){
newi = newi*10;
}
int i = num%10 ;
newi = newi+i;
num = num/10;
if(num <= 9){
newi = newi*10+num;
break;
}
}
if(newi == x){
return true;
}else{
return false;
}
}
}

时间复杂度:O(\log_{10}(n))

运行结果:

【程序57】
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。
'.' 匹配任意单个字符
'*' 匹配零个或多个前面的那一个元素

import java.util.HashMap;
import java.util.Map; /**
* 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。
* '.' 匹配任意单个字符
* '*' 匹配零个或多个前面的那一个元素
*/
public class Subject57 {
public static void main(String[] args) {
Map<String ,String> map = new HashMap<>();
map.put("dddc","d*dddc"); //true;
for (Map.Entry<String,String> entry :map.entrySet()){
System.out.println(entry.getKey()+" : "+entry.getValue());
System.out.println(isMatch(entry.getKey(),entry.getValue()));
}
} /**
* 实现匹配规则
* @param s
* @param p
* @return
*/
public static boolean isMatch(String s, String p) {
if (p.isEmpty()) return s.isEmpty();
boolean first_match = (!s.isEmpty() &&
(p.charAt(0) == s.charAt(0) || p.charAt(0) == '.')); if (p.length() >= 2 && p.charAt(1) == '*'){
return (isMatch(s, p.substring(2)) ||
(first_match && isMatch(s.substring(1), p)));
} else {
return first_match && isMatch(s.substring(1), p.substring(1));
}
}
}

时间复杂度:O(TP)

运行结果:

以上题目均来自:https://leetcode-cn.com/ ,如果你热爱编码,热爱算法,该网站一定适合你。

《Java练习题》进阶练习题(一)的更多相关文章

  1. 6、50道JAVA基础编程练习题跟答案

    50道JAVA基础编程练习题 [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 程序分析 ...

  2. 50道JAVA基础编程练习题

    50道JAVA基础编程练习题 [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子对数为多少? 程序分析 ...

  3. 50道JAVA基础编程练习题 - 题目

    50道JAVA基础编程练习题[1]题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? [2]题目:判断 ...

  4. 【视频+图文】Java基础经典练习题(一)输出2-100之间的素数,及素数个数

    目录 第一题:判断2-100之间有多少个素数,并输出所有素数. 1.视频讲解: 2.思路分析: 代码讲解:以i=4为例 4.为大家准备了彩蛋: 能解决题目的代码并不是一次就可以写好的 我们需要根据我们 ...

  5. 【视频+图文】Java经典基础练习题(三):输入3个整数,并将其由小到大输出

    目录 一.视频讲解 二.思路分析 总结: 三.代码+详解+结果 四.彩蛋 能解决题目的代码并不是一次就可以写好的 我们需要根据我们的思路写出后通过debug模式找到不足再进行更改 多次测试后才可得到能 ...

  6. 3.Java异常进阶

    3.JAVA异常进阶 1.Run函数中抛出的异常 1.run函数不会抛出异常 2.run函数的异常会交给UncaughtExceptionhandler处理 3.默认的UncaughtExceptio ...

  7. Java字符串进阶

    Java字符串进阶 前言 最常用的对字符串操作的类有三个,分别是String,StringBuilder,StringBuffer,下面将会详细的说说这三个类...... String String类 ...

  8. 总结:Java 集合进阶精讲2-ArrayList

    知识点:Java 集合框架图 总结:Java 集合进阶精讲1 总结:Java 集合进阶精讲2-ArrayList 初探: ArrayList底层结构是数组,是List接口的 可变数组的实现,所以会占用 ...

  9. 总结:Java 集合进阶精讲1

    知识点:Java 集合框架图 总结:Java 集合进阶精讲1 总结:Java 集合进阶精讲2-ArrayList 集合进阶1---为集合指定初始容量 集合在Java编程中使用非常广泛,当容器的量变得非 ...

  10. 第二十八节:Java基础-进阶继承,抽象类,接口

    前言 Java基础-进阶继承,抽象类,接口 进阶继承 class Stu { int age = 1; } class Stuo extends Stu { int agee = 2; } class ...

随机推荐

  1. PHP 核心特性之匿名函数

    提出 在匿名函数出现之前,所有的函数都需要先命名才能使用 1 2 3 4 5 function increment($value) {     return $value + 1; } array_m ...

  2. iOS 抽奖轮盘效果实现思路

    临近活动,相信不少app都会加一个新的需求——抽奖不多废话,先上GIF效果图 作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要这是一个我的iOS交流群:937194184,不管你是小白还是大牛欢 ...

  3. 新闻实时分析系统 Spark2.X环境准备、编译部署及运行

    1.Spark概述 Spark 是一个用来实现快速而通用的集群计算的平台. 在速度方面, Spark 扩展了广泛使用的 MapReduce 计算模型,而且高效地支持更多计算模式,包括交互式查询和流处理 ...

  4. web网站常用功能测试点总结

    目录 一.输入框 二.搜索功能 三.添加.修改功能 四.删除功能 五.注册.登录模块 六.上传图片测试 七.查询结果列表 八.返回键检查 九.回车键检查 十.刷新键检查 十一.直接URL链接检查 十二 ...

  5. 【Android - 进阶】之Dialog分类及使用

    1.确定取消对话框 代码: // 使用AlertDialog.Builder初始化对话框 AlertDialog.Builder builder0 = new AlertDialog.Builder( ...

  6. javascript获取当前时间CurentTime

    function CurentTime(){ var now = new Date(); var year = now.getFullYear(); //年 var month = now.getMo ...

  7. matlab实现PSNR

    目录 1.PSNR原理 2.PSNR的matlab实现代码 3.针对彩色图像的PSNR的matlab代码 @ 1.PSNR原理 PSNR,峰值信噪比,通常用来评价一幅图像压缩后和原图像相比质量的好坏, ...

  8. 【nodejs原理&源码杂记(8)】Timer模块与基于二叉堆的定时器

    [摘要] timers模块部分源码和定时器原理 示例代码托管在:http://www.github.com/dashnowords/blogs 一.概述 Timer模块相关的逻辑较为复杂,不仅包含Ja ...

  9. 失去循环标签的Python,我这样实现跳出外层循环

    不完美的Python 自从各类Python大火,感觉天上地下哪儿都有Python的一席之地,Python功夫好啊-但python有些细节上缺少其他语言的便利.今天我们就来举几个例子. 跳出外层循环 大 ...

  10. 转:MySQL下载安装、配置与使用(win7x64)

    1 第一大步:下载. a.俗话说:“巧妇难为无米之炊”嘛!我这里用的是 ZIP Archive 版的,win7 64位的机器支持这个,所以我建议都用这个.因为这个简单嘛,而且还干净. 地址见图 拉倒最 ...