Coursera Algorithms Programming Assignment 3: Pattern Recognition (100分)

来源:http://www.cnblogs.com/evasean/archive/2017/07/27/7246793.html
-Advertisement-
Play Games

題目原文詳見http://coursera.cs.princeton.edu/algs4/assignments/collinear.html 程式的主要目的是尋找n個points中的line segment,line segment的要求就是包含不少於4個點。 作業包含三部分程式實現: 一、Poi ...


題目原文詳見http://coursera.cs.princeton.edu/algs4/assignments/collinear.html

程式的主要目的是尋找n個points中的line segment,line segment的要求就是包含不少於4個點。

作業包含三部分程式實現:

一、Point

compareTo()用來比較本節點this與其他節點that的大小:假如this節點坐標(x0, y0),that節點坐標(x1, y1),只有y0 < y1或(y0==y1 && x0<x1)的時候this < that

slopeTo()用來計算that節點到本節點this的斜率,計算方法為(y1 − y0) / (x1 − x0),特別註意的是,x0 != x1 && y0==y1時,slople為0,x0==x1 && y0!=y1時,slople應為positive infinity,x0==x1 && y0==y1時,slope應為negative infinity,

slopeOrder()用來返回比較器,這個比較器的參照點是本節點p0(x0, y0),如果兩個待比較節點分別是p1(x1, y1)和p2(x2, y2),此比較器的設計要求是當p1相對於p0的斜率大於p2相對於p0的斜率時,p1>p2。比較器主要在排序方法中使用

  1 import java.util.Comparator;
  2 import edu.princeton.cs.algs4.StdDraw;
  3 
  4 public class Point implements Comparable<Point> {
  5 
  6     private final int x; // x-coordinate of this point
  7     private final int y; // y-coordinate of this point
  8 
  9     /**
 10      * Initializes a new point.
 11      *
 12      * @param x
 13      *            the <em>x</em>-coordinate of the point
 14      * @param y
 15      *            the <em>y</em>-coordinate of the point
 16      */
 17     public Point(int x, int y) {
 18         /* DO NOT MODIFY */
 19         this.x = x;
 20         this.y = y;
 21     }
 22 
 23     /**
 24      * Draws this point to standard draw.
 25      */
 26     public void draw() {
 27         /* DO NOT MODIFY */
 28         StdDraw.point(x, y);
 29     }
 30 
 31     /**
 32      * Draws the line segment between this point and the specified point to
 33      * standard draw.
 34      *
 35      * @param that
 36      *            the other point
 37      */
 38     public void drawTo(Point that) {
 39         /* DO NOT MODIFY */
 40         StdDraw.line(this.x, this.y, that.x, that.y);
 41     }
 42 
 43     /**
 44      * Returns the slope between this point and the specified point. Formally,
 45      * if the two points are (x0, y0) and (x1, y1), then the slope is (y1 - y0)
 46      * / (x1 - x0). For completeness, the slope is defined to be +0.0 if the
 47      * line segment connecting the two points is horizontal;
 48      * Double.POSITIVE_INFINITY if the line segment is vertical; and
 49      * Double.NEGATIVE_INFINITY if (x0, y0) and (x1, y1) are equal.
 50      *
 51      * @param that
 52      *            the other point
 53      * @return the slope between this point and the specified point
 54      */
 55     public double slopeTo(Point that) {
 56         /* YOUR CODE HERE */
 57         int x0 = this.x;
 58         int y0 = this.y;
 59         int x1 = that.x;
 60         int y1 = that.y;
 61         if (x0 == x1 && y0 == y1)
 62             return Double.NEGATIVE_INFINITY;
 63         else if (x0 == x1)
 64             return Double.POSITIVE_INFINITY;
 65         else if (y0 == y1)
 66             return +0.0;
 67         else
 68             return (y1 - y0) / (double)(x1 - x0);
 69     }
 70 
 71     /**
 72      * Compares two points by y-coordinate, breaking ties by x-coordinate.
 73      * Formally, the invoking point (x0, y0) is less than the argument point
 74      * (x1, y1) if and only if either y0 < y1 or if y0 = y1 and x0 < x1.
 75      *
 76      * @param that
 77      *            the other point
 78      * @return the value <tt>0</tt> if this point is equal to the argument point
 79      *         (x0 = x1 and y0 = y1); a negative integer if this point is less
 80      *         than the argument point; and a positive integer if this point is
 81      *         greater than the argument point
 82      */
 83     public int compareTo(Point that) {
 84         /* YOUR CODE HERE */
 85         int x0 = this.x;
 86         int y0 = this.y;
 87         int x1 = that.x;
 88         int y1 = that.y;
 89         if (y0 == y1) {
 90             if (x0 == x1)
 91                 return 0;
 92             else if (x0 > x1)
 93                 return 1;
 94             else
 95                 return -1;
 96         } else if (y0 > y1)
 97             return 1;
 98         else
 99             return -1;
100     }
101 
102     /**
103      * Compares two points by the slope they make with this point. The slope is
104      * defined as in the slopeTo() method.
105      *
106      * @return the Comparator that defines this ordering on points
107      */
108     public Comparator<Point> slopeOrder() {
109         /* YOUR CODE HERE */
110         return new SlopeOrder(this);
111     }
112     /**
113      * 此comparator提供兩個點關於參照點的比較方法,主要供排序方法使用
114      * invokePoint就是參照點,兩個待比較的Point的大小,這就是排序方法中要用的排序依據
115      * @author evasean www.cnblogs.com/evasean/
116      *
117      */
118     private class SlopeOrder implements Comparator<Point>{
119         private final Point p0;
120         public SlopeOrder(Point invokePoint){
121             this.p0 = invokePoint;
122         }
123         @Override
124         public int compare(Point o1, Point o2) {
125             // TODO Auto-generated method stub
126             double slope1 = p0.slopeTo(o1);
127             double slope2 = p0.slopeTo(o2);
128             return Double.compare(slope1, slope2); //double不推薦用==直接比大小,採用這種方式比較好
129         }
130     }
131 
132     /**
133      * Returns a string representation of this point. This method is provide for
134      * debugging; your program should not rely on the format of the string
135      * representation.
136      *
137      * @return a string representation of this point
138      */
139     public String toString() {
140         /* DO NOT MODIFY */
141         return "(" + x + ", " + y + ")";
142     }
143 
144     /**
145      * Unit tests the Point data type.
146      */
147     public static void main(String[] args) {
148         /* YOUR CODE HERE */
149         Point p1 = new Point(0, 0);
150         Point p2 = new Point(1, 1);
151         System.out.println("p1.compareTo(p2)=" + p1.compareTo(p2));
152         System.out.println("p1.slopeTo(p2)=" + p1.slopeTo(p2));
153         Point p3 = new Point(0, 4);
154         System.out.println("p1.slopeTo(p3)=" + p1.slopeTo(p3));
155         Point p4 = new Point(4, 4);
156         System.out.println("p3.compareTo(p4)=" + p3.compareTo(p4));
157         System.out.println("p3.slopeTo(p4)=" + p3.slopeTo(p4));
158         Point p5 = new Point(0, 0);
159         System.out.println("p1.slopeTo(p5)=" + p1.slopeTo(p5));
160     }
161 }

 

