面試筆試

最近需要找工作了,特將遇到的面試筆試題總結在這裏,後續會陸續添加。。希望對大家也有幫助

1:不能被繼承只能被實例化3次

分析:不能被繼承,只需要將該類的構造函設置爲私有的就可以了,那麼如何得到它呢,只能通過靜態函數得到了(不能創建對象,自然不能用對象調用該函數)。。當然如果用指針,必須得有析構,析構函數當然可以不爲私有(但是爲了對稱,一般寫成私有)。。。(爲了防止賦值和複製,複製構造函數及賦值操作符都要爲私有)。此外代碼中也可以用引用類型。

代碼:

#include<iostream> 
using namespace std; 
class Singleton {
	public:
		static int count;  
		static Singleton* GetInstance() { 
			if(count>0){    
				count--;    
				return new Singleton();   
			}else{    
				return NULL;   
			}  
		}  
		static void DeleteInstance(Singleton *PInstance){   
			if(PInstance!=NULL){    
				delete PInstance;    
				PInstance=NULL;   
			}else{    
				cout<<"is NULL"<<endl;   
			}  
		}  
		static void Getcount(int n){   
			count=n;  
		} 
	private:  
		Singleton()  
		{   
			cout<<"Singleton is constructed"<<endl;  
		}  
		~Singleton()  
		{   
			cout<<"Singleton is deconstructed"<<endl;  
		} 
};  
int Singleton::count=0; 
int main() {  
	Singleton::Getcount(3);  
	Singleton *p1=Singleton::GetInstance();     
	Singleton *p2=Singleton::GetInstance();  
	Singleton *p3=Singleton::GetInstance();  
	Singleton *p4=Singleton::GetInstance();  
	if(p3==NULL) 
	{   
		cout<<"p3 NULL"<<endl;  
	}  
	else{   
		cout<<"p3 not NULL"<<endl;  
	}  
	if(p4==NULL)  
	{   
		cout<<"p4 NULL"<<endl;  
	}  
	else  
	{   
		cout<<"p4 not NULL"<<endl;  
	}  
	Singleton::DeleteInstance(p1);  
	Singleton::DeleteInstance(p2);  
	Singleton::DeleteInstance(p3);  
	Singleton::DeleteInstance(p4);  
	return 0; 
}


2: 以下代碼調用了幾次構照函數和析構函數

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

class Test
{
public:
	Test()
	{
		cout<<"Test 被構建!"<<endl;
	}
	~Test()
	{
		cout<<"Test 被析構!"<<endl;
	}

};

int main(int argc,char *argv[])
{
	
	vector<Test> (*vec)=new vector<Test>();
	Test a1,a2;

	vec->push_back(a1);

	vec->push_back(a2);


	delete vec;
	return 0;
}
分析:
答案是調用了兩次構造函數,卻調用了5次析構函數,


如果將最後delete vec;去掉 則只調用3次析構函數。爲什麼會調用了5次構造函數呢,原因是vector容器的自增長,當將a1 push到容器中時,會複製a1,調用複製構造函數,此時當push a2的時候,容器預分配的容量(capacity)爲1,因此需要重新找一塊更大的內存空間來存放兩個元素,並且將第一個元素複製過來,再撤銷第一個元素,依次會調用依次複製構造函數,並且立刻析構,再調用複製構造函數a2.如下:

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

class Test
{
public:
	Test()
	{
		cout<<"Test 被構建!"<<endl;
	}
	Test(const Test &a){
		*this = a;
		cout << "複製構照函數被調用!" << endl;
	}
	~Test()
	{
		cout<<"Test 被析構!"<<endl;
	}

};

int main(int argc,char *argv[])
{
	
	vector<Test> (*vec)=new vector<Test>();
	Test a1,a2;

	vec->push_back(a1);

	vec->push_back(a2);


	delete vec;
	return 0;
}



第一次複製構照函數被調用,是push a1發生複製,第二次複製構照函數被調用和析構是重新分配內存是複製a1並撤銷原有的a1,第三次複製構照函數被調用是push a2.

vector是在內存中連續存儲,中的函數reserve()用來設置容器預分配容量的大小,resize()是設置容器實際的大小,size()是返回容器實際大小,capacity()是得到容器預分配容器大小。當前實際容器大小爲n,也等於預分配的大小時,當調用push_back()會將容器預分配的容量變成n+n/2,此時會複製n個元素,並加上push新的元素,共有n+1個實際元素。


