字节--手串
字節–手串
文章目錄
- 字節--手串
- 一、題目描述
- 二、分析
- 三、代碼
一、題目描述
作為一個手串藝人,有金主向你訂購了一條包含n個雜色串珠的手串——每個串珠要么無色,要么涂了若干種顏色。為了使手串的色彩看起來不那么單調,金主要求,手串上的任意一種顏色(不包含無色),在任意連續的m個串珠里至多出現一次(注意這里手串是一個環形)。手串上的顏色一共有c種。現在按順時針序告訴你n個串珠的手串上,每個串珠用所包含的顏色分別有哪些。請你判斷該手串上有多少種顏色不符合要求。即詢問有多少種顏色在任意連續m個串珠中出現了至少兩次。
- 輸入描述:
- 輸出描述:
二、分析
這道題同樣不能暴力模擬求解,還需要技巧。
- 1. 首先輸入了珠子個數n 要求連續珠串不能重復的個數是m,串珠顏色有c種
- 2. 這道題也是需要設計一個良好的數據結構才能求解
- 3. 我們可以把這個串珠和顏色設計為一個二維矩陣,行向量是每一個串珠,列向量是串珠顏色,列向量總數為c,如果在i行j列上的這個數對應的串珠的位置沒有這個顏色那么置0
- 簡言之,就是將每個串珠的顏色都擴充為一樣的c種,原本擁有的就為1,沒有的就為0,那么就可以設計為一個0-1表示的二維矩陣,如下圖中所示
- 4.其次,再研究研究輸出結果,是要求不滿足m個串珠連續的顏色總和,那么這個問題就轉變為了我對每種顏色檢查是否符合結果
- 5. 針對每一種顏色檢查的是否有連續個m個串珠針對同一種顏色同時出現了兩個1(針對矩陣而言)
- 因為需要針對同一種顏色從第一個串珠(第一行)檢查到最后一個串珠(最后一行),那么整體的遍歷結束就會結束于n + m(因為到達最后一行相鄰的串珠是第一行開始到m-1)
- 6. 依次檢查每一列是否符合要求即可得到最后的總數
三、代碼
#include<iostream> #include<vector> #include<unordered_set>using namespace std; int main() {int n;int m;int c;cin>>n>>m>>c;//構建二維數組//行代表珠串數//列代表顏色//0代表該珠串沒有出現某顏色,1代表出現某顏色vector<vector<int>> matrix(n,vector<int>(c));for (int i = 0; i < n; i++) {int total ;cin>>total;for (int j = 0; j < total; j++) {int k ;cin>>k;matrix[i][k - 1] = 1;}}//構造結果數組//如果對應顏色處為1代表該顏色違規//用數組保存的原因是可能出現一個顏色多次違規的情況vector<int> result(c);//遍歷所有顏色,也可以理解為遍歷數組只不過是遍歷每一顏色列,縱向遍歷for (int i = 0; i < c; i++) {//標記某一顏色上一次出現的位置int lastIndex = -1;//end為珠串判斷結束的位置,等于n + m - 1是因為珠串是環形int end = n + m - 1;for (int j = 0; j < end; j++) {//防止越界int row = j % n;//如果等于1就代表該位置出現i號顏色,那么就需要和上一次出現i號顏色進行判斷if(matrix[row][i] == 1) {//如果上一次出現該顏色的位置為-1,就代表該顏色是第一次出現//進行標記if (lastIndex == -1) lastIndex = j;else {//反之就代表該顏色是多次出現,就需要判斷其上一次出現的位置和//當前出現的位置之間的距離是否超過m//超過m就代表該顏色違規,進行標記if (j - lastIndex < m) result[i] = 1;//反之就代表該顏色多次出現的距離超過m,就更新lastIndex即可else {lastIndex = j;}}}}}int sum = 0;for (int i = 0; i < c; i++) {if (result[i] == 1) sum++;}cout<<sum<<endl;return 0; } 超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結