二、Brute force

 

這個類很簡單,直接看代碼

  1 import java.util.ArrayList;
  2 import java.util.Arrays;
  3 import java.util.Comparator;
  4 
  5 import edu.princeton.cs.algs4.In;
  6 import edu.princeton.cs.algs4.StdDraw;
  7 import edu.princeton.cs.algs4.StdOut;
  8 /**
  9  * @author evasean www.cnblogs.com/evasean/
 10  */
 11 public class BruteCollinearPoints {
 12     private int segNum;
 13     private Point[] points; //提交作業時提示輸入的給構造函數的數組內容不能發生改變,故類中加個數組將輸入參數存起來
 14     private ArrayList<LineSegment> segmentList= new ArrayList<LineSegment>();
 15 
 16     public BruteCollinearPoints(Point[] inpoints) {
 17         if (inpoints == null)
 18             throw new IllegalArgumentException("Constructor argument Point[] is null!");
 19         // finds all line segments containing 4 points
 20         for (int i=0;i<inpoints.length;i++) {
 21             if (inpoints[i] == null)
 22                 throw new IllegalArgumentException("there is null in constructor argument");
 23         }
 24         points = new Point[inpoints.length];
 25         for (int i=0;i<inpoints.length;i++) {
 26             points[i] = inpoints[i];
 27         }
 28         Arrays.sort(points); //對本對象的私有數組進行排序
 29         for (int i=0;i<points.length-1;i++) {
 30             if (points[i].compareTo(points[i+1]) == 0) // 與前一個元素相等
 31                 throw new IllegalArgumentException("there exists repeated points!");
 32         }
 33         //作業提交時提示隨機穿插順序調用numberOfSegments()和segment()方法返回結果要求穩定
 34         //那麼構造函數中就要把LineSegment找好
 35         findLineSegment(points); 
 36     }
 37 
 38     /**
 39      * 按照作業要求用四層迴圈來做
 40      * @param points
 41      */
 42     private void findLineSegment(Point[] points) {
 43         int pNum = points.length;
 44         for (int i = 0; i < pNum - 3; i++) { // i不需要遍歷最後三個節點,因為至少四個節點才能組成LineSegment
 45             // 每個comparator需要占據額外空間,總共需要n-4個Comparator<Point>的額外空間
 46             Comparator<Point> comparator = points[i].slopeOrder();
 47             for (int j = i + 1; j < pNum - 2; j++) {
 48                 if (points[j].compareTo(points[i]) == 0)
 49                     continue; // 相同point直接跳過
 50                 for (int l = j + 1; l < pNum - 1; l++) {
 51                     if (points[l].compareTo(points[i]) == 0)
 52                         continue;
 53                     if (points[l].compareTo(points[j]) == 0)
 54                         continue;
 55                     if (comparator.compare(points[j], points[l]) == 0) { // point[j]和point[l]相對於point[i]的斜率相等
 56                         for (int m = l + 1; m < pNum; m++) {
 57                             if (points[m].compareTo(points[i]) == 0)
 58                                 continue;
 59                             if (points[m].compareTo(points[j]) == 0)
 60                                 continue;
 61                             if (points[m].compareTo(points[l]) == 0)
 62                                 continue;
 63                             if (comparator.compare(points[l], points[m]) == 0) {
 64                                 // point[l]和point[m]相對於point[i]的斜率相等時,i、j、l、m 四點可以組成一個linesegment
 65                                 // 每個LineSegment需要占據一份額外空間
 66                                 LineSegment seg = new LineSegment(points[i], points[m]);
 67                                 segmentList.add(seg);
 68                             }
 69                         }
 70                     }
 71                 }
 72             }
 73         }
 74         segNum = segmentList.size();
 75         
 76     }
 77     
 78     public int numberOfSegments() {
 79         // the number of line segments
 80         return segNum;
 81     }
 82     
 83     public LineSegment[] segments() {
 84         // the line segments
 85         //作業提交時,提示要求多次調用segments()方法返回的應該是不同的對象
 86         LineSegment[] segments = new LineSegment[segNum];
 87         int i = 0;
 88         for(LineSegment seg : segmentList){
 89             segments[i++] = seg;
 90         }
 91         return segments;
 92     }
 93 
 94     public static void main(String[] args) {
 95         // read the n points from a file
 96         In in = new In(args[0]);
 97         //In in = new In("collinear/input8.txt"); //本地測試使用
 98         int n = in.readInt();
 99         Point[] points = new Point[n];
100         for (int i = 0; i < n; i++) {
101             int x = in.readInt();
102             int y = in.readInt();
103             points[i] = new Point(x, y);
104         }
105         
106         // draw the points
107         StdDraw.enableDoubleBuffering();
108         StdDraw.setXscale(0, 32768);
109         StdDraw.setYscale(0, 32768);
110         StdDraw.setPenColor(StdDraw.RED);
111         StdDraw.setPenRadius(0.01);
112         for (Point p : points) {
113             p.draw();
114         }
115         StdDraw.show();
116 
117         // print and draw the line segments
118         BruteCollinearPoints collinear = new BruteCollinearPoints(points);
119         for (LineSegment segment : collinear.segments()) {
120             StdOut.println(segment);
121             segment.draw();
122         }
123         StdDraw.show();
124     }
125 }

