1. 程式人生 > >計算最小跨度(阿里筆試題)

計算最小跨度(阿里筆試題)

題目:給定兩個由數字0-9組成的字元陣列,如“2345”, “4436”,從這兩個陣列分別取數,生成新陣列。
比如生成:44234365,生成方式如下圖所示,每個陣列取數放入新陣列的時候,是按照下標從小到大取得。
對於字元陣列,定義跨度值:K(c),為數字c最大下標和最小下標之差。比如數字44234365每個數字的K(c)定義如下:
num   2  3 4 5 6  
K(c)   0  2 4 0 0  
請找到一種取合成方式,使得K(c)的總和最小(比如,上例總和為6,但總和並非最小)。打印出最小的K(c) 之和。

利用二叉樹的方法解題:

1.首先通過遞迴的方式建立二叉樹

2.遍歷所有葉子節點並將資料放入容器vector

3.遍歷容器計算跨度Kc最小值

程式碼如下:

#include <iostream>
#include <string>
#include <vector>
using namespace std;

/*給定兩個由數字0-9組成的字元陣列,如“2345”, “4436”,從這兩個陣列分別取數,生成新陣列。
比如生成:44234365,生成方式如下圖所示,每個陣列取數放入新陣列的時候,是按照下標從小到大取得。
對於字元陣列,定義跨度值:K(c),為數字c最大下標和最小下標之差。比如數字44234365每個數字的K(c)定義如下:
num   2  3 4 5 6  
K(c)   0  2 4 0 0  
請找到一種取合成方式,使得K(c)的總和最小(比如,上例總和為6,但總和並非最小)。打印出最小的K(c) 之和。


請完成下面這個函式,實現題目要求的功能*/
/*當然,你也可以不按照下面這個模板來作答,完全按照自己的想法來 ^-^ */

/******************************開始寫程式碼******************************/

struct Binarytree{                    //定義二叉樹結構體
	string data;
	Binarytree *leftchild;
	Binarytree *rightchild;
};

Binarytree *left_Binarytree(string& first, string& second);      //宣告左子樹和右子樹
Binarytree *right_Binarytree(string& first, string& second);
string data = "";
size_t i = 0, j = 0;

Binarytree *left_Binarytree(string& first,string& second)        //建立左子樹
{
	string data1;
	Binarytree *T;
	if (i >= first.size() )      //判定是否為葉節點,終止遞歸併刪除非單個插入的first/second子串,如:first2345全插入後直接在後面新增的second4436
	{
		T = NULL; 
		data.erase(data.end() - second.size() + j-1, data.end()-1);
	}
	else if (j >= second.size() )
	{
		T = NULL;
	}
	else{
		data1 = first[i++];                                     //每深入一層,插入一個字元
		data = data + data1;
		if (i >= first.size())                                //當first字串完全插入時,在後面插入second剩下的字串
		{
			data = data + second.substr(j, second.size() - j);
		}
		T = new Binarytree;
		T->data = data;
		   //cout << T->data << endl;
		T->leftchild = left_Binarytree(first, second);          //遞迴呼叫
		T->rightchild = right_Binarytree(first, second);
		data.erase(data.end() - 1);                             //遞迴返回後刪除最後一個字元,深度i減一
		i--;
	}
	return T;
}


Binarytree *right_Binarytree(string& first,string& second)      //建立右子樹
{
	string data2;
	Binarytree *T;
	if (i >= first.size() )    
	{
		T = NULL; 
	}
	else if (j >= second.size() )        //判定是否為葉節點,終止遞歸併刪除非單個插入的first/second子串,如:first2345全插入後直接在後面新增的second4436
	{
		T = NULL; 
		data.erase(data.end() - first.size() + i-1, data.end()-1);
	}
	else{
		data2 = second[j++];
		data = data + data2;
		if (j >= second.size() )                            //當first字串完全插入時,在後面插入second剩下的字串       
		{
			data = data + first.substr(i, first.size() - i);
		}
		T = new Binarytree;
		T->data = data;
		  //cout << T->data << endl;
		T->leftchild = left_Binarytree(first, second);         //遞迴呼叫
		T->rightchild = right_Binarytree(first, second);
		data.erase(data.end() - 1);                            //遞迴返回後刪除最後一個字元,深度j減一
		j--;
	}

	return T;
}


