問題描述
有n個人他們之間認識與否用鄰接矩陣表示(1表示認識,0表示不認識),並a認識b並不意味著b認識a,也就意味著是個有向圖
如果乙個人是名人,他必須滿足兩個條件,乙個是他不認識任何人,另乙個是所有人必須都認識他。
分析問題
首先,我們從中可以分析出,名人必定最多只有1個,因為如果有兩個名人ab,那麼你說他們倆是否認識呢,考慮a是名人,那麼b必定認識a,得出b必定不是名人,與b是名人的條件衝突,因為名人不認識任何人
解決問題
用乙個陣列儲存所有沒檢查的人的編號,遍歷陣列中的兩個人i,j。
如果i認識j,則i必定不是名人,刪除i
如果i不認識j,則j必定不是名人,刪除j
最終會只剩下乙個人,我們檢查一下這個人是否是名人即可,如果是,返回這個人,如果不是,那麼這n個人中並無名人
編寫**
//初始化陣列編號
for(int i=a;i
a[i]=i;
}while(n>1)
else
}//最終檢查a[0]是否為名人
for(int i=0;i
//不考慮自身,並且檢查他是否認識某個人,如果認識,那麼不是名人
//檢查其他人是否認識他,如果有人不認識他,那麼他也不是名人
if((a[0]!=i)&&(known[a[0]][i]||!known[i][a[0]]))
return -1;
}return a[0];
演算法優化
以上演算法需要用乙個陣列來儲存沒有檢查的人的編號,意味著空間複雜度為o(n),是否可以讓空間複雜度降低到o(1)呢,答案是肯定的,解決方法就是用一頭掃的方法
這裡我們就不需要用乙個陣列來儲存沒有檢查的人的編號了,我們直接對n個人進行遍歷
遍歷的方式是定義兩個下標,用兩個下標一起往後掃,對於兩個下標i,j而言,保證[o~i-1]沒有名人,並且[i~j-1]也沒有名人,如果i認識j,那麼i不是名人,刪掉i,刪除的方法就是i=j,j++,如果i不認識j,刪除j,刪除的方式是j++,遍歷的時候讓j一直加就可以了。
int i=0;j=1;
for(;j
if(known[a[i]a[j]])
i=j;
}for(j=0;j
if((i!=j)&&(known[i][j]||!known[j][i]))
return -1;
}return i;
演算法優化2
除了一頭掃的優化方式,也可以用兩頭掃的方式優化以上的演算法
保證0~i-1沒有名人,並且j+1~n也沒有名人
如果i認識j,刪除i
如果i不認識j,刪除j
i=0;j=n-1;
while(i
if(known[i][j])
else
}for(j=0;j
if(i!=j&&(known[i][j]||!known[j][i]))
return -1
}return i;
面試題 賽馬問題
據說,這是google的面試題。面試題目如下 一共有25匹馬,有乙個賽場,賽場有5個賽道,就是說最多同時可以有5匹馬一起比賽。假設每匹馬都跑的很穩定,不用任何其他工具,只通過馬與馬之間的比賽,試問,最少得比多少場才能知道跑得最快的5匹馬?不能使用撞大運的演算法 很明顯這是乙個演算法題,網上有很多貼子...
SQL問題(面試題)
面試完後在本地mysql資料庫中重現了該問題 資料表stuscore資訊如下 1 計算每個人的總成績,並且排名 要求顯示字段 學號 姓名 總成績 select stuid as 學號,name as 姓名,sum score as 總成績 from stuscore group by stuid o...
解決小公尺公司的面試題
題目 一副從1到n的牌,每次從牌堆頂取一張放桌子上,再取一張放牌堆底,直到手上沒牌,最後桌子上的牌是從1到n有序,設計程式,輸入n,輸出牌堆的順序陣列。c 放入桌子上陣列 public static int v new int 0 public static int m new int 0 stat...