3:函數調用過程與函數返回值過程

函數返回過程:函數返回值如果是函數中普通的變量---假設爲類類型,那麼普通變量的範圍只能在函數內部,因此此時會產生一個全局的臨時變量(如果是類類型則調用複製構造函數並析構該局部普通變量),,然後會調用賦值操作符將臨時的全局變量賦值我們的變量,並且賦值操作符調用後會析構臨時的全局變量。。

函數調用過程:將函數的下一個地址入棧,並將函數形參從右到左依次入棧,(不會產生臨時全局構造函數),,,函數返回過程會逆序出棧。。

代碼:

#include<iostream>
using namespace std;
template <class T>
class Test
{
public:
	Test(T _t){t=_t;}
	Test(){}
	~Test(){cout<<"_析構函數調用了!"<<endl;}
	Test(const Test<T>& _test){ 
		cout << "複製構照函數被調用!" << endl;
		t=_test.t;
	}
	Test& operator=(const Test<T>& _test)
	{
	   cout<<"賦值操作符函數被調用!"<<endl;
	   t=_test.t;
	   return *this;
	}
	// 友元需要重寫模板type
	template<class Type> friend Test<Type> operator+(const Test<Type>&,const Test<Type>&);

	void print(Test<T> test);
	T t;
};

template <class T>
Test<T> operator+(const Test<T>&obj1,const Test<T> &obj2)
{
	Test<T> obj;
	obj.t=obj1.t+obj2.t;
	return obj;   // 會產生一個臨時的全局變量temp,會調用複製構造函數將obj賦給temp,然後析構obj,————函數返回過程---產生全局臨時變量
}

template <class T>
void Test<T>::print(Test<T> test){    
	cout << test.t << endl;
}

int main(int argc,char** argv)
{
	Test<int> test_1(2);
    Test<int> test_2(3);
	Test<int> test_3;
	test_3 = test_1+test_2;   // 然後將全局變量temp賦值給test_3 賦值操作符結束 臨時變量temp被析構 ——函數返回過程 
	test_3.print(test_2);   // 模擬函數調用過程,將函數的下一個地址入棧,並將display的形參從右到左依次入棧,(直接將test_2複製,不會產生臨時全局構造函數)
	char c;
    cin>>c;
	return 0;
}
結果:

第一次調用複製構照函數是由於operator+中返回obj時會產生一個全局的臨時變量,調用複製構照函數,並將局部變量obj析構掉,然後調用賦值操作符將全局臨時變量賦值給給test_3,並析構掉全局臨時變量( 第二次析構函數調用),然後print實參傳形參調用複製構照函數。。

注意當一個類還沒有定義完全時,不能使用該類類型定義該類的成員,但可以用指針或其引用,,也可以聲明(而不是定義)使用該類型作爲形參類型或者返回類型的函數。如例子中的print函數

此外注意的是友元函數,可以將非成員函數,類及成員函數聲明爲友元,當將非成員函數和類聲明爲友元時,我們無需提前聲明,友元會將該非成員函數及類引入到外圍作用域,,而將成員函數設爲友元,則需要事先定義包含該友元函數的類A,然後定義所需要的類B,最終定義類A中被當做友元的成員函數。

4(阿里面試題):約瑟夫問題

n個人(編號爲0,1,...,n-1)圍成一個圈子,從0號開始依次報數,每數到第m個人,這個人就得自殺,之後從下個人開始繼續報數,直到所有人都死亡爲止。問最後一個死的人的編號(其實看到別人都死了之後最後剩下的人可以選擇不自殺……)

分析:這是典型的約瑟夫問題,可以用單循環鏈表來進行求解,但此時時間複雜度過高,會達到O(n*m)的時間複雜度——這是我在面試的時候所說的方法。這裏我們給出一種時間複雜度爲O(n),空間複雜度爲O(1)的解法——這裏是我主要想講解的方法。當然也有兩種O(lgn)的解法,但是這兩種解法我還沒有看,參看http://maskray.me/blog/2013-08-27-josephus-problem-two-log-n-solutions

爲了討論方便,先把問題稍微改變一下,並不影響原意:

