# Hash Table# String# Greedy

d578 - 小涵的積木

🔗 前往 ZeroJudge 原題

題目描述

題目描述了小涵有許多組相同的積木,每塊積木上都有文字。她不小心弄丟了一塊積木,現在給定剩下的積木上的文字,要求找出丟失的那塊積木上的文字。輸入包含積木組數 n 和積木組合數 m,以及剩餘積木上的文字。

解題思路

這題的核心思想是利用模數運算來找出丟失的積木。如果 n * m 比較小,可以直接使用 map 統計每個字串出現的次數,然後找出出現次數不是 m 的倍數的字串,這個字串就是丟失的積木。如果 n * m 比較大,則使用一個二維陣列 buffer 統計每個字元在每個位置出現的次數,然後找出第一個出現次數不是 m 的倍數的字元,並將其組合成丟失的積木字串。

複雜度分析

  • 時間複雜度: O(nmk) 其中 k 是字串的平均長度。在 n*m 較小的情況下,map 的操作佔主導,時間複雜度接近 O(nmk)。在 n*m 較大的情況下,遍歷 buffer 陣列的時間複雜度為 O(1000*128),可以視為常數時間。
  • 空間複雜度: O(nm) 或 O(1000128)。在 n*m 較小的情況下,map 的空間複雜度為 O(nm)。在 n*m 較大的情況下,buffer 陣列的空間複雜度為 O(1000128),可以視為常數空間。

程式碼

#include <iostream>
#include <map>
using namespace std;
long long int n,m,type2=1001*129,buffer[1001][129];
int main(){
	cin.tie(0); ios::sync_with_stdio(false);
	while(cin >> n >> m){
		if(n==0&&m==0)break;
		long long int k=n*m-1;
		string a;
		if(type2>=k){
			map <string,int> s;
			map <string,int> ::iterator i;
			getline(cin,a);
			while(k--){
				getline(cin,a);
				++s[a];
			}
			for(i=s.begin();i!=s.end();++i){
				if(i->second%m){
					cout << i->first << "\n";
					break; 
				}
			}
		}
		else{
			getline(cin,a);
			string rt;
			while(k--){
				getline(cin,a);
				int al=a.length();
				for(int i=0;i<al;++i){
					++buffer[i][a[i]];
				}
			}
			for(int i=0;i<1000;++i){
				int s=0;
				for(int j=0;j<128;++j){
					if(buffer[i][j]%m){
						rt+=(char)j;
						s=1;
						break;	
					}
				}
				if(s==0)break;
			}
			cout << rt << "\n";
		}
	}
}

Discussion