vector<string> lea;
void leaf(Binarytree* tree)                                    //將所有葉子的值存入一個容器
{
	if (tree->leftchild == NULL&&tree->rightchild==NULL)
	{
		lea.push_back(tree->data);		
	}
	else {
		leaf(tree->leftchild);
		leaf(tree->rightchild);
	}
}

int calcMinKLenSum(string& first, string& second){             //計算跨度Kc的最小值
	Binarytree *left_tree=left_Binarytree(first, second);
	Binarytree *right_tree=right_Binarytree(first, second);
	leaf(left_tree);
	leaf(right_tree);
	int k;
	int min, kc;

	//遍歷葉子容器
	//vector<string>::iterator it = lea.begin();
	//for (; it != lea.end(); ++it)
	//{
	//	cout << (*it) << endl;
	//}

	for (k = 0,kc = 0; k <= 9; k++)                           //以第一個葉子的跨度Kc為初始值
	{
		if (lea[i].find(48 + k) != string::npos)
			kc += lea[i].find_last_of(48 + k) - lea[i].find_first_of(48 + k);
		min = kc;
	}

	for (size_t i = 0; i < lea.size();i++)                   //計算所有葉子的跨度Kc,取最小值min
	{
		for ( k = 0,kc = 0; k <= 9; k++)
		{
			if (lea[i].find(48 + k) != string::npos)
				kc += lea[i].find_last_of(48 + k) - lea[i].find_first_of(48 + k);
		}
		min = min>kc ? kc : min;
		//cout << min << endl;
	}	
	return min;
}

/******************************結束寫程式碼******************************/

int main() {
	string first, second;
	cin >> first >> second;
	int sum = calcMinKLenSum(first, second);
	cout << sum << endl;
	system("pause");
	return 0;
}

執行結果:

相關推薦

計算跨度阿里試題

題目:給定兩個由數字0-9組成的字元陣列,如“2345”, “4436”,從這兩個陣列分別取數,生成新陣列。比如生成:44234365,生成方式如下圖所示,每個陣列取數放入新陣列的時候,是按照下標從小到大取得。對於字元陣列,定義跨度值:K(c),為數字c最大下標和最小下標之差

試題8:旋轉陣列的Leetcode-153,154

題目:把一個數組最開始的若干元素搬到陣列的末尾,稱為陣列的旋轉。 輸入一個遞增陣列的一個旋轉,輸出其最小值。假設這個遞增陣列中沒有重複元素 例如陣列{3,4,5,1,2}是{1,2,3,4,5}的一個旋轉,最小值是1。 一. O(N)解法 最直觀的解

數組合並問題阿里試題,動態規劃

咋一看到本題,首先想到的是窮舉法,後來跑測試資料時,程式執行效率很慢,無法滿足本題要求。後來想到本題是屬於典型的動態規劃問題,找出計算公式,將大問題轉化為小問題求解,本題的邊界情況比較多,找出全部的邊界情況是難點。問題分析:(1)求出公式:當陣列長度n=1時,f(a1,b1)

旋轉陣列的數字無重複數字

