pta第一到第三次題目集

熊建新發表於2023-03-26

(1)前言

pta第一次作業的7-1,7-2,7-4主要熟悉運用了 if-else 的語句使用,以及運用System.out.printf進行格式化輸出,7-3九九乘法表主要學會了運用for迴圈及多重迴圈的使用7-5到7-10,在運用迴圈和if-else語句的同時,學會了應用String類,對字串進行輸入和輸出,同時對String類中的方法有了更多的瞭解。總體量感覺較大,題目較多。

pta第二次作業7-1到7-8主要是對第一次題目集的鞏固,加深了對if-else的使用,其中7-5利用switch-case能替代if-else更好的解決問題,7-9為壓軸題,對類與物件的概念有了初步的認識,該題難度較大。

pta第三次作業7-1到7-2難度較為簡單,對類與物件的概念有了更深的一步見解,後7-3,7-4是第二次作業中求下一天的迭代,認為難度較大,一題的量抵10題!!!

(2)設計與分析(對題目原始碼分析,參考power。。有相應的解釋和心得)

--訓練題集01和訓練題集02中的題目較為簡單,未涉及到較多方法和類,主要是以熟悉if-else語句,巢狀for迴圈,String類內方法的呼叫,以及簡單日期類的設計。訓練題集01中7-1,7-2,7-4,以及訓練題集02中7-4,7-5,7-8中主要訓練了if-else和switch-case語句的使用,並結合了String類中幾個方法的使用,以02中的7-4與7-5中部分程式碼為例子:

7-4:

7-4中 輸入案例如下:兩個整數:遊戲種族、角色的選項,以空格分隔。例如:1 2。

種族選項設定為:1、人類 2、精靈 3、獸人 4、暗精靈
角色選項設定為:1、戰士 2、法師 3、射手

發現選項設定都為整型常量 ,並且各個常量代表的選項不同,便立馬想到switch語句中的兩個規則:

case標籤必須是常量表示式(constantExpression),如62或者’8’等。

case標籤必須是唯一表示式;也就是說,不允許兩個case具有相同的值。

所以先建立兩個變數a,b,然後用一個if語句限制a,b的值限制為選項中要求的值,也就是1-4和1-3,緊接著使用switch-case語句,就能輕鬆解決,但最後測試程式碼的時候發現,一套流程下來,結果還是有誤,當我輸入了1 1的時候 測試用例中輸出了4個種族和3個角色,說明沒有進行單一選擇,後面再看switch語句的用法,發現每個case語句結束後,都少了break;以至於進入到case 1後,後面的case語句都進入了,導致了問題的出現,所有修改程式碼的時候,每個語句後面都增加了break;最後測試便成功了。

7-5:

7-5中案例如下:

學校的學號由8位數字組成,前兩位是入學年份(省略了20);第3、4位是學院編號,01代表材料學院,02代表機械學院,03代表外語學院,20代表軟體學院;第5、6位是學院內部班級編號,最後兩位是班級內部學號。如:18011103,入學年份是2018年,材料學院,11班,03號     8位數字組成的學號。輸入案例:例如:18011103   注意:輸入學號不是8位或者學院編號不是01、02、03、20其中之一,屬於非法輸入

開始的時候在糾結是否使用字元陣列,但發現其中都是兩兩字元出現,所以採用了String類來對輸入進行處理,由於每兩位數的組成代表不一樣的事物,想到呼叫String類中substring方法,這樣可以有效的將特定下標的兩個字元取出,最後使用equalsIgnoreCase進行提取出的字串與題目給出的進行比較(不能講字串用“==”進行比較,java中字串的比較是==比較引用,equal比較值,例如  案例一: String a="abc";String b="abc",那麼a==b將返回true。因為在java中字串的值是不可改變的,相同的字串在記憶體中只會存一份,所以a和b指向的是同一個物件;

               案例二:String a=new String("abc"); String b=new String("abc");那麼a==b將返回false,此時a和b指向不同的物件。)成功解決問題。

 

--訓練題集03中4題都是類與物件及方法的設計與使用,前兩題為基礎題,7-3,7-4為日期類的迭代,難度係數較高,7-3與7-4案例如下:

7-3類的設計以及部分主函式原始碼:

 

 

 

 定義日期類,主要包含無條件構造物件和有條件構造物件,以及多個方法,。

其中判斷閏年方法比較簡單當該年能夠被4整除並且不被100整除或者該年能直接整除四百,則為閏年,返回true的值,否則返回false值,所以一個if語句就可以解決該問題。

 

判斷輸入年份年月日是否正確的時候,則要呼叫isLeapYear方法,因為閏年時,2月份的日子為29天,所以需要呼叫該方法,接下來按照題目要求用if語句判斷是否在正確範圍內。

獲取下一天的方法則需要,再次呼叫checkInputVlidity方法,實現了方法的迭代,接下來需要注意的是月份的最後一天和年份的最後一個月,多個if-else進行條件判斷,最後求得下一天,最後透過測試。

 

 --訓練題集中7-4日期類設計在當時寫的時候,可謂是一波三折,算是最難最難的題目了,雖然不用寫主函式,只要設計類和方法,但是是前兩次作業日期類的迭代中的迭代!!!類與方法的設計主要如下:

 

 

public DateUtil getNextNDays(int n);//取得year-month-day的下n天日期

public DateUtil getPreviousNDays(int n);//取得year-month-day的前n天日期

public boolean compareDates(DateUtil date);//比較當前日期與date的大小(先後)

