7屆藍橋杯第10題 -壓縮變換
壓縮變換
小明最近在研究壓縮演算法。
他知道,壓縮的時候如果能夠使得數值很小,就能通過熵編碼得到較高的壓縮比。
然而,要使數值很小是一個挑戰。
最近,小明需要壓縮一些正整數的序列,這些序列的特點是,後面出現的數字很大可能是剛出現過不久的數字。對於這種特殊的序列,小明準備對序列做一個變換來減小數字的值。
變換的過程如下:
從左到右列舉序列,每列舉到一個數字,如果這個數字沒有出現過,剛將數字變換成它的相反數,如果數字出現過,則看它在原序列中最後的一次出現後面(且在當前數前面)出現了幾種數字,用這個種類數替換原來的數字。
比如,序列(a1, a2, a3, a4, a5)=(1, 2, 2, 1, 2)在變換過程為:
a1: 1未出現過,所以a1變為-1;
a2: 2未出現過,所以a2變為-2;
a3: 2出現過,最後一次為原序列的a2,在a2後、a3前有0種數字,所以a3變為0;
a4: 1出現過,最後一次為原序列的a1,在a1後、a4前有1種數字,所以a4變為1;
a5: 2出現過,最後一次為原序列的a3,在a3後、a5前有1種數字,所以a5變為1。
現在,給出原序列,請問,按這種變換規則變換後的序列是什麼。
輸入格式:
輸入第一行包含一個整數n,表示序列的長度。
第二行包含n個正整數,表示輸入序列。
輸出格式:
輸出一行,包含n個數,表示變換後的序列。
例如,輸入:
5
1 2 2 1 2
程式應該輸出:
-1 -2 0 1 1
再例如,輸入:
12
1 1 2 3 2 3 1 2 2 2 3 1
程式應該輸出:
-1 0 -2 -3 1 1 2 2 0 0 2 2
資料規模與約定
對於30%的資料,n<=1000;
對於50%的資料,n<=30000;
對於100%的資料,1 <=n<=100000,1<=ai<=10^9
資源約定:
峰值記憶體消耗(含虛擬機器) < 256M
CPU消耗 < 3000ms
請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入...” 的多餘內容。
所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。
注意:不要使用package語句。不要使用jdk1.7及以上版本的特性。
注意:主類的名字必須是:Main,否則按無效程式碼處理。
這道題依然可以使用倆種方式來寫,一種是遞迴類演算法策略, 一種是內嵌迴圈,但注意題幹中這麼一句話:”對於100%的資料,1 <=n<=100000,1<=ai<=10^9“, 顯然如果使用遞迴類演算法策略來寫,肯定是極大耗時的,所以藉著遞迴的思想來轉換寫成迴圈
package LanQiao_TrueQuestion; import java.util.HashSet; import java.util.LinkedList; import java.util.Set; public class lq_7_10 { static int n=12; static int[] x={1 ,1 ,2, 3, 2, 3, 1, 2, 2, 2 ,3, 1};//使用者輸入陣列 static LinkedList<Integer> newx ;//作為新陣列輸出 static int[] y;//作為二表儲存 public static void main(String[] args) { y=new int[n]; newx= new LinkedList<>(); for (int i=0;i<x.length;i++){ //遍歷y,如果陣列y中儲存了相應的值,那麼遍歷區間存在多少種不同的數, 實現儲存 for (int j = 0; j <y.length ; j++) { if(x[i]==y[j]){ Set<Integer> set=new HashSet<>(); for (int k = j+1; k <i ; k++) { set.add(x[k]); } newx.addLast(set.size()); //修改y中儲存值 y[j]=0;//舊值刪除 y[i]=x[i];//新址新增 break; } if(j==y.length-1){//代表了遍歷了整個陣列也沒有找到,那麼做另外處理 //陣列y中不存在x中的元素 newx.addLast(x[i]-x[i]*2); y[i]=x[i];//新增相應的值 } } } System.out.print(newx); } }
總結:要想快速寫出本題,還必須在稿紙上清晰寫出演算法設計邏輯,不然寫程式碼會錯誤連連
注意: 藍橋杯演算法設計題8-10 ,根本就是不讓你使用演算法策略的意思