問題描述:n個人(編號0~(n-1)),從0開始報數,報到(m-1)的退出,剩下的人繼續從0開始報數。求勝利者的編號。

我們知道第一個人(編號一定是(m-1 mod n)出列之後,剩下的n-1個人組成了一個新的約瑟夫環(以編號爲k=m mod n的人開始):

k k+1 k+2 ... n-2,n-1,0,1,2,... k-2

並且從k開始報0

我們把他們的編號做一下轉換:

k --> 0

k+1 --> 1

k+2 --> 2

...

...

k-2 --> n-2

變換後就完完全全成爲了(n-1)個人報數的子問題,假如我們知道這個子問題的解:例如x是最終的勝利者,那麼根據上面這個表把這個x變回去不剛好就是n個人情況的解嗎?!!變回去的公式很簡單,相信大家都可以推出來:x'=(x+k) mod n

如何知道(n-1)個人報數的問題的解?對,只要知道(n-2)個人的解就行了。(n-2)個人的解呢?當然是先求(n-3)的情況 ---- 這顯然就是一個倒推問題!好了,思路出來了,下面寫遞推公式

f表示i個人玩遊戲報m退出最後勝利者的編號,最後的結果自然是f[n]

遞推公式

f[1]=0;

f=(f+m) mod i; (i>1

有了這個公式,我們要做的就是從1-n順序算出f的數值,最後結果是f[n]。因爲實際生活中編號總是從1開始,我們輸出f[n]+1

由於是逐級遞推,不需要保存每個f,程序也是異常簡單:

#include <iostream>
using namespace std;
const int m = 3;
int main()
{
    int n, f = 0;
    cin >> n;
    for (int i = 1; i <= n; i++) f = (f + m) % i;
    cout << f + 1 << endl;
	return 0;
}

參考:http://baike.baidu.com/view/213217.htm


5.1(阿里面試題):請在一個小時內實現atoi的c函數

以下是我的代碼:當時處理溢出的時候用了long long,但是MAXINT+1,沒有轉換成long long

#define MAXINT (int)0x7fffffff
int strToInt(const string &str){
	if(str == "")return 0;
	int i = 0;
	bool isMinus = false;
	if(str[i]=='+' || str[i] == '-'){
		if(str[i] == '-')
			isMinus = true;
		i++;
	}
	long long int result = 0;
	for(; i < str.size(); i++)
	{
		if(str[i] < '0' || str[i] > '9') return 0;
		result = result * 10 + str[i] - '0';
		if(result > (long long)(MAXINT)+1)
			return 0;
	}
	result = isMinus ? -result : result;
	
	return result == (long long)(MAXINT)+1 ? 0 : result;

}

或者更直接的,因爲unsigned int的範圍爲0~0xffffffff = 4294967295,而int的範圍爲-2147483648(0x80000000)~2147483647(0x7fffffff)  所以我們可以直接將result 先設置爲unsigned int,  這樣就不會超過0x7fffffff了。MAX+1也不需要進行轉換了。代碼如下:

#define MAX (unsigned int)0x7fffffff

int strToInt2(const string &str){
	if(str == "")return 0;
	int i = 0;
	bool isMinus = false;
	if(str[i]=='+' || str[i] == '-'){
		if(str[i] == '-')
			isMinus = true;
		i++;
	}
	unsigned int result = 0;
	for(; i < str.size(); i++)
	{
		if(str[i] < '0' || str[i] > '9') return 0;
		result = result * 10 + str[i] - '0';
		if(result > MAX+1)
			return 0;
	}
	result = isMinus ? -result : result;
	
	return result == MAX+1 ? 0 : result;

}


5.2 實現strcpy函數(注意:strcpy基於dst已經有足夠的空間容納src了,否則會出現運行上的錯誤)

代碼如下:要考慮從後往前還是從前往後進行copy

// strcpy函數中源代碼調用的是memcpy(dst, src, count) 其中count = strlen(src)+1  === strncpy
//  其中strcpy基於dst已有足夠空間容納src的長度,否則運行出錯
//其實現等同於下面的代碼  其中已經確保dst有足夠空間容納src了
char *my_mecpy(const char *src, char *dst){      // 最好用void* 然後再在代碼中強制將void*轉換成char*
	if(NULL == dst || NULL == src) return dst;

	int len = strlen(src)+1;     // 注意strcpy拷貝的空間包括\0 字符所以長度爲strlen(str)+1
	char *ret = dst;
	if(src + len <= dst || dst <= src){   // 這兩種情況從前往後進行copy
		while(len--){
			*dst++ = *src++;
		}
	}
	else{                         // 反之從後往前進行copy
		dst = dst + len - 1;
		src = dst + len - 1;
		while(len--){
			*dst-- = *src--;
		}
	}
	return ret;
}


注意memcpy不考慮複製的重疊部分,memmove才考慮重疊部分,所以上面的是memmove

參考文獻:1:http://blog.csdn.net/xinpo66/article/details/8551788

2:http://blog.csdn.net/gpengtao/article/details/7464061/


6:

int *myIntArray()
{
    int buffer[6] = {0};
    for (int i = 1; i <= sizeof(buffer); i++)
    {
        buffer[i-1] = i;
    }
    return buffer;
}


int *myInt()
{
	int i = 10;
    int *buffer = &i;
    return buffer;
}
以上兩段函數調用的時候,會返回什麼樣的結果?

cout << myIntArray()[0] << endl;

cout << * myInt() << endl;

其中myIntArray()沒有使用new或者malloc分配內存,所有buffer數組的內存區域在棧區隨着char*myIntArray()的結束,棧區內存釋放,字符數組也就不存在了,所以會產生也指針,輸出結果未知. 而myInt會返回正常結果10(爲什麼??按常理int i的值也被釋放了啊,爲什麼還能返回正確值。 可能是編譯器的原因,,如果是類類型 則也會出現野指針)

class SolutionTest{
public:
	SolutionTest():x(10){
		cout << "構照函數被調用" << endl;}
	SolutionTest(const SolutionTest &st){
		this->x = st.x;
		cout << "賦值構照函數被調用" << endl;
	}
	SolutionTest& operator=(const SolutionTest& st){
		this->x = st.x;
		cout << "賦值操作符被調用" << endl;
		return *this;
	}
	~SolutionTest(){
		cout << "析構函數被調用" << endl;
	}
	int x;


};


SolutionTest* getPtr(){
	SolutionTest st;
	SolutionTest *pst = &st;
	return pst;
}
此時調用SolutionTest *st = getPtr(); cout << st->x << endl; 也會是野指針

7(360研發)在寫一個函數,根據兩文件的絕對路徑算出相對路徑。如 a="/qihoo/app/a/b/c/d/new.c",b="/qihoo/app/1/2/test.c',那麼b相對於a的相對路徑是"../../../../1/2/test.c"

分析:相對路徑就是從a的文件開始,../表示到a文件的上一層,所以相對路徑爲a和b字符串不相同的字符開始a後面/個數就有多少個../作爲b的前綴。而後半部分爲b開始不相同字符所對應的上一個/開始到字符串b的結尾。。

代碼:

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

void getRelativeString(const string &a, const string &b){
	int i = 0, j = 0;
	while(i < a.size() && j < b.size()){     // 不相同的字符位置
		if(a[i] == b[j]){
			i++;
			j++;
		}else break;
	}
	// 計算a在不同點後面有多少個/  
	int remain_a = 0;
	while( (i = a.find_first_of('/', i)) != string::npos){  // 找到a後面還有多少'/' 結果即爲a有多少個/ 那麼b的前綴就有多少個../  即爲pre_str
		remain_a ++;
		i++;
	}
	string pre_str = "";
	for(int k = 0; k < remain_a; k++){
		pre_str += "../";
	}

	// 計算b的後半部分
	//cout << remain_a << endl;
	while(j < b.size() && b[j] != '/')j++;       // 找到b不相同的地方到上一個/的單詞  結果就爲pre_str 加上從該單詞開始的b後面的字符串。
	string str = b.substr(0, j);
	str = b.substr(str.find_last_of('/')+1);

	// 得到結果
	str = pre_str + str;
	cout << str << endl;

}

int main(){
	string a = "/qihoo/app/a/b/c/d/new.c";
	string b = "/qihoo/app/1/2/test.c";
	getRelativeString(a, b);
	return 0;
}


8:已知rand7()可以產生1~7的7個數(均勻概率),利用rand7() 產 生 rand10() 1~10(均勻概率)。(騰訊筆試題)

分析:剛開始我是用(int)rand7()/7.0*10,但是後來發現不對,這樣生成到1-10不是均勻概率。可以這樣7*(rand7()-1)+rand7()這樣會均勻的生成1-49之間數的均勻概率,這裏減1的目的就是爲了能產生1-7的數字,此時我們讓1-40之間的數值模10且加1就能均勻的生成1-10之間的數字了(1-10,11-20.21-30,31-40),而對於大於40以上的數字它重新生成

代碼:

int rand10()
{
    int n=49;
    while(n>40){
        n=7*(rand7()-1)+rand7();
    }
    return n%10+1;
}
變形:給定能隨機生成整數 1 到 5 的函數,寫出能隨機生成整數 1 到 7 的函數。
同理:如下代碼,這樣21以下的元素對7取模再加1就能生成1-7之間的數字了。

int rand7()
{
    int n=25;
    while(n>21){
        n=5*(rand5()-1)+rand5();
    }
    return (n%7)+1;
}

9:找最長重複字串

分析:以下代碼時間複雜度爲O(N^3)

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

int main(){
	string s;
	cin >> s;

	int len = 0;
	for(int i = 0; i < s.size(); i++){    // 字串位置
		for(int j = s.size()-i; j >= i; j--){   // 字串長度
			string str = s.substr(i, j);
			int front = s.find(str);      // 在s中從前往後找字串
			int back = s.rfind(str);      // 在s中從後往前找字串
			if(front != back && j > len){
				len = j;
			}
		}
	}
	cout << len << endl;
	return 0;
	
}

10:(美團模擬筆試題)求出一個給定的字符串如str = “   I   love you   ”;返回“I love you”;去掉首尾空格字符,字符串中間出現多個空格字符時,只保留1個。

代碼:

char *eraseEmptySpace(char *str){
	char *result = new char[256];   // 不知道大小是不是要固定。
	int i = 0, t = 0;
	while(str[i] != '\0'){
		if(str[i] != ' ' || str[i+1] != ' '){   // 當前爲空不爲空或者當前不爲空下一個爲空 則加入  // 否則++
			result[t++]= str[i];
		}
		i++;    
	}
	result[t]='\0';        //
	if(result[0] == ' ')result = result+1;
	return result;
}

int main(){
	char *str = "    I   love   you    ";
	char *result = eraseEmptySpace(str);
	cout << result << endl;

	return 0;
}

11:N二維座標系中的點對中求最近點對的距離

分析:/*採用分治法,最主要的是計算一個點在S1中,一個點在S2中的最近距離,方法是我們先得到S1和S2內部最小的最近距離dis,然後在
以mid爲中心的dis距離內的點放入新數組T中,然後對T按照Y座標軸排序,我們知道要想滿足條件須要當前點最多與其後面的7個點比較就可以了
*/

代碼:closePair.h

#define N 1000    // 最大節點數
#define maxInt 0x7fffffff
struct Point{
	int x;
	int y;
};
closePair.cpp

Point V[N], T[N];


inline bool sortByX(const Point &p1, const Point &p2){
	return p1.x < p2.x;
}


inline bool sortByY(const Point &p1, const Point &p2){
	return p1.y < p2.y;
}


double calc_dist(const Point &p1, const Point &p2){
	return sqrt((p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y)+0.0);
}


// 二分 遞歸的求解s到t之間的
double merge(int s, int t){
	if(s >= t) return maxInt;
	double dis = maxInt;
	int mid = (s+t)>>1;
	dis = min(dis, min(merge(s, mid), merge(mid+1,t)));  // 計算兩邊的最近點對距離

	//將兩邊距離中心在dis距離以內的點作爲候選並按照Y座標進行排序
	int len = 0;
	for(int i = s; i <= t; i++){
		if(V[i].x >= V[mid].x - dis && V[i].x <= V[mid].x+dis){
			T[len++] = V[i];
		}
	}
	sort(T, T+len, sortByY);
	for(int i = 0; i < len; i++){  // 當前這個點按y軸排序好的最多8個點(dis*(2*dis)領域內)
		for(int j = i+1; j < min(i+7, len) && T[j].y - T[i].y <= dis; j++){
			dis = min(dis, calc_dist(T[i], T[j]));
		}
	}
	return dis;

}

// 主函數

double closestPair(){
	int n;
	cin >> n;
	for(int i = 0; i < n; i++)
		cin >> V[i].x >> V[i].y;
	sort(V, V+n, sortByX);    // 按x軸進行排序

	return merge(0, n-1);     // 歸併

}
參考文獻:1:編程之美

2:http://noalgo.info/793.html


12:隨機洗牌算法

思路:關鍵是從後往前進行遍歷 這樣某張牌被選中放在任何一個位置的概率都是1/n

/*
隨機的洗牌算法:從後往前進行更新某張排被選中放在第i個位置的概率爲1/n
*/

int arr[101];
int n;

void start(){
	for(int i = 0; i < n; i++)
		arr[i] = i;
	for(int i = n-1; i >= 0; i--){   // 這裏採用逆序遍歷
		int index = rand()%(i+1);
		swap(arr[index], arr[i]);
	}
}
參考文獻:

1:http://sumnous.github.io/blog/2014/05/13/random-pick-function/  隨機數生成函數面試題

2:等概率隨機排列數組 http://www.gocalf.com/blog/shuffle-algo.html


13: 實現stack,並由操作push,pop,top,getMin即取最小值

分析:此題用鏈表,關鍵是在head上進行操作,取最小值最佳情況也能達到O(1)時間內完成

myStack.h

#ifndef MYSTACK_H
#define MYSTACK_H

struct Node{
	Node *next;
	int value;
	Node(int v):value(v), next(NULL){}
};


class myStack{
public:
	myStack():head(NULL){}
	void push(int v);
	void pop();
	int top();
	int getMin();
private:
	Node *head;
};


#endif

myStack.cpp

/*
實現棧,並模擬取出棧中的最小值;; 我們用鏈表來實現,head作爲棧的頭部
*/

void myStack::push(int v){
	Node *p =  new Node(v);
	if(head == NULL) head = p;
	else{
		p->next = head;
		head = p;
	}
}

// O(1)時間內刪除 
void myStack::pop(){
	if(head == NULL) return;
	Node *p = head;
	head = head->next;
	delete p;
}

//  也是O(1)
int myStack::top(){
	if(head == NULL) return 0;
	return head->value;
}

// 另外一種思路是在myStack中保存一個最小值,在push的時候動態更新它,
// 此時取得最小值就是O(1)了,但是刪除的時候就需要重新遍歷stack更新最小值(O(N)) 但是很多情況下取的最小值就是O(1)了

int myStack::getMin(){
	if(head == NULL) return -1;
	Node *p = head;
	int result = head->value;
	while(p != NULL){
		result = min(result, p->value);
		p = p->next;
	}
	return result;

}


14: 已知n是個正整數,輸出1/n的小數點後k位數字,如n = 5, k=3,則輸出爲200,; 如n=10, k=3,則輸出010

分析:此題我用的思路直接得到1/n 爲double類型,但是面試官說這個有可能精度不夠,其實這是一個模擬人工算1/n的過程

代碼1:

// 取出1/n 小數點後面k位數字  給定的n是個正整數

void getKMod(int n, int k){
	double t = 1/(n+0.0);    // 浮點型可能不夠準確
	int tmp = 0;
	while(k--){
		tmp = t*10;
		cout << tmp;
		t = t*10 - tmp;
	}
	cout << endl;
}

模擬人工算的工程:

void getKMod2(int n, int k){    // 最爲準確的解法,模仿1/n的過程
	int t = 10;
	while(k--){
		cout << t/n;
		t = (t%n)*10;
	}
	cout << endl;
}


15:fibonacci數列變形,每步只能走一個臺階或者兩個臺階,其中第5,8,13臺階不能走,問走到第20的臺階方法數有多少種
方法一:迭代 f(n)= f(n-1)+f(n-2) 這樣當n = 5, 8, 13的時候f(5)=f(8)=f(13)=0
方法二:分別對1~4; 6~7;9~12;14~20計算fibonacci數列,然後進行相乘即可爲3*1*3*13 = 117


16:有A和B兩個數組,如果A中有100個硬幣,30個向上,現在有兩種操作,一:直接將A中硬幣移到B中,二:移到B中進行翻轉,問什麼樣的操作才能是A與B中的硬幣朝上數目相等
    假設從A中選擇x個元素,有y個向上,此時將x移動到B中並翻轉,此時30-y = x-y 導出x=30  因此只需要將30個硬幣全部翻轉移到B數組中即可


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章