PAT做題過程中的一些方法技巧總結

1.格式化輸出整數

例子:

7766 - 6677 = 1089
9810 - 0189 = 9621
9621 - 1269 = 8352
8532 - 2358 = 6174

 printf("%04d - %04d = %04d\n",max,min,n);不滿足的前面補0。用%04d即可。%04d就是不足4位數前面補0的意思。

比用cout輸出要方便:

void print(int n){
//    if(n>0&&n<10)
//        cout<<"000"<<n;
//    else if(n>=10&&n<100)
//        cout<<"00"<<n;
//    else if(n>=100&&n<1000)
//        cout<<"0"<<n;
//    else
//        cout<<n;
}

2.四捨五入

 int c=(int)((b-a)/100+0.5);//1.2+0.5==>1,   1.5+0.5==>2

3.加速cin,cout

在輸入輸出很大時可以加上這兩句:

ios::sync_with_stdio(false);

cin.tie(flase);

注1:endl開銷很大,可用‘\n’代替

注2:在pat中,輸出一行空行,用printf("\n");會報格式錯誤,而cout<<"\n"就沒事,很奇怪,先記在這。

4.字符串分割

4.1 用scanf(只能輸入字符串的時候)

例如:01:01:06:01

scanf("%d:%d:%d:%d", &data[i].month, &data[i].day, &data[i].hour, &data[i].minute);

4.2 用string類

涉及到string類的兩個函數find和substr: 

string本身沒有提供切割的方法,但可以使用stl提供的封裝進行實現或者通過c函數strtok()函數實現。
1、find函數 
原型:size_t find ( const string& str, size_t pos = 0 ) const; 
功能:查找子字符串第一次出現的位置。 
參數說明:str爲子字符串,pos爲初始查找位置。 
返回值:找到的話返回第一次出現的位置,否則返回string::npos

2、substr函數 
原型:string substr ( size_t pos = 0, size_t n = npos ) const; 
功能:獲得子字符串。 
參數說明:pos爲起始位置(默認爲0),n爲結束位置(默認爲npos) 
返回值:子字符串 

5.讀取字符串含空格或換行等

雖然可以使用 cin 和 >> 運算符來輸入字符串,但它可能會導致一些需要注意的問題。
當 cin 讀取數據時,它會傳遞並忽略任何前導白色空格字符(空格、製表符或換行符)。一旦它接觸到第一個非空格字符即開始閱讀,當它讀取到下一個空白字符時,它將停止讀取。以下面的語句爲例:

cin >> namel;

可以輸入 "Mark" 或 "Twain",但不能輸入 "Mark Twain",因爲 cin 不能輸入包含嵌入空格的字符串。

爲了解決這個問題,可以使用一個叫做 getline 的 C++ 函數。此函數可讀取整行,包括前導和嵌入的空格,並將其存儲在字符串對象中。
getline 函數如下所示:

 在<string>中的getline函數有四種重載形式:

istream& getline (istream&  is, string& str, char delim);
istream& getline (istream&& is, string& str, char delim);
istream& getline (istream&  is, string& str);

istream& getline (istream&& is, string& str);
讀取的istream是作爲參數is傳進函數的。讀取的字符串保存在string類型的str中。

函數的變量:

is    :表示一個輸入流,例如 cin。

str   :string類型的引用,用來存儲輸入流中的流信息。

delim :char類型的變量,所設置的截斷字符;在不自定義設置的情況下,遇到’\n’,則終止輸入。

有用實例:

while(getline(cin,line))

(注意:這裏默認回車符停止讀入,按Ctrl+Z(Windows)(Ctrl+D(Linux))或鍵入EOF(參考MSDN)回車即可退出循環。)

6.計算兩個時間的間隔

例如:起:01:01:06:01  終:01:01:08:03 間隔:122分鐘,若是跨天跨月跨年,再去計算會十分麻煩,此時就可以找一個基準參照時間

例如00:00:00到dd:hh:mm,統統轉化爲分鐘來計算,data[i].time = data[i].day * 24 * 60 + data[i].hour * 60 + data[i].minute;

兩個時間都轉爲相對00:00:00的時間間隔後再相減,就是最後兩者的時間間隔。

7.由二叉樹的先序和中序得到後序,或者構造一顆二叉樹

void postorder(int inL,int inR,int perL,int perR){
	if(inL>inR)//perL>perR也行
		return;
	int root=per[perL],k=0;
	while(k<inR&&in[k]!=root)
		k++;
	int leftnum=k-inL;
	postorder(inL,k-1,perL+1,perL+leftnum);//左子樹遞歸(中序跟k的位置直接有關,先序跟k無直接關係,而是由中序k-inL得到左子樹所含結點數,再間接可得位置)
	postorder(k+1,inR,perL+leftnum+1,perR);//右子樹遞歸(同理)
	post.push_back(root);//打印或放入後序隊列
}
void postorder(int root,int start,int end){//先序提供根結點信息root,左右子樹大小的信息由中序的start和end提供
	if(start>end)
		return;
	int k=0;
	while(k<end&&per[root]!=in[k])//找到中序的根結點位置
		k++;
	postorder(root+1,start,k-1);
	postorder(root+1+k-start,k+1,end);//先序是根左右的結構,其右子樹的根結點的位置必須先知道左子樹大小,而左子樹的大小有必須得根據中序得到
	post.push_back(per[root]);//打印或放入後序隊列
}

構造二叉樹寫法:

Node *create(int postL,int postR,int inL,int inR){
	if(postL>postR)//相等時也成立
		return NULL;
	Node *root=new Node;
	root->data=post[postR];
	int k;
	for(k=inL;k<=inR;++k){//找到中序數組中左右子樹的分割結點
		if(in[k]==post[postR])
			break;
	}
	int numLeft=k-inL;//左子樹的結點個數
	root->lchild=create(postL,postL+numLeft-1,inL,k-1);
	root->rchild=create(postL+numLeft,postR-1,k+1,inR);
	return root;
}

 一般取閉區間

postorder(0,0,n-1);

 

發佈了13 篇原創文章 · 獲贊 30 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章