壓縮變換
小明最近在研究壓縮算法。
他知道,壓縮的時候如果能夠使得數值很小,就能通過熵編碼得到較高的壓縮比。
然而,要使數值很小是一個挑戰。
最近,小明需要壓縮一些正整數的序列,這些序列的特點是,後面出現的數字很大可能是剛出現過不久的數字。對於這種特殊的序列,小明準備對序列做一個變換來減小數字的值。
變換的過程如下:
從左到右枚舉序列,每枚舉到一個數字,如果這個數字沒有出現過,剛將數字變換成它的相反數,如果數字出現過,則看它在原序列中最後的一次出現後面(且在當前數前面)出現了幾種數字,用這個種類數替換原來的數字。
比如,序列(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 ,根本就是不讓你使用算法策略的意思