class Solution { public: int minNumberInRotateArray(vector<int> rotateArray) { if(rotateArray.size()==1) {

AOJ2249 短路+花費雙權值

擴展 最小 col 滿足 fill 最短 題解 return queue 寫題解之前先罵一下這道題 xxx給數據範圍點數<1e4,邊數<2e4,結果我開2e4和3e4都RE,然後找問題一個多小時,最後我開了1e5和2e5,題面太能唬人了吧!?真是sb題面 ---

計算器 貝殼試題

描述 假設有這樣一個計算器,該計算器只有兩個按鈕,按下第一個按鈕能使顯示數值減少1,按下第二個按鈕能使顯示數值乘以2,當前顯示數值為N,那麼至少要按多少次按鈕才能使顯示數值變成M? 輸入 輸

單詞查詢公司試題

題目:單詞查詢 分析:題目限制了字母在詞典中只可以上下左右相鄰,那就意味著不能左上、右上、左下、右下、那就 比起八個方向的就更加簡單。具體實現就深搜唄~具體細節在程式碼的註釋 測試樣例: 5 5 3 hello help high p a b h m f h e

POJ 3164 樹形圖 朱劉演算法

Command Network Time Limit: 1000MS Memory Limit: 131072K Total Submissions: 20151 Accepted: 5792 Description After a l

BZOJ1797: [Ahoi2009]Mincut 洛谷P4126

最小割 Tarjan 結論題。。。 跑一遍最小割,對殘量網路進行縮點,使得剩下的邊都是滿流邊。 一條邊屬於最小割的並集當這條邊兩個端點所在的聯通塊不同。 一條邊屬於最小割的交集當這條邊兩個端點所在的聯通塊分別與源點和匯點相同。 下面給出口胡: 如果這條邊的兩個

JS 求一組陣列中的大值,不包括0

<body> <script type="text/javascript"> var arr=[]; do{ var num=prompt("請輸入一個整數:") if(num!=0){

白話經典算法系列之九 從歸併排序到數列的逆序數對微軟試題

首先來看看原題   微軟2010年筆試題 在一個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱為一個逆序數對。一個排列中逆序的總數就稱為這個排列的逆序數。如{2,4,3,1}中,2和1,4和3,4和1,3和1是逆序數對,因此整個陣列的逆序數對個數為

隨筆-尋找旋轉排序陣列中的有重複元素

題目: 假設按照升序排序的陣列在預先未知的某個點上進行了旋轉。 ( 例如,陣列 [0,1,2,4,5,6,7] 可能變為 [4,5,6,7,0,1,2] )。 請找出其中最小的元素。 注意陣列中可能存在重複的元素。 示例 1: 輸入: [1,3,5] 輸出: 1

隨筆-尋找旋轉排序陣列中的無重複數字

題目: 假設按照升序排序的陣列在預先未知的某個點上進行了旋轉。 ( 例如,陣列 [0,1,2,4,5,6,7] 可能變為 [4,5,6,7,0,1,2] )。 請找出其中最小的元素。 你可以假設陣列中不存在重複元素。 示例 1: 輸入: [3,4,5,1,2] 輸

7進位制字串轉為10進位制的int型別數字H3C試題

【2011年華三通訊應屆生筆試題】題目:請寫一段將7進位制轉為10進位制的正整數的函式。  【思路】在Java API中有相關的函式,Integer.parsint(String str,int ra

vc編譯exe的體積優化附編譯器引數

人們都說vc做出的東西可以小點,現在你開啟vc編譯一個Hello World出來!點屬性看下,咦!我沒走眼吧,就一Hello World就160kb真是要人命啊!  呵呵!上面的情況是筆者所遭遇的情況.不過後來了解vc可以通過設定引數來自定義編譯方式.為什麼檔案那麼大!主要是編譯器加入了很多沒必要的程式碼

旋轉陣列的數字改造二分法

題目:把一個數組最開始的若干個元素搬到陣列的末尾,我們稱之為陣列的旋轉。輸入一個遞增排序的陣列的一個旋轉,輸出旋轉陣列的最小元素。例如陣列{3,4,5,1,2}為{1,2,3,4,5}的一個旋轉,該陣列的最小值為1。 思路:這兒題目說了陣列是有序的,為了提升效率,可以用二分查詢去做,題目上也說了用二分查詢去

練習4-10 找出20 point(s)

練習4-10 找出最小值 (20 point(s)) 本題要求編寫程式,找出給定一系列整數中的最小值。 輸入格式: 輸入在一行中首先給出一個正整數n,之後是n個整數,其間以空格分隔。 輸出格式: 在一行中按照“min = 最小值”的格式輸出n個整數中的最小值。 輸入樣例:

LeetCode -- Triangle 路徑求 動態規劃問題

Given a triangle, find the minimum path sum from top to bottom.  Each step you may move to adjacent numbers on the row below. For example, given the foll

樹形圖劉朱演算法記錄

演算法步驟: 1、建立最短邊集(有向邊), 注意除去自環(自己連向自己) in[v] 記錄最小權值,pre[v] 記錄邊的起點 例子: 邊1 A->B 權:5 邊2 C->B 權:3 則 in[B]=3 pre[B]=C

043_字典序問題best cow line

  poj 3617   從一個字串s中頭部或者尾部取同一個字元,加到字串T中,要求字串T的字典序最小。   對s和s的逆序s'進行比較。如果一樣再對下一對進行比較,保證較小的字母較早被訪問。   題