http://community.csdn.net/Expert/topic/5603/5603029.xml?temp=.7464868
我覺得題目應該不是太難吧,如下:
請把一個整形數組中重複的數字去掉。例如:
1, 2, 0, 2, -1, 999, 3, 999, 88
答案應該是:
1, 2, 0, -1, 999, 3, 88
我說有兩種方案,一種費時間,一種費空間,先說費時間的方案:
從第一個開始逐個與後面的比較,如發現相同,則把該元素標記為array[0]的值。然後再迴圈一次,移動元素,將重複的濾掉。
代碼如下:
int array[] = {1, 2, 0, 2, -1, 999, 3, 999, 88};
//先標記重複的元素
int len = sizeof(array) / sizeof(array[0]) + 1;
for(int i = 0; i < len; i++)
{
//如果已被標為array[0]的值,直接跳過
if(i != 0 && array[i] == array[0])
continue;
for(int j = i + 1; j < len; j++)
{
if(array[j] == array[i])
array[j] = array[0];
}
}
//重複資料刪除的元素
i = 0;
int j = 1;
for (; j < len; j++)
{
if(array[j] != array[0])
{
//下面兩句的作用只是在剛開始如果沒有重複資料時,不需要進行拷貝,
i++;
if(i != j)
//進行移動拷貝
array[i] = array[j];
}
}
while(i < len)
array[i++] = 0;
他說問題出在這個for迴圈裡,因為比如:
1, 2, 0, 2, -1, 999, 3, 999, 88,在for迴圈過程中,變為了1, 2, 0, -1, -1, 999, 3, 999, 88,也就是說-1沒有被清掉。我說沒有清掉但會被後面的元素覆蓋,而且在最後的while迴圈裡,會將i到len之間的所有資料清掉。他不作解釋,說要我好好想想,我想再說的時候,他說這個我就不再我和爭了。他這樣說的話,我覺得自己也沒有說下去的必要。我說還有一種費空間的方法,他說今天就到這裡,覺得我和他們要求的有差距。然後就say goodbye。
我覺得這個到底在拷貝後清不清這個元素,可以這樣考慮:
1、如果重複資料較多,比如90%都是重複的,那最後一個清除的while迴圈無疑相當於多了一個O(n)的時間,在拷貝後立馬清除,就可以去掉這個while,節省時間。
2、但如果重複的較少,比如只有10%,而且這個不是整型,是一個很大的對象,那也應該考慮清除這個操作的時間,所以應該盡量減少清除操作。在拷貝之後立馬清除肯定清除操作會比不清除的操作次數多。
所以這個到底是不是立即清除不是一概而論,也需要分情況。
我覺得這個演算法的時間複雜度比較高吧,為O(n*(n-1)/2) + O(n) = O(n^2),但他好像不是強調這個。
另外,如果考慮時間不考慮空間的話,我覺得可以用一個輔助數組t,先對array進行排序,但是對t進行操作,不改變array,用快速排序或堆等的時間複雜度是nlogn,或者用箱子排序,這個時間在n很大的時候明顯小於n^2,但n很大的時候,又得多申請n*4位元組作為t,所以空間可能增加得很大,所以我把它用代碼錶示。他也沒有聽我說這些。
我覺得應該還有更好的辦法吧,但他說我做得不對的地方,我覺得有點冤,誠然我覺得我們需要考慮這些細小的問題,但我覺得也需要在分情況的情況下,我的也不一定完全是錯誤的。而且我覺得面試的時候應該也不能根據這個直接否定,連商量解決的機會都沒有,也許是對方沒有理解清楚呢。不過可能微軟畢竟是微軟。而且我是一個外派過去面試的,難道就應該這樣對待?呵呵,不解了。
還需要解釋一下的是,代碼裡int len = sizeof(array) / sizeof(array[0]) + 1;我忘了寫/ sizeof(array[0]) ,可能也給他造成不好的印象吧。
大家還是幫我分析分析,是不是這裡有什麼嚴重的失誤呢?謝謝各位仁兄,大師