三、A faster, sorting-based solution

 

這個類的設計思想題目中已經描述的很詳細了,主要就是以下四點:

  1. Think of p as the origin. 
  2. For each other point q, determine the slope it makes with p
  3. Sort the points according to the slopes they makes with p
  4. Check if any 3 (or more) adjacent points in the sorted order have equal slopes with respect to p. If so, these points, together with p, are collinear.

這個演算法的性能瓶頸就在於第三點的排序,更詳細的設計思路我直接寫在代碼註釋里。

  1 import java.util.ArrayList;
  2 import java.util.Arrays;
  3 import java.util.Comparator;
  4 import java.util.HashMap;
  5 import java.util.List;
  6 import java.util.Map;
  7 
  8 import edu.princeton.cs.algs4.In;
  9 import edu.princeton.cs.algs4.StdDraw;
 10 import edu.princeton.cs.algs4.StdOut;
 11 /**
 12  * @author evasean www.cnblogs.com/evasean/
 13  */
 14 public class FastCollinearPoints {
 15     
 16     private Point[] points; //提交作業時提示輸入的給構造函數的數組內容不能發生改變,故類中加個數組將輸入參數存起來
 17     private final LineSegment[] segments;
 18     private int segNum;
 19     
 20     private List<PointPair> pointPairList; //存儲構成LineSegment的起點和終點Point對
 21     /**
 22      * LineSegment類不允許變動,但是可使用靈活度受限,自己新加個內部類使用
 23      * 本類用來存儲可構成LineSegment的起點和終點point對
 24      * 由於在遍歷過程中會存在包含關係的起點和終點point對,僅僅靠LineSegment類識別包含關係的效率會很低
 25      * 此類中加了slope來記錄就可以很大的提高效率了,因為一個點和一個斜率就確定了一條直線
 26      * 不需要再進行額外比較和計算
 27      * 因為由於PointPair是對points從前到後遍歷產生的,所以如果兩個PointPair存在包含關係,那麼
 28      * 這兩個PointPair中largePoint和slope一定相等
 29      * 但smallPoint不相等,smallPoint更小的那個PointPair包含了另一個PointPair
 30      * 這是LineSegment去重的關鍵
 31      * @author evasean www.cnblogs.com/evasean/
 32      */
 33     private class PointPair{
 34         private final Point smallPoint;
 35         private final Point largePoint;
 36         private final double slope; 
 37         public PointPair(Point smallPoint, Point largePoint){
 38             this.smallPoint = smallPoint;
 39             this.largePoint = largePoint;
 40             this.slope = largePoint.slopeTo(smallPoint);
 41         }
 42         public Point getLargePoint(){
 43             return this.largePoint;
 44         }
 45         public Point getSmallPoint(){
 46             return this.smallPoint;
 47         }
 48         public double getSlope(){
 49             return this.slope;
 50         }
 51         public int compareTo(PointPair that) {
 52             Point l1 = this.getLargePoint();
 53             Point l2 = that.getLargePoint();
 54             double s1 = this.getSlope();
 55             double s2 = that.getSlope();
 56             if(l1.compareTo(l2) > 0) return 1;
 57             else if(l1.compareTo(l2) < 0) return -1;
 58             else{
 59                 if(s1>s2) return 1;
 60                 else if(s1<s2) return -1;
 61                 else return 0;
 62             }
 63         }
 64         /**
 65          * 判斷PointPair中的包含關係時需要用到比較器
 66          * 此比較器是以largePoint為比較的主要元素,slope為次要元素
 67          * smallPoint不參比較大小的考核,僅僅在兩個PointPair相等時用作判斷包含關係之用
 68          * 兩個PointPair pp1 和 pp2中
 69          * if pp1.largePoint > pp2.largePoint --> pp1 > pp2
 70          * else if pp1.largePoint < pp2.largePoint --> pp1 < pp2
 71          * if pp1.largePoint == pp2.largePoint && pp1.slope > pp2.slope --> pp1 > pp2
 72          * if pp1.largePoint == pp2.largePoint && pp1.slope < pp2.slope --> pp1 < pp2
 73          * if pp1.largePoint == pp2.largePoint && pp1.slope == pp2.slope --> pp1 == pp2
 74          * @return
 75          */
 76         public Comparator<PointPair> pointPairComparator() {
 77             return new PointPairComparator();
 78         }
 79         private class PointPairComparator implements Comparator<PointPair>{
 80             @Override
 81             public int compare(PointPair pp1, PointPair pp2) {
 82                 // TODO Auto-generated method stub
 83                 Point l1 = pp1.getLargePoint();
 84                 Point l2 = pp2.getLargePoint();
 85                 double s1 = pp1.getSlope();
 86                 double s2 = pp2.getSlope();
 87                 if(l1.compareTo(l2) > 0) return 1;
 88                 else if(l1.compareTo(l2) < 0) return -1;
 89                 else{
 90                     return Double.compare(s1, s2); //double元素用Double.compare進行比較更精確
 91                 }
 92             }
 93         }
 94     }
 95     
 96     public FastCollinearPoints(Point[] inpoints) {
 97         // finds all line segments containing 4 or more points
 98         if (inpoints == null)
 99             throw new IllegalArgumentException("Constructor argument Point[] is null!");
100         // finds all line segments containing 4 points
101         for (int i=0;i<inpoints.length;i++) {
102             if (inpoints[i] == null)
103                 throw new IllegalArgumentException("there is null in constructor argument");
104         }
105         points = new Point[inpoints.length];
106         for (int i=0;i<inpoints.length;i++) {
107             points[i] = inpoints[i];
108         }
109         Arrays.sort(points); //對本對象的私有數組進行排序
110         for (int i=0;i<points.length-1;i++) {
111             if (points[i].compareTo(points[i+1]) == 0) // 與前一個元素相等
112                 throw new IllegalArgumentException("there exists repeated points!");
113         }
114         //作業提交時提示隨機穿插順序調用numberOfSegments()和segment()方法返回結果要求穩定
115         //那麼構造函數中就要把LineSegment找好
116         findPointPairForLineSegment(points);
117         segments = generateLineSegment();
118     }
119 
120     /**
121      * 尋找滿足LineSegment的PointPair
122      * @param points
123      */
124     private void findPointPairForLineSegment(Point[] points){
125         int pNum = points.length;
126         pointPairList = new ArrayList<PointPair>();
127         for (int i = 0; i < pNum - 3; i++) { //i不需要遍歷最後三個節點,因為至少四個節點才能組成LineSegment
128             if(points[i]==null)
129                 throw new IllegalArgumentException("there is null in constructor argument");
130             Point origin = points[i]; //i處節點作為相對原點
131             Point[] tPoints = new Point[pNum-i-1]; //需要用到額外空間來存儲本輪i之後的節點根據它們各自與節點i的相對斜率來排序的結果
132             int tpNum = 0;
133             for (int j = i + 1; j < pNum; j++) {
134                 tPoints[tpNum++] = points[j];
135             }
136             //origin.slopeOrder()這個比較器就是告訴Arrays.sort待排序的那些節點tPoints排序的依據是各自與節點i的斜率
137             Arrays.sort(tPoints,origin.slopeOrder()); 
138             
139             int startPostion = 0; //startPosition用來記錄slope相同的point位置區間的起始位置
140             double slope = origin.slopeTo(tPoints[0]);
141             Map<Integer,Integer> intervalMap = new HashMap<Integer,Integer>(); //記錄slope相同的point位置區間
142             int curPostion = 1;
143             for(; curPostion<tpNum; curPostion++){
144                 if(Double.compare(origin.slopeTo(tPoints[curPostion]), slope)==0)
145                     continue;
146                 else{ //遍歷至slope不與之前相同的位置
147                     if(curPostion-startPostion >= 3) { 
              
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 使用函數的意義 首先必須要認識到的是函數在python使用過程中是十分重要的,對於我們經常寫代碼時發生的多次重覆的某些代碼,我們時常會使用函數來解決諸如此類問題。 這是因為函數在解決代碼重用方面具有很大的優勢,並且這些定義好的函數在面臨修改代碼時的操作也減輕了很大一部分的工作量,並且程式可讀性也很好 ...
  • MyBatis配置文件、操作sql語句(本文全是代碼,代碼中包含詳細註釋) ...
  • Google Inception Net,ILSVRC 2014比賽第一名。控制計算量、參數量,分類性能非常好。V1,top-5錯誤率6.67%,22層,15億次浮點運算,500萬參數(AlexNet 6000萬)。V1降低參數量目的,參數越多模型越龐大,需數據量越大,高質量數據昂貴;參數越多,耗費 ...
  • #Author:clarkproduct_list = [('iphone',5800),('Mac Pro',9800),('bike',800),('watch',10600),('coffee',31),('python',120),]shopping_list = [] #定義一個空的列表用 ...
  • http://search.maven.org/#artifactdetails%7Cstax%7Cstax%7C1.2.0_rc2-dev%7Cjar commons-fileupload-1.2.1.jar <dependency> <groupId>tomcat</groupId> <arti ...
  • python變數的記憶體地址查詢 流程式控制制和縮進 if 條件: 執行下一個語句(內容) 內容2 else: 內容3 內容4 python語言縮進必須一樣,或者用4個空格,一般強烈推薦使用四個空格代替縮進。因為在不同的系統環境可以使用。沒有因為縮進的問題導致程式不相容性的問題。 = 和 == 的區別 一 ...
  • 如何使用PHP自動備份資料庫 1、前言 mysql資料庫的備份方式有很多; 例如: 1、使用mysqldump函數 mysqldump -u username -p dbname table1 table2 ... > BackupName.sql dbname參數表示資料庫的名稱 table1和t ...
  • 正常在Java工程中讀取某路徑下的文件時,可以採用絕對路徑和相對路徑,絕對路徑沒什麼好說的,相對路徑,即相對於當前類的路徑。在本地工程和伺服器中讀取文件的方式有所不同,以下圖配置文件為例。 本地讀取資源文件 java類中需要讀取properties中的配置文件,可以採用文件(File)方式進行讀取: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...