問題描述:一串首尾相連的珠子(n個),有n種顏色(n<=10),設計乙個演算法,取出其中一段,要求包含所有n種顏色,並使長度最短。並分析時間複雜度與空間複雜度。
思路:可以利用一種計數的方法。定義兩個指標p1和p2,主要有三個步驟:
(1)p1向前移動,如果p1所指的珠子顏色編號為 i ,則增加 i 的出現次數。
當出現的顏色種數為n時,p1停止。
(2)p2向前移動,如果p2所指的珠子顏色編號為 i ,則減少 i 的出現次數
。當出現的顏色種數減為n-1時,p2停止。
(3)p1和p2所指的這段珠子,包含了n種顏色。如果比當前的最小段更短,則進行更新。回到(1)繼續,迴圈終止條件為p2指向最後乙個珠子。
以上給出了實現的思路,具體實現時應該注意一點,這串珠子應該是環狀的。時間複雜度為o(n),空間複雜度為o(n)。
參考**:
const int n = 5; //顏色種類
//函式功能 : 找目標珠子,珠子的顏色用編號表示
//函式引數 : pbead指向珠子陣列,n為珠子個數,from為開始位置,to為結束位置
//返回值 : 找到為真,否則為假
bool beadproblem(int *pbead, int n, int &from, int &to)
; //用於計數
int minlen = n+1;
int i = 0, j = -1, cnt = 0;
while(j < n - 1) //j = n-1時,指向最後乙個珠子
cnt--; //顏色種數減1
} i = (i + 1) % n; //考慮了環的特性,不能是i++
if(i == 0 && j == -1) //i回到了初始位置,但是j未更新,即沒有找到符合條件的段
break;
} return minlen != n+1;
}
有幾個地方解釋一下:第一,if(++count[pbead[i]] == 1 && ++cnt == n) 這個判斷語句看似很複雜。具體是這樣執行的,首先增加當前珠子顏色的出現次數。如果不是1,根據布林判斷的短路原則,++cnt 不會執行。如果是1,表明第一次出現,需要增加出現顏色的種數,因此執行++cnt。如果cnt增加到n表示找到了一段珠子,包含所有n種顏色。接著進入if語句,盡可能縮短。
第二,for(j = j + 1; j < n && --count[pbead[j]]; j++) 這句for迴圈語句。為什麼j 初始時要加1呢?可以這樣理解,假設之前已經找到了一段珠子,那麼j指向珠子的末端。現在又找到一段,這一段珠子的末端應該從j + 1開始計算,不應包含j。
下面給出一段測試程式及一些測試結果。
int main()
; int from, to;
int n = sizeof(bead)/sizeof(int);
if(beadproblem(bead, n, from, to))
{ int i;
for(i = from; i != to; i = (i+1)%n)
cout<
PHP 串聯珠子問題
1 串連珠子問題 類似於關鍵字搜尋 34 function shortest sub a,m 14 15 h 0 頭指標16 t 0 尾指標17 loop true 18 while loop else 2728 找到了所有顏色,縮減當前子串 29if sum m else 4243 更新最短子串資...
Git筆記(29) 搜尋
無論倉庫裡的 量有多少 經常需要查詢乙個函式是在 呼叫或者定義的,或者乙個方法的變更歷史 git 提供了兩個有用的工具來快速地從它的資料庫中瀏覽 和提交 git 提供了乙個grep命令,可以很方便地從提交歷史或者工作目錄中查詢乙個字串或者正規表示式 用 git 本身源 的查詢作為例子 預設情況下 g...
演算法筆記2 9補充
2.9 1 cin與cout 讀入多個變數,讀入了int 型變數n double型變數db char 型變數c char 型陣列str cin n db c str 如果想要讀入一整行,則需要使用getline函式,把一整行都讀入char型陣列str 100 中 char str 100 cin.g...