從藍橋杯題目看Java輸入問題

就我目前有限的藍橋杯做題經驗來看,C/C++和Java的第一個區別就是輸入。Java的輸入相對比較困難,雖然Scanner已經提供了很多便利,能夠接受多種類型的輸入,但是在多行輸入,尤其是包含空格,長度未知的輸入情況下十分痛苦。。。
以今天做到的一個問題爲例:
*問題描述
某涉密單位下發了某種票據,並要在年終全部收回。
每張票據有唯一的ID號。全年所有票據的ID號是連續的,但ID的開始數碼是隨機選定的。
因爲工作人員疏忽,在錄入ID號的時候發生了一處錯誤,造成了某個ID斷號,另外一個ID重號。
你的任務是通過編程,找出斷號的ID和重號的ID。
假設斷號不可能發生在最大和最小號。
輸入格式
要求程序首先輸入一個整數N(N<100)表示後面數據行數。
接着讀入N行數據。
每行數據長度不等,是用空格分開的若干個(不大於100個)正整數(不大於100000),請注意行內和行末可能有多餘的空格,你的程序需要能處理這些空格。
每個整數代表一個ID號。
輸出格式
要求程序輸出1行,含兩個整數m n,用空格分隔。
其中,m表示斷號ID,n表示重號ID
樣例輸入1
2
5 6 8 11 9
10 12 9
樣例輸出1
7 9
樣例輸入2
6
164 178 108 109 180 155 141 159 104 182 179 118 137 184 115 124 125 129 168 196
172 189 127 107 112 192 103 131 133 169 158
128 102 110 148 139 157 140 195 197
185 152 135 106 123 173 122 136 174 191 145 116 151 143 175 120 161 134 162 190
149 138 142 146 199 126 165 156 153 193 144 166 170 121 171 132 101 194 187 188
113 130 176 154 177 120 117 150 114 183 186 181 100 163 160 167 147 198 111 119
樣例輸出2
105 120*
這個問題對數據輸入處理的要求比較高(對java而言,C/C++的話直接一句gets()就能解決問題),之前想用for()循環套while(s.hasNext()){},然而while()一入深似海,再也出不來了。百度一下發現是.hasNext()對控制檯的輸入阻塞(就是說會停在這一步,直到輸入EOF/Ctrl+Z結束這一步)的緣故。當然也可以用next()結束它,但是就這道題的要求而言似乎不可行。
最後在網上看到一個帖子提供了思路,原文見:

錯誤票據(藍橋杯JavaB組預賽)
http://blog.csdn.net/c740869614/article/details/9252899

以下是對本題思路和注意點的總結:
1.輸入:因爲不管是一個一個數字.nextInt()讀入還是一整行讀入轉爲數組都很麻煩(反正我是想不出該怎麼實現T^T),所以在整行讀入String後再單獨對這個String做處理。

            for(...){
            String ss=s.nextLine();
            Scanner line=new Scanner(ss);
            //因爲是從字符串裏讀,所以不存在控制檯讀入碰到的結束符問題
            while(line.hasNext()){...}
        }

接受來源是String的直接好處就是沒有控制檯那個無法結束循環的問題~
(這裏發現自己知識的小漏洞,竟然不知道Scanner還可以有String這個參數,還是要熟悉API啊!)
另外,nextInt()這類不帶Line的函數,用時要格外小心,讀完自成一行的一個數字要讀下一行數據時一定要加.nextLine()把回車換行搞掉,否則會出錯。

2.算法:第一反應當然是要把數據放到數組裏排序然後遍歷啦。然而看了那篇帖子發現這個想法好蠢的說QAQ 。
我們的最終目的不是想動數據,而是知道數據出現的次數。所以只要能達到統計每個數出現的次數就大功告成啦~這個思路其實是比較重要的,這個思想跟哈希有什麼關係我也不太清楚(對一些術語傻傻分不清楚,還求大神指教哇~)


        //存對所有數據的個數統計,數字大小不超過10000,故數組大小爲10001
        int[] ary=new int[10001];
        ...
        int d=line.nextInt();
        ...
        ary[d]++;
        //在最小到最大之間遍歷統計次數的數組,2次則重複,0次則缺失
            for(int j=min;j<=max;j++){
                if(ary[j]==0)
                    System.out.print(j+" ");
                if(ary[j]==2)
                    System.out.print(j+" ");
            }

歡迎指正,歡迎補充~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章