public boolean equalTwoDates(DateUtil date);//判斷兩個日期是否相等

public int getDaysofDates(DateUtil date);//求當前日期與date之間相差的天數

public String showDate();//以“year-month-day”格式返回日期值

其中有需要

應用程式共測試三個功能:

  1. 求下n天
  2. 求前n天
  3. 求兩個日期相差的天數

求下n天的時候,當時想的是,利用一個for迴圈,然後將求下一天的方法匯入進去,未超過n天,則繼續迴圈求出下一天,於是再次迭代,將求下一天方法放入求下n天的方法中,最後求出了下n天的結果。求前n天情況類似,先寫出求前一天的方法,再利用for迴圈 帶入到求前n天的方法中去。

但測試結果如下:

 

 

 雖然都是對的,但是耗時實在是太高了,一單要求測試大一點的整數,要等待的時間實在太長,不符合設計程式的初衷,所以對求下n天的方法進行了改進:要麼去除部分迴圈,要麼使迴圈次數變小,我選擇了後者;

 

 

 這樣n在每輪迴圈中至少減去365,相較於上圖,大大減少了迴圈的次數,提高了效率。

在求兩個日期差的天數時,也是將判斷日期大小以及日期是否正確的方法調入到其方法中。最困擾我的是演算法,但也是想了一些時候想出來了:首先求出另兩個日期的年份差,然後將差值*365天(由於其中可能包含閏年,則需要for迴圈以及if-else語句判斷,將每年的天數相加),然後將日期大的月份每個月的天數相加,再減去日期小的月份的每個月的天數,最後求得日期差,具體程式碼和方法如下:

 

 (判斷日期是否相等,相等則返回n,初值為0)   (判斷年份是否有差異)

最後經過一系列迴圈,返回最後n的值,得到相差的天數

(3)採坑心得

--訓練集中7-2中的第九行容易把“||”打成“&&”,造成測試資料出錯(這個點在一開始其實很容易想到,但是下意識打成了“||”,屬實不應該)

 

 --訓練集2中7-4運用的switch-case語句中,開始容易把break給遺漏掉,導致輸出的結果有多行,測試時發現問題(switch 要break ,switch 要break,switch 要break   重要的事說三遍!!!!!)

 

 --訓練集02中的7-8的14行判斷直角三角形兩邊平方和等於斜邊平方,但在java浮點數中應該寫為平方和與斜邊平方差小於一個較小值,因為浮點數做算術會有誤差,這題測試點一直沒過就在這裡:浮點數做算術有誤差!!!!

 --訓練題集03中7-4的日期類設定中,由於開始在求下一天的方法中判斷2月是否為閏月時使用if未用else,導致在求下n天的時候,一但有一年判斷為閏年,接下來的每年2月都會是29天,最後導致求下n天的時候一直會出現2-3天的誤差。(注意if-else在迴圈語句中的使用,不能偷懶少了else!!!)

 

 

 

(4)改進建議(對編碼給出見解)

1.首先我認為主要需要改進的地方,是在那些出現了較多判斷條件的題目,特別是其中if-else和switch-case的選擇。例如訓練題集01中的7-1,7-2,7-4,以及題目集02中的7-4,7-5,7-8。大部分運用的是if-else語句,原因如下:

當分支較多時,當時用switch的效率是很高的。因為switch是隨機訪問的,就是確定了選擇值之後直接跳轉到那個特定的分支,但是if...else是遍歷所以得可能值,知道找到符合條件的分支。如此看來,switch的效率確實比if-else要高的多。

switch...case只能處理case為常量的情況,對非常量的情況是無能為力的。例如 if (a > 1 && a < 100),是無法使用switch...case來處理的。所以,switch只能是在常量選擇分支時比ifelse效率高,但是ifelse能應用於更多的場合,ifelse比較靈活。

例如題目集02中7-5的程式碼如下:  如果選擇的分支大於或等於下列情況,我會選擇用switch-case語句。

 

 2.我認為最需要改進的,是訓練題集03中7-4的求下n天,當時提交的程式碼如下:

 

 

 

 在求下n天的方法中,使用了求下一天的方法,再加入for迴圈,看是非常合理且方便,實際上:

 

 耗時達到了8秒多!!!!!!!!!  這說明該迴圈結構迴圈較大(最大達到10000天!!!)自身的演算法出現了問題,然後便換了一種思路  部分程式碼如下:

 

 這樣下來便解決了最根本的問題 ,迴圈的次數減少了,執行時長大大減少,由8秒多變成了200毫秒。

(5)總結

 這前三次作業是老師佈置的第一次作業,也是我入門java的第一次作業,題目總體來說難度中等,畢竟就算不能達到速成程式碼的境界,但較難的題目也能被自己軟磨硬泡弄出來。自身的java語法得到了提高,對類和方法的設計也有了進一步的認知和理解,但自身java語法基礎仍然比較薄弱,例如String的方法有些仍然不能靈活運用,以及對類與物件的理解仍然不足,下一步,首先繼續保持java的系統不斷點的線上學習,多上機實驗,將知識轉化到程式程式碼上。

對課程和老師的建議:希望在pta上佈置一些中等難度的題目,儘量涉及到新學的內容,方便記憶,同時希望課堂上講的知識能夠運用到例項上展示出來。(目前確實很多東西感覺學了沒有結合具體例子或操作,等於0)現在課程任務量挺大的,累點不要緊,要緊的是累點的話,要學會真本事。

 

相關文章