演算法面試
A. 演算法面試
我在《再談「我是怎麼招程序員」》中比較保守地說過,「問難的演算法題並沒有錯,錯的很多面試官只是在膚淺甚至錯誤地理解著面試演算法題的目的。」,今天,我想加強一下這個觀點——我反對純演算法題面試!(注意,我說的是純演算法題)圖片源Wikipedia(點擊圖片查看詞條)我再次引用我以前的一個觀點——能解演算法題並不意味著這個人就有能力就能在工作中解決問題,你可以想想,小學奧數題可能比這些題更難,但並不意味著那些奧數能手就能解決實際問題。好了,讓我們來看一個示例(這個示例是昨天在微博上的一個討論),這個題是——「找出無序數組中第2大的數」,幾乎所有的人都用了O(n)的演算法,我相信對於我們這些應試教育出來的人來說,不用排序用O(n)演算法是很正常的事,連我都不由自主地認為O(n)演算法是這個題的標准答案。我們太習慣於標准答案了,這是我國教育最悲哀的地方。(廣義的洗腦就是讓你的意識依賴於某個標准答案,然後通過給你標准答案讓你不會思考而控制你)功能性需求分析試想,如果我們在實際工作中得到這樣一個題 我們會怎麼做?我一定會分析這個需求,因為我害怕需求未來會改變,今天你叫我找一個第2大的數,明天你找我找一個第4大的數,後天叫我找一個第100大的數,我不搞死了。需求變化是很正常的事。分析完這個需求後,我會很自然地去寫找第K大數的演算法——難度一下子就增大了。很多人會以為找第K大的需求是一種「過早擴展」的思路,不是這樣的,我相信我們在實際編碼中寫過太多這樣的程序了,你一定不會設計出這樣的函數介面 —— Find2ndMaxNum(int* array, int len),就好像你不會設計出 DestroyBaghdad(); 這樣的介面,而是設計一個DestoryCity( City& ); 的介面,而把Baghdad當成參數傳進去!所以,你應該是聲明一個叫FindKthMaxNum(int* array, int len, int kth),把2當成參數傳進去。這是最基本的編程方法,用數學的話來說,叫代數!最簡單的需求分析方法就是把需求翻譯成函數名,然後看看是這個介面不是很二?!(註:不要糾結於FindMaxNum()或FindMinNum(),因為這兩個函數名的業務意義很清楚了,不像Find2ndMaxNum()那麼二)非功能性需求分析性能之類的東西從來都是非功能性需求,對於演算法題,我們太喜歡研究演算法題的空間和時間復雜度了。我們希望做到空間和時間雙豐收,這是演算法學術界的風格。所以,習慣於標准答案的我們已經失去思考的能力,只會機械地思考演算法之內的性能,而忽略了演算法之外的性能。如果題目是——「從無序數組中找到第K個最大的數」,那麼,我們一定會去思考用O(n)的線性演算法找出第K個數。事實上,也有線性演算法——STL中可以用nth_element求得類似的第n大的數,其利用快速排序的思想,從數組S中隨機找出一個元素X,把數組分為兩部分Sa和Sb。Sa中的元素大於等於X,Sb中元素小於X。這時有兩種情況:1)Sa中元素的個數小於k,則Sb中的第 k-|Sa|個元素即為第k大數;2) Sa中元素的個數大於等於k,則返回Sa中的第k大數。時間復雜度近似為O(n)。搞學術的nuts們到了這一步一定會歡呼勝利!但是他們哪裡能想得到性能的需求分析也是來源自業務的!我們一說性能,基本上是個人都會問,請求量有多大?如果我們的FindKthMaxNum()的請求量是m次,那麼你的這個每次都要O(n)復雜度的演算法得到的效果就是O(n*m),這一點,是書獃子式的學院派人永遠想不到的。因為應試教育讓我們不會從實際思考了。工程式的解法根據上面的需求分析,有軟體工程經驗的人的解法通常會這樣:1)把數組排序,從大到小。2)於是你要第k大的數,就直接訪問 array[k]。排序只需要一次,O(n*log(n)),然後,接下來的m次對FindKthMaxNum()的調用全是O(1)的,整體復雜度反而成了線性的。其實,上述的還不是工程式的最好的解法,因為,在業務中,那數組中的數據可能會是會變化的,所以,如果是用數組排序的話,有數據的改動會讓我重新排序,這個太耗性能了,如果實際情況中會有很多的插入或刪除操作,那麼可以考慮使用B+樹。工程式的解法有以下特點:1)很方便擴展,因為數據排好序了,你還可以方便地支持各種需求,如從第k1大到k2大的數據(那些學院派寫出來的代碼在拿到這個需求時又開始撓頭苦想了)2)規整的數據會簡化整體的演算法復雜度,從而整體性能會更好。(公欲善其事,必先利其器)3)代碼變得清晰,易懂,易維護!(學院派的和STL一樣的近似O(n)復雜度的演算法沒人敢動)爭論你可能會和我有以下爭論,如果程序員做這個演算法題用排序的方式,他一定不會像你想那麼多。是的,你說得對。但是我想說,很多時候,我們直覺地思考,恰恰是正確的路。因為「排序」這個思路符合人類大腦處理問題的方式,而使用學院派的方式是反大腦直覺的。反大腦直覺的,通常意味著晦澀難懂,維護成本上升。就是一道面試題,我就是想測試一下你的演算法技能,這也扯太多了。沒問題,不過,我們要清楚我們是在招什麼人?是一個只會寫演算法的人,還是一個會做軟體的人?這個只有你自己最清楚。這個演算法題太容易誘導到學院派的思路了。是的這道「找出第K大的數」,其實可以變換為更為業務一點的題目——「我要和別的商戶競價,我想排在所有競爭對手報價的第K名,請寫一個程序,我輸入K,和一個商品名,系統告訴我應該訂多少價?(商家的所有商品的報價在一數組中)」——業務分析,整體性能,演算法,數據結構,增加需求讓應聘者重構,這一個問題就全考了。你是不是在說演算法不重要,不用學?千萬別這樣理解我,搞得好像如果面試不面,我就可以不學。演算法很重要,演算法題能鍛煉我們的思維,而且也有很多實際用處。我這篇文章不是讓大家不要去學演算法,這是完全錯誤的,我是讓大家帶著業務問題去使用演算法。問你業務問題,一樣會問到演算法題上來。小結看過這上面的分析,我相信你明白我為什麼反對純演算法面試題了。原因就是純演算法的面試題根本不能反應一個程序的綜合素質!那麼,在面試中,我們應該要考量程序員的那些綜合素質呢?我以為有下面這些東西:會不會做需求分析?怎麼理解問題的?解決問題的思路是什麼?想法如何?會不會對基礎的演算法和數據結構靈活運用?另外,我們知道,對於軟體開發來說,在工程上,難是的下面是這些挑戰:軟體的維護成本遠遠大於軟體的開發成本。軟體的質量變得越來越重要,所以,測試工作也變得越來越重要。軟體的需求總是在變的,軟體的需求總是一點一點往上加的。程序中大量的代碼都是在處理一些錯誤的或是不正常的流程。所以,對於編程能力上,我們應該主要考量程序員的如下能力:設計是否滿足對需求的理解,並可以應對可能出現的需求變化。
B. 老生常談:面試演算法有必要嗎
首先,面試什麼東西不是被面試者決定的,而是面試者決定的。
其次,編程,本回質上是用計算機解決問題,而答經過多年業界總結出來的經典演算法,就是針對經典而典型問題的解決方案,學習這些演算法,除了能夠解決這些典型問題之外還能夠掌握解決問題的能力,從而觸類旁通。所以說,面試演算法是考察被面試者解決問題能力的一種方法。
第三,面試內容除了它能否起到考察作用之外,還要考慮成本問題。看一個被面試者能否做出一道演算法題,是一個成本很低的做法(甚至連電腦都不需要),這對於公司來說是可以接受的。
綜上所述,面試演算法有必要。
C. 程序員面試時都要考演算法嗎
看應聘什麼職位...我面試的時候一點演算法都沒有涉及到...
某些特定開發崗位確實需回要扎實的演算法基礎.比如根答雲存儲,大數據什麼的.但是像普通的程序開發崗位應該對演算法要求不大.
所以,我猜測:如果面試跟演算法不怎麼相關的職位考官還問演算法的問題時,應該是你前面的回答還不足以讓考官錄用你。考官在給你展示自己的機會.
D. 一道面試演算法題
這是典型的桶排序演算法,
假設有9個桶,每個桶里存放N個數字。桶應該是唯一的。
所以推出結論:
1。桶是唯一的(我們因此可以利用Hashtable的唯一性來做到);
2。桶內成員可以不排序,因此可以利用數組或者Vector來做到;
3。Hashtable需要主鍵key來唯一標識,正好數字1~9是不重復的,是唯一的;
3。把每個數值的第一位取出來,以第一位值做為key找到hashtable中的相應vector,再將vector.addElements(該數值);
4。完成;
具體做法:
1.生成桶,9個桶,每個桶以數字1~9做為主鍵命名
Hashtable table=new Hashtable();
for(int i=1;i<10;i++){
Vector vector=new Vector();
table.put(new String(i), vector);
}
2. 遍歷每個數字,將當前數字的第一位分解出來,辦法有很多種,比如除十法,這里介紹直接轉字元串再取第一位法:
假設你的要處理的數字們放在數組裡面int[] tmp;
for(int i=0;i<tmp.length;i++){
int num=tmp[i];
String str=new String(num);
char ch=str.charAt(0);
//壓入到桶里,先把想要的桶找到,利用主鍵
Vector vect=(Vector)table.get(""+ch);
//找到桶後再把數值壓到桶里
vect.addElements(new Integer(num));
}
//取出來的時候,有多種方法,一種是利用key取出Vector,再遍歷Vector,得到其中元素,元素的key為String, 內容為Integer
另一種方法是先遍歷hashtable再遍歷vector
同樣的應用還有給一幅被洗過的撲克牌進行升或降排棄,因此可以建13個桶(A~K),每個桶內的牌再按花色排序(相當於對Vector排序,也可以不用Vector而直接用數組或者ArrayList等等)
我看了你的修改提問,現回答如下:
即使不能使用java己經封裝好的Hashtable類,自己也可以很輕易地利用代碼編寫出類似於Hashtable的集合類,用來包容其它對象,並以主鍵key來唯一標識.
如果你不想這樣思考,那麼直接用數組來實現桶排序也很方便,外層數組長度是固定的,即1~9共9個數組元素 Elements e=new Elements[9]。
這九個數組元素不是數字,必須是你自定義的類。並用這個類形成鏈表結構
比如:
public class Element{
int data;//存數字
Element next=null;//下一個元素是誰
}
比如有數字 51,52,53 這三個數都是以5打頭,那麼他們應該放在一個桶裡面,即第五號桶,也就是外層數組的第個元素中。
if( 判斷該數字,是否應該放在5號桶){
Elements tmp=new Elements();
tmp.data=該數字;
Elements current=e[4];
if(current==null){current=tmp;}//如果該桶以前從未放過數字,則放進去的就是頭部,直接引用就行了,比如51應該放在頭部
else{//如果該桶以前己經放過數字,如51,己經放了,現在放52。52就應該做為51的next元素,而53就是52的next就行了
while(current!=null){current=current.next;}//遍歷,從而取到最後一個元素的引用
//取到最後一個元素後,current=tmp;即可,這樣就形成了鏈表結構
}
}
通過上述代表形成的結果是, 外層結構是9個元素組成的數組
每個數組元素是Elements類對象形成的鏈表結構,有頭有層通過next欄位串連起來。
如果要排序,只需要對每個鏈表內部進行排序就可以了
E. 面試和演算法心得 怎麼樣 知乎
考查要點:
對Web標準的理解
瀏覽器差異
CSS基本功:布局、盒模型、選擇器優先順序及使用等專
Javascript 基礎、屬JS面向對象實現原理、閉包機制、作用域
通常可以做一些小練習來判斷TA的水平,js 雖然很靈活,但是具體的實現方式能體現出一個人的全局觀,隨著代碼規模的增長,復雜度增加,如何合理劃分模塊實現功能和介面的能力比較重要。這里有一份前不久我出的試題,難度不算大
作者:馬驍
鏈接:http://www.hu.com/question/19568008/answer/12242523
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請註明出處。
F. java演算法面試題:排序都有哪幾種方法
一、冒泡排序
[java] view plain
package sort.bubble;
import java.util.Random;
/**
* 依次比較相鄰的兩個數,將小數放在前面,大數放在後面
* 冒泡排序,具有穩定性
* 時間復雜度為O(n^2)
* 不及堆排序,快速排序O(nlogn,底數為2)
* @author liangge
*
*/
public class Main {
public static void main(String[] args) {
Random ran = new Random();
int[] sort = new int[10];
for(int i = 0 ; i < 10 ; i++){
sort[i] = ran.nextInt(50);
}
System.out.print("排序前的數組為");
for(int i : sort){
System.out.print(i+" ");
}
buddleSort(sort);
System.out.println();
System.out.print("排序後的數組為");
for(int i : sort){
System.out.print(i+" ");
}
}
/**
* 冒泡排序
* @param sort
*/
private static void buddleSort(int[] sort){
for(int i=1;i<sort.length;i++){
for(int j=0;j<sort.length-i;j++){
if(sort[j]>sort[j+1]){
int temp = sort[j+1];
sort[j+1] = sort[j];
sort[j] = temp;
}
}
}
}
}
二、選擇排序
[java] view plain
package sort.select;
import java.util.Random;
/**
* 選擇排序
* 每一趟從待排序的數據元素中選出最小(或最大)的一個元素,
* 順序放在已排好序的數列的最後,直到全部待排序的數據元素排完。
* 選擇排序是不穩定的排序方法。
* @author liangge
*
*/
public class Main {
public static void main(String[] args) {
Random ran = new Random();
int[] sort = new int[10];
for (int i = 0; i < 10; i++) {
sort[i] = ran.nextInt(50);
}
System.out.print("排序前的數組為");
for (int i : sort) {
System.out.print(i + " ");
}
selectSort(sort);
System.out.println();
System.out.print("排序後的數組為");
for (int i : sort) {
System.out.print(i + " ");
}
}
/**
* 選擇排序
* @param sort
*/
private static void selectSort(int[] sort){
for(int i =0;i<sort.length-1;i++){
for(int j = i+1;j<sort.length;j++){
if(sort[j]<sort[i]){
int temp = sort[j];
sort[j] = sort[i];
sort[i] = temp;
}
}
}
}
}
三、快速排序
[java] view plain
package sort.quick;
/**
* 快速排序 通過一趟排序將要排序的數據分割成獨立的兩部分, 其中一部分的所有數據都比另外一部分的所有數據都要小,
* 然後再按此方法對這兩部分數據分別進行快速排序, 整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。
* @author liangge
*
*/
public class Main {
public static void main(String[] args) {
int[] sort = { 54, 31, 89, 33, 66, 12, 68, 20 };
System.out.print("排序前的數組為:");
for (int data : sort) {
System.out.print(data + " ");
}
System.out.println();
quickSort(sort, 0, sort.length - 1);
System.out.print("排序後的數組為:");
for (int data : sort) {
System.out.print(data + " ");
}
}
/**
* 快速排序
* @param sort 要排序的數組
* @param start 排序的開始座標
* @param end 排序的結束座標
*/
public static void quickSort(int[] sort, int start, int end) {
// 設置關鍵數據key為要排序數組的第一個元素,
// 即第一趟排序後,key右邊的數全部比key大,key左邊的數全部比key小
int key = sort[start];
// 設置數組左邊的索引,往右移動判斷比key大的數
int i = start;
// 設置數組右邊的索引,往左移動判斷比key小的數
int j = end;
// 如果左邊索引比右邊索引小,則還有數據沒有排序
while (i < j) {
while (sort[j] > key && j > start) {
j--;
}
while (sort[i] < key && i < end) {
i++;
}
if (i < j) {
int temp = sort[i];
sort[i] = sort[j];
sort[j] = temp;
}
}
// 如果左邊索引比右邊索引要大,說明第一次排序完成,將sort[j]與key對換,
// 即保持了key左邊的數比key小,key右邊的數比key大
if (i > j) {
int temp = sort[j];
sort[j] = sort[start];
sort[start] = temp;
}
//遞歸調用
if (j > start && j < end) {
quickSort(sort, start, j - 1);
quickSort(sort, j + 1, end);
}
}
}
[java] view plain
/**
* 快速排序
*
* @param a
* @param low
* @param high
* voidTest
*/
public static void kuaisuSort(int[] a, int low, int high)
{
if (low >= high)
{
return;
}
if ((high - low) == 1)
{
if (a[low] > a[high])
{
swap(a, low, high);
return;
}
}
int key = a[low];
int left = low + 1;
int right = high;
while (left < right)
{
while (left < right && left <= high)// 左邊向右
{
if (a[left] >= key)
{
break;
}
left++;
}
while (right >= left && right > low)
{
if (a[right] <= key)
{
break;
}
right--;
}
if (left < right)
{
swap(a, left, right);
}
}
swap(a, low, right);
kuaisuSort(a, low, right);
kuaisuSort(a, right + 1, high);
}
四、插入排序
[java] view plain
package sort.insert;
/**
* 直接插入排序
* 將一個數據插入到已經排好序的有序數據中,從而得到一個新的、個數加一的有序數據
* 演算法適用於少量數據的排序,時間復雜度為O(n^2)。是穩定的排序方法。
*/
import java.util.Random;
public class DirectMain {
public static void main(String[] args) {
Random ran = new Random();
int[] sort = new int[10];
for (int i = 0; i < 10; i++) {
sort[i] = ran.nextInt(50);
}
System.out.print("排序前的數組為");
for (int i : sort) {
System.out.print(i + " ");
}
directInsertSort(sort);
System.out.println();
System.out.print("排序後的數組為");
for (int i : sort) {
System.out.print(i + " ");
}
}
/**
* 直接插入排序
*
* @param sort
*/
private static void directInsertSort(int[] sort) {
for (int i = 1; i < sort.length; i++) {
int index = i - 1;
int temp = sort[i];
while (index >= 0 && sort[index] > temp) {
sort[index + 1] = sort[index];
index--;
}
sort[index + 1] = temp;
}
}
}
順便添加一份,差不多的
[java] view plain
public static void charuSort(int[] a)
{
int len = a.length;
for (int i = 1; i < len; i++)
{
int j;
int temp = a[i];
for (j = i; j > 0; j--)//遍歷i之前的數字
{
//如果之前的數字大於後面的數字,則把大的值賦到後面
if (a[j - 1] > temp)
{
a[j] = a[j - 1];
} else
{
break;
}
}
a[j] = temp;
}
}
把上面整合起來的一份寫法:
[java] view plain
/**
* 插入排序:
*
*/
public class InsertSort {
public void sort(int[] data) {
for (int i = 1; i < data.length; i++) {
for (int j = i; (j > 0) && (data[j] < data[j - 1]); j--) {
swap(data, j, j - 1);
}
}
}
private void swap(int[] data, int i, int j) {
int temp = data[i];
data[i] = data[j];
data[j] = temp;
}
}
五、順便貼個二分搜索法
[java] view plain
package search.binary;
public class Main {
public static void main(String[] args) {
int[] sort = {1,2,3,4,5,6,7,8,9,10};
int mask = binarySearch(sort,6);
System.out.println(mask);
}
/**
* 二分搜索法,返回座標,不存在返回-1
* @param sort
* @return
*/
private static int binarySearch(int[] sort,int data){
if(data<sort[0] || data>sort[sort.length-1]){
return -1;
}
int begin = 0;
int end = sort.length;
int mid = (begin+end)/2;
while(begin <= end){
mid = (begin+end)/2;
if(data > sort[mid]){
begin = mid + 1;
}else if(data < sort[mid]){
end = mid - 1;
}else{
return mid;
}
}
return -1;
}
}
G. 做圖像類演算法面試的時候會不會面試數學
我在《再談逗我是怎麼招程序員地》中比較保守地說過,逗問難的演算法題並沒有錯,錯的很多面試官只是在膚淺甚至錯誤地理解著面試演算法題的目的。地,今天,我想加強一下這個觀點——我反對純演算法題面試!(注意,我說的是純演算法題)圖片源Wikipedia(點擊圖片查看詞條)我再次引用我以前的一個觀點——能解演算法題並不意味著這個人就有能力就能在工作中解決問題,你可以想想,小學奧數題可能比這些題更難,但並不意味著那些奧數能手就能解決實際問題。好了,讓我們來看一個示例(這個示例是昨天在微博上的一個討論),這個題是——逗找出無序數組中第2大的數地,幾乎所有的人都用了O(n)的演算法,我相信對於我們這些應試教育出來的人來說,不用排序用O(n)演算法是很正常的事,連我都不由自主地認為O(n)演算法是這個題的標准答案。我們太習慣於標准答案了,這是我國教育最悲哀的地方。(廣義的洗腦就是讓你的意識依賴於某個標准答案,然後通過給你標准答案讓你不會思考而控制你)功能性需求分析試想,如果我們在實際工作中得到這樣一個題 我們會怎麼做看我一定會分析這個需求,因為我害怕需求未來會改變,今天你叫我找一個第2大的數,明天你找我找一個第4大的數,後天叫我找一個第100大的數,我不搞死了。需求變化是很正常的事。分析完這個需求後,我會很自然地去寫找第K大數的演算法——難度一下子就增大了。很多人會以為找第K大的需求是一種逗過早擴展地的思路,不是這樣的,我相信我們在實際編碼中寫過太多這樣的程序了,你一定不會設計出這樣的函數介面 —— Find2ndMaxNum(int* array, int len),就好像你不會設計出 DestroyBaghdad(); 這樣的介面,而是設計一個DestoryCity( City& ); 的介面,而把Baghdad當成參數傳進去!所以,你應該是聲明一個叫FindKthMaxNum(int* array, int len, int kth),把2當成參數傳進去。這是最基本的編程方法,用數學的話來說,叫代數!最簡單的需求分析方法就是把需求翻譯成函數名,然後看看是這個介面不是很二看!(註:不要糾結於FindMaxNum()或FindMinNum(),因為這兩個函數名的業務意義很清楚了,不像Find2ndMaxNum()那麼二)非功能性需求分析性能之類的東西從來都是非功能性需求,對於演算法題,我們太喜歡研究演算法題的空間和時間復雜度了。我們希望做到空間和時間雙豐收,這是演算法學術界的風格。所以,習慣於標准答案的我們已經失去思考的能力,只會機械地思考演算法之內的性能,而忽略了演算法之外的性能。如果題目是——逗從無序數組中找到第K個最大的數地,那麼,我們一定會去思考用O(n)的線性演算法找出第K個數。事實上,也有線性演算法——STL中可以用nth_element求得類似的第n大的數,其利用快速排序的思想,從數組S中隨機找出一個元素X,把數組分為兩部分Sa和Sb。Sa中的元素大於等於X,Sb中元素小於X。這時有兩種情況:1)Sa中元素的個數小於k,則Sb中的第 k-|Sa|個元素即為第k大數;2) Sa中元素的個數大於等於k,則返回Sa中的第k大數。時間復雜度近似為O(n)。搞學術的nuts們到了這一步一定會歡呼勝利!但是他們哪裡能想得到性能的需求分析也是來源自業務的!我們一說性能,基本上是個人都會問,請求量有多大看如果我們的FindKthMaxNum()的請求量是m次,那麼你的這個每次都要O(n)復雜度的演算法得到的效果就是O(n*m),這一點,是書獃子式的學院派人永遠想不到的。因為應試教育讓我們不會從實際思考了。工程式的解法根據上面的需求分析,有軟體工程經驗的人的解法通常會這樣:1)把數組排序,從大到小。2)於是你要第k大的數,就直接訪問 array[k]。排序只需要一次,O(n*log(n)),然後,接下來的m次對FindKthMaxNum()的調用全是O(1)的,整體復雜度反而成了線性的。其實,上述的還不是工程式的最好的解法,因為,在業務中,那數組中的數據可能會是會變化的,所以,如果是用數組排序的話,有數據的改動會讓我重新排序,這個太耗性能了,如果實際情況中會有很多的插入或刪除操作,那麼可以考慮使用B+樹。工程式的解法有以下特點:1)很方便擴展,因為數據排好序了,你還可以方便地支持各種需求,如從第k1大到k2大的數據(那些學院派寫出來的代碼在拿到這個需求時又開始撓頭苦想了)2)規整的數據會簡化整體的演算法復雜度,從而整體性能會更好。(公欲善其事,必先利其器)3)代碼變得清晰,易懂,易維護!(學院派的和STL一樣的近似O(n)復雜度的演算法沒人敢動)爭論你可能會和我有以下爭論,如果程序員做這個演算法題用排序的方式,他一定不會像你想那麼多。是的,你說得對。但是我想說,很多時候,我們直覺地思考,恰恰是正確的路。因為逗排序地這個思路符合人類大腦處理問題的方式,而使用學院派的方式是反大腦直覺的。反大腦直覺的,通常意味著晦澀難懂,維護成本上升。就是一道面試題,我就是想測試一下你的演算法技能,這也扯太多了。沒問題,不過,我們要清楚我們是在招什麼人看是一個只會寫演算法的人,還是一個會做軟體的人看這個只有你自己最清楚。這個演算法題太容易誘導到學院派的思路了。是的這道逗找出第K大的數地,其實可以變換為更為業務一點的題目——逗我要和別的商戶競價,我想排在所有競爭對手報價的第K名,請寫一個程序,我輸入K,和一個商品名,系統告訴我應該訂多少價看(商家的所有商品的報價在一數組中)地——業務分析,整體性能,演算法,數據結構,增加需求讓應聘者重構,這一個問題就全考了。你是不是在說演算法不重要,不用學看千萬別這樣理解我,搞得好像如果面試不面,我就可以不學。演算法很重要,演算法題能鍛煉我們的思維,而且也有很多實際用處。我這篇文章不是讓大家不要去學演算法,這是完全錯誤的,我是讓大家帶著業務問題去使用演算法。問你業務問題,一樣會問到演算法題上來。小結看過這上面的分析,我相信你明白我為什麼反對純演算法面試題了。原因就是純演算法的面試題根本不能反應一個程序的綜合素質!那麼,在面試中,我們應該要考量程序員的那些綜合素質呢看我以為有下面這些東西:會不會做需求分析看怎麼理解問題的看解決問題的思路是什麼看想法如何看會不會對基礎的演算法和數據結構靈活運用看另外,我們知道,對於軟體開發來說,在工程上,難是的下面是這些挑戰:軟體的維護成本遠遠大於軟體的開發成本。軟體的質量變得越來越重要,所以,測試工作也變得越來越重要。軟體的需求總是在變的,軟體的需求總是一點一點往上加的。程序中大量的代碼都是在處理一些錯誤的或是不正常的流程。所以,對於編程能力上,我們應該主要考量程序員的如下能力:設計是否滿足對需求的理解,並可以應對可能出現的需求變化。
H. 要面試演算法工程師,大神給點相關經驗啊
演算法是比較復雜又基礎的學科,每個學編程的人都會學習大量的演算法。而根據統計,以下這18個問題是面試中最容易遇到的,本文給出了一些基本答案,供演算法方向工程師或對此感興趣的程序員參考。
1)請簡單解釋演算法是什麼?
演算法是一個定義良好的計算過程,它將一些值作為輸入並產生相應的輸出值。簡單來說,它是將輸入轉換為輸出的一系列計算步驟。
2)解釋什麼是快速排序演算法?
快速排序演算法能夠快速排序列表或查詢。它基於分割交換排序的原則,這種類型的演算法佔用空間較小,它將待排序列表分為三個主要部分:
·小於Pivot的元素
·樞軸元素Pivot(選定的比較值)
·大於Pivot的元素
3)解釋演算法的時間復雜度?
演算法的時間復雜度表示程序運行完成所需的總時間,它通常用大O表示法來表示。
4)請問用於時間復雜度的符號類型是什麼?
用於時間復雜度的符號類型包括:
·Big Oh:它表示小於或等於目標多項式
·Big Omega:它表示大於或等於目標多項式
·Big Theta:它表示與目標多項式相等
·Little Oh:它表示小於目標多項式
·Little Omega:它表示大於目標多項式
5)解釋二分法檢索如何工作?
在二分法檢索中,我們先確定數組的中間位置,然後將要查找的值與數組中間位置的值進行比較,若小於數組中間值,則要查找的值應位於該中間值之前,依此類推,不斷縮小查找范圍,直至得到最終結果。
6)解釋是否可以使用二分法檢索鏈表?
由於隨機訪問在鏈表中是不可接受的,所以不可能到達O(1)時間的中間元素。因此,對於鏈表來說,二分法檢索是不可以的(對順序鏈表或排序後的鏈表是可以用的)。
7)解釋什麼是堆排序?
堆排序可以看成是選擇排序的改進,它可以定義為基於比較的排序演算法。它將其輸入劃分為未排序和排序的區域,通過不斷消除最小元素並將其移動到排序區域來收縮未排序區域。
8)說明什麼是Skip list?
Skip list數據結構化的方法,它允許演算法在符號表或字典中搜索、刪除和插入元素。在Skip list中,每個元素由一個節點表示。搜索函數返回與key相關的值的內容。插入操作將指定的鍵與新值相關聯,刪除操作可刪除指定的鍵。
9)解釋插入排序演算法的空間復雜度是多少?
插入排序是一種就地排序演算法,這意味著它不需要額外的或僅需要少量的存儲空間。對於插入排序,它只需要將單個列表元素存儲在初始數據的外側,從而使空間復雜度為O(1)。
10)解釋什麼是「哈希演算法」,它們用於什麼?
「哈希演算法」是一個哈希函數,它使用任意長度的字元串,並將其減少為唯一的固定長度字元串。它用於密碼有效性、消息和數據完整性以及許多其他加密系統。
11)解釋如何查找鏈表是否有循環?
要知道鏈表是否有循環,我們將採用兩個指針的方法。如果保留兩個指針,並且在處理兩個節點之後增加一個指針,並且在處理每個節點之後,遇到指針指向同一個節點的情況,這只有在鏈表有循環時才會發生。
12)解釋加密演算法的工作原理?
加密是將明文轉換為稱為「密文」的密碼格式的過程。要轉換文本,演算法使用一系列被稱為「鍵」的位來進行計算。密鑰越大,創建密文的潛在模式數越多。大多數加密演算法使用長度約為64到128位的固定輸入塊,而有些則使用流方法。
13)列出一些常用的加密演算法?
一些常用的加密演算法是:
·3-way
·Blowfish
·CAST
·CMEA
·GOST
·DES 和Triple DES
·IDEA
·LOKI等等
14)解釋一個演算法的最佳情況和最壞情況之間有什麼區別?
·最佳情況:演算法的最佳情況解釋為演算法執行最佳的數據排列。例如,我們進行二分法檢索,如果目標值位於正在搜索的數據中心,則這就是最佳情況,最佳情況時間復雜度為0。
·最差情況:給定演算法的最差輸入參考。例如快速排序,如果選擇關鍵值的子列表的最大或最小元素,則會導致最差情況出現,這將導致時間復雜度快速退化到O(n2)。
15)解釋什麼是基數排序演算法?
基數排序又稱「桶子法」,是通過比較數字將其分配到不同的「桶里」來排序元素的。它是線性排序演算法之一。
16)解釋什麼是遞歸演算法?
遞歸演算法是一個解決復雜問題的方法,將問題分解成較小的子問題,直到分解的足夠小,可以輕松解決問題為止。通常,它涉及一個調用自身的函數。
17)提到遞歸演算法的三個定律是什麼?
所有遞歸演算法必須遵循三個規律:
·遞歸演算法必須有一個基點
·遞歸演算法必須有一個趨向基點的狀態變化過程
·遞歸演算法必須自我調用
18)解釋什麼是冒泡排序演算法?
冒泡排序演算法也稱為下沉排序。在這種類型的排序中,要排序的列表的相鄰元素之間互相比較。如果它們按順序排列錯誤,將交換值並以正確的順序排列,直到最終結果「浮」出水面。
滿意記得採納哈
I. 面試演算法題一般給多少時間
主要是讓你用計算機就可以啊
J. Java面試筆試,數據結構和演算法考到什麼程度
你說的那個數據結構不一定考的。 Java面試就那麼點東西,各個公司也不一回樣。 答有的分筆試和機試。這些公司想看看實際面試人員的能力,節省了以後的時候。 筆試中,無非就是一些概念性的東西巴了。 比如:jsp是servlet嗎? servlet的生存周期;還有一些面向對象的知識。這些平常用心的話都沒問題,即使臨陣磨槍也行。 那麼機試就的要看你自己的能力了,對框架的屬性程度。還有就是在也不能常見的對數據 庫的CRUD也就是增刪改查操作。機試都好這口。 其實面試如果也沒筆試機試那麼就問幾道題的話,如果是技術人,幾道題下來就知道你的底子了,在問些邏輯上的也就知道要你還是不要你了。 在有你要對一些資料庫知識了解一些。 做java的 oracle 得達到掌握 sql server 了解就行 基本語法啥的就可以了 mysql 這個也得達到掌握 別的就不要會用到