1023題解:貪心算法實(shí)現(xiàn)最小數(shù)字組合)
1. PAT乙級(jí)1023題目解析與實(shí)戰(zhàn)攻略作為計(jì)算機(jī)專業(yè)學(xué)生和編程愛好者繞不開的編程能力測(cè)試PATProgramming Ability Test乙級(jí)考試中的1023題一直是高頻考點(diǎn)。這道題看似簡單卻暗藏不少算法實(shí)現(xiàn)的細(xì)節(jié)陷阱。我在三次模擬考試中兩次栽在這道題上最終通過系統(tǒng)化分析總結(jié)出一套穩(wěn)定解法這里把完整解題思路和避坑指南分享給大家。1.1 題目核心要求分析題目描述為給定數(shù)字0-9各若干個(gè)要求按指定規(guī)則組合成最小的整數(shù)。具體規(guī)則包括至少使用1個(gè)非零數(shù)字作為首位所有給定數(shù)字必須全部使用不能有前導(dǎo)零除非本身就是0實(shí)際樣例輸入格式為數(shù)字0的個(gè)數(shù) 數(shù)字1的個(gè)數(shù) ... 數(shù)字9的個(gè)數(shù)例如輸入2 2 0 0 0 3 0 0 1 0表示有數(shù)字02個(gè)數(shù)字12個(gè)數(shù)字53個(gè)數(shù)字81個(gè) 其他數(shù)字個(gè)數(shù)為01.2 解題關(guān)鍵點(diǎn)拆解這道題的核心難點(diǎn)在于非零最小數(shù)字的選取策略剩余數(shù)字的排列組合方式處理全零輸入的特殊情況輸出格式的精確控制2. 算法設(shè)計(jì)與實(shí)現(xiàn)方案2.1 貪心算法應(yīng)用最有效的解法是采用貪心算法首先選擇最小的非零數(shù)字作為首位剩余數(shù)字按從小到大的順序排列如果所有數(shù)字都是0則直接輸出0#include stdio.h int main() { int count[10] {0}; for(int i0; i10; i) { scanf(%d, count[i]); } // 尋找最小的非零首位 int first -1; for(int i1; i10; i) { if(count[i] 0) { first i; count[i]--; break; } } // 處理全零情況 if(first -1) { printf(0\n); return 0; } printf(%d, first); // 輸出剩余數(shù)字從小到大 for(int i0; i10; i) { while(count[i] 0) { printf(%d, i); count[i]--; } } printf(\n); return 0; }2.2 時(shí)間復(fù)雜度分析該算法的時(shí)間復(fù)雜度為O(n)其中n是輸出數(shù)字的總位數(shù)。因?yàn)閷ふ沂孜粩?shù)字固定10次循環(huán)O(1)輸出剩余數(shù)字與輸入數(shù)字總數(shù)成正比O(n)空間復(fù)雜度為O(1)只使用了固定大小的計(jì)數(shù)數(shù)組。3. 常見錯(cuò)誤與調(diào)試技巧3.1 典型錯(cuò)誤案例未處理全零輸入// 錯(cuò)誤代碼示例 if(count[0] 10) { // 錯(cuò)誤判斷條件 printf(0\n); return 0; }首位選擇邏輯錯(cuò)誤// 錯(cuò)誤代碼示例 for(int i0; i10; i) { // 從0開始遍歷會(huì)導(dǎo)致選擇0作為首位 if(count[i] 0) { first i; count[i]--; break; } }輸出格式錯(cuò)誤// 錯(cuò)誤代碼示例 printf(%d, first); // 缺少換行符 for(int i0; i10; i) { ... }3.2 調(diào)試與驗(yàn)證方法邊界測(cè)試用例全零輸入0 0 0 0 0 0 0 0 0 0僅一個(gè)非零數(shù)字0 1 0 0 0 0 0 0 0 0最大規(guī)模輸入20 20 20 20 20 20 20 20 20 20輸出驗(yàn)證技巧使用assert驗(yàn)證數(shù)字使用數(shù)量是否正確打印中間變量檢查首位選擇邏輯對(duì)比標(biāo)準(zhǔn)輸出檢查格式要求重要提示PAT系統(tǒng)對(duì)輸出格式要求極其嚴(yán)格務(wù)必確保行末無多余空格最后有換行符數(shù)字間無分隔符4. 性能優(yōu)化與擴(kuò)展思考4.1 算法優(yōu)化空間雖然當(dāng)前解法已是最優(yōu)但可以考慮使用更緊湊的輸入處理int num; while(scanf(%d, num) ! EOF) { count[i] num; if(i 10) break; }批量輸出優(yōu)化char output[1000]; int pos 0; output[pos] first 0; for(int i0; i10; i) { while(count[i]--) { output[pos] i 0; } } output[pos] \0; printf(%s\n, output);4.2 題目變種思考最大數(shù)版本要求組成最大數(shù)解法從大到小選擇數(shù)字9→8→...→0指定數(shù)位限制如不超過10位需添加數(shù)位計(jì)數(shù)判斷帶權(quán)值組合每個(gè)數(shù)字有特定權(quán)值變?yōu)閯?dòng)態(tài)規(guī)劃問題5. PAT備考實(shí)戰(zhàn)建議5.1 刷題策略乙級(jí)題目優(yōu)先級(jí)前20題基礎(chǔ)語法練習(xí)21-50題算法入門51-95題重點(diǎn)突破含1023這類經(jīng)典題時(shí)間分配建議讀題分析3-5分鐘編寫代碼10-15分鐘調(diào)試測(cè)試5-10分鐘5.2 考場(chǎng)應(yīng)對(duì)技巧答題流程先通讀所有題目按難易程度排序從簡單題開始建立信心調(diào)試技巧使用printf調(diào)試關(guān)鍵變量準(zhǔn)備常用代碼模板注意題目中的邊界條件描述時(shí)間管理遇到卡殼題目先做標(biāo)記最后15分鐘檢查所有題目提交狀態(tài)確保每道題都有基本解法提交這道題在真實(shí)考試中出現(xiàn)概率約15%建議至少練習(xí)3種不同變種。我在實(shí)際考試中遇到過類似的數(shù)字組合問題當(dāng)時(shí)因?yàn)闆]處理好全零情況丟了5分。后來發(fā)現(xiàn)PAT的測(cè)試用例特別喜歡在邊界條件上設(shè)置陷阱所以現(xiàn)在每次做題都會(huì)特意構(gòu)造極端用例驗(yàn)證。