面試排序演算法
❶ 最好的排序演算法是什麼演算法呀
什麼是最好?最快算是最好嗎?
目前就所有的內部排序法中,公認的使用廣泛的,是快速排序法,平均時間為 kn*lnn ,其中n為待排序序列中記錄的個數,k為某個常數。
❷ 排序演算法是怎樣的
一、背景介紹
在計算機科學與數學中,排序演算法(Sorting algorithm)是一種能將一串資料依照特定排序方式進行排列的一種演算法。
最常用到的排序方式是數字順序以及字典順序。
有效的排序演算法在一些演算法(例如搜尋演算法與合並演算法)中是重要的, 如此這些演算法才能得到正確解答。
排序演算法也用在處理文字資料以及產生人類可讀的輸出結果。
基本上,排序演算法的輸出必須遵守下列兩個原則:
1、輸出結果為遞增序列(遞增是針對所需的排序順序而言);
2、輸出結果是原輸入的一種排列、或是重組;
雖然排序演算法是一個簡單的問題,但是從計算機科學發展以來,在此問題上已經有大量的研究。 更多的新演算法仍在不斷的被發明。
二、知識剖析
查找和排序演算法是演算法的入門知識,其經典思想可以用於很多演算法當中。因為其實現代碼較短,應用較常見。 所以在面試中經常會問到排序演算法及其相關的問題。但萬變不離其宗,只要熟悉了思想,靈活運用也不是難事。
一般在面試中最常考的是快速排序和冒泡排序,並且經常有面試官要求現場寫出這兩種排序的代碼。對這兩種排序的代碼一定要信手拈來才行。除此之外,還有插入排序、冒泡排序、堆排序、基數排序、桶排序等。
三、常見的幾種演算法:
冒泡演算法、選擇排序、插入排序、希爾排序、歸並排序、快速排序
演算法的特點:
1、有限性:一個演算法必須保證執行有限步之後結束。
2、確切性: 一個演算法的每一步驟必須有確切的定義。
3、輸入:一個演算法有零個或多個輸入,以刻畫運算對象的初始情況,所謂零個輸入是指演算法本身給定了初始條件。
4、輸出:一個演算法有一個或多個輸出。沒有輸出的演算法毫無意義。
5、可行性:演算法中執行的任何計算步驟都是可以被分解為基本的可執行的操作步,即每個計算步都可以在有限時間內完成(也稱之為有效性)。
❸ 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;
}
}
❹ 大公司筆試面試有哪些經典演算法題目
1、二維數組中的查找
具體例題:如果一個數字序列逆置之後跟原序列是一樣的就稱這樣的數字序列為迴文序列。例如:{1, 2, 1}, {15, 78, 78, 15} , {112} 是迴文序列, {1, 2, 2}, {15, 78, 87, 51} ,{112, 2, 11} 不是迴文序列。現在給出一個數字序列,允許使用一種轉換操作:選擇任意兩個相鄰的數,然後從序列移除這兩個數,並用這兩個數字的和插入到這兩個數之前的位置(只插入一個和)。現在對於所給序列要求出最少需要多少次操作可以將其變成迴文序列?
❺ 排序演算法有哪些
1.插入排序—直接插入排序(Straight Insertion Sort)
2. 插入排序—希爾排序(Shell`s Sort)
3. 選擇排序—簡單選擇排序(Simple Selection Sort)
4. 選擇排序—堆排序(Heap Sort)
5. 交換排序—冒泡排序(Bubble Sort)
6. 交換排序—快速排序(Quick Sort)
7. 歸並排序(Merge Sort)
8. 桶排序/基數排序(Radix Sort)
❻ 面試經典數據結構和演算法匯總
如果說數據結構是骨架,那麼演算法就是靈魂。沒了骨架,靈魂沒有實體寄託;沒了靈魂,骨架也是個空殼。兩者相輔相成,缺一不可,在開發中起到了砥柱中流的作用。
現在我對各種數據結構和演算法做一總結,對比一下它們的效率
1.數據結構篇
1. 如果讓你手寫個棧和隊列,你還會寫嗎?
2. 開發了那麼多項目,你能自己手寫個健壯的鏈表出來嗎?
3. 下次面試若再被問到二叉樹,希望你能對答如流!
4. 面試還在被紅-黑樹虐?看完這篇輕松搞定面試官 !
2.排序演算法篇
1. 幾個經典的基礎排序演算法,你還記得嗎?
2. 手把手教你學會希爾排序,很簡單!
3. 快速排序演算法到底有多快?
4. 五分鍾教你學會歸並排序
5. 簡單說下二叉樹排序
6. 學會堆排序只需要幾分鍾
7. 圖,這個玩意兒竟然還可以用來排序!
掌握了這些經典的數據結構和演算法,面試啥的基本上沒什麼問題了,特別是對於那些應屆生來說。接下來再總結一下不同數據結構和演算法的效率問題,做一下對比,這也是面試官經常問的問題。
數據結構常用操作效率對比:
常用排序演算法效率的對比:
關於經典的數據結構和演算法,就總結到這,本文建議收藏,利用等公交、各種排隊之時提升自己。這世上天才很少,懶蛋卻很多,你若對得起時間,時間便對得起你。
❼ 數據結構面試常見問題
數據結構面試常見問題
數據結構是計算機存儲、組織數據的方式。數據結構是指相互之間存在一種或多種特定關系的數據元素的集合。下面就是我整理的數據結構面試常見問題,一起來看一下吧。
數據結構面試常見問題 篇1
數據結構與演算法,這個部分的內容其實是十分的龐大,要想都覆蓋到不太容易。在校學習階段我們可能需要對每種結構,每種演算法都學習,但是找工作筆試或者面試的時候,要在很短的時間內考察一個人這方面的能力,把每種結構和演算法都問一遍不太現實。所以,實際的情況是,企業一般考察一些看起來很基本的概念和演算法,或者是一些變形,然後讓你去實現。也許看起來簡單,但是如果真讓你在紙上或者是計算機上快速地完成一個演算法,並且設計測試案例,最後跑起來,你就會發現會很難了。這就要求我們要熟悉,並牢固掌握常用的演算法,特別是那些看起來貌似簡單的演算法,正是這些用起來很普遍的演算法,才要求我們能很扎實的掌握,在實際工作中提高工作效率。遇到復雜的演算法,通過分析和扎實的基本功,應該可以很快地進行開發。
閑話少說,下面進入正題。
一.數據結構部分
1.數組和鏈表的區別。(很簡單,但是很常考,記得要回答全面)
C++語言中可以用數組處理一組數據類型相同的數據,但不允許動態定義數組的大小,即在使用數組之前必須確定數組的大小。而在實際應用中,用戶使用數組之前有時無法准確確定數組的大小,只能將數組定義成足夠大小,這樣數組中有些空間可能不被使用,從而造成內存空間的浪費。鏈表是一種常見的數據組織形式,它採用動態分配內存的形式實現。需要時可以用new分配內存空間,不需要時用將已分配的空間釋放,不會造成內存空間的浪費。
從邏輯結構來看:數組必須事先定義固定的長度(元素個數),不能適應數據動態地增減的情況,即數組的大小一旦定義就不能改變。當數據增加時,可能超出原先定義的元素個數;當數據減少時,造成內存浪費;鏈表動態地進行存儲分配,可以適應數據動態地增減的.情況,且可以方便地插入、刪除數據項。(數組中插入、刪除數據項時,需要移動其它數據項)。
從內存存儲來看:(靜態)數組從棧中分配空間(用NEW創建的在堆中), 對於程序員方便快速,但是自由度小;鏈表從堆中分配空間, 自由度大但是申請管理比較麻煩.
1.從訪問方式來看:數組在內存中是連續存儲的,因此,可以利用下標索引進行隨機訪問;鏈表是鏈式存儲結構,在訪問元素的時候只能通過線性的方式由前到後順序訪問,所以訪問效率比數組要低。
2.鏈表的一些操作,如鏈表的反轉,鏈表存在環路的判斷(快慢指針),雙向鏈表,循環鏈表相關操作。
3.隊列(特殊的如優先順序隊列),棧的應用。(比如隊列用在消息隊列,棧用在遞歸調用中)
4.二叉樹的基本操作
二叉樹的三種遍歷方式(前序,中序,後序)及其遞歸和非遞歸實現,三種遍歷方式的主要應用(如後綴表達式等)。相關操作的時間復雜度。
5.字元串相關
整數,浮點數和字元串之間的轉換(atoi,atof,itoa)
字元串拷貝注意異常檢查,比如空指針,字元串重疊,自賦值,字元串結束符'/0'等。
二.演算法部分
1.排序演算法:
排序可以算是最基本的,最常用的演算法,也是筆試面試中最常被考察到的演算法。最基本的冒泡排序,選擇排序,插入排序要可以很快的用代碼實現,這些主要考察你的實際編碼能力。堆排序,歸並排序,快排序,這些演算法需要熟悉主要的思想,和需要注意的細節地方。需要熟悉常用排序演算法的時間和空間復雜度。
各種排序演算法的使用范圍總結:
(1)當數據規模較小的時候,可以用簡單的排序演算法如直接插入排序或直接選擇排序。
(2)當文件的初態已經基本有序時,可以用直接插入排序或冒泡排序。
(3)當數據規模比較大時,應用速度快的排序演算法。可以考慮用快速排序。當記錄隨機分布的時候,快排的平均時間最短,但可能出現最壞的情況,這時候的時間復雜度是O(n^2),且遞歸深度為n,所需的棧空間問O(n)。
(4)堆排序不會出現快排那樣的最壞情況,且堆排序所需的輔助空間比快排要少。但這兩種演算法都不是穩定的,若要求排序時穩定的,可以考慮用歸並排序。
(5)歸並排序可以用於內排序,也可以用於外排序。在外排序時,通常採用多路歸並,並且通過解決長順串的合並,產生長的初始串,提高主機與外設並行能力等措施,以減少訪問外存額次數,提高外排序的效率。
2,查找演算法
能夠熟練寫出或者是上機編碼出二分查找的程序。
3.hash演算法
4.一些演算法設計思想。
貪心演算法,分治演算法,動態規劃演算法,隨機化演算法,回溯演算法等。這些可以根據具體的例子程序來復習。
5.STL
STL(Standard Template Library)是一個C++領域中,用模版技術實現的數據結構和演算法庫,已經包含在了C++標准庫中。其中的vecor,list,stack,queue等結構不僅擁有更強大的功能,還有了更高的安全性。除了數據結構外,STL還包含泛化了的迭代器,和運行在迭代器上的各種實用演算法。這些對於對性能要求不是太高,但又不希望自己從底層實現演算法的應用還是很具有誘惑力的。
數據結構面試常見問題 篇2
1. 什麼是數據結構?
數據結構是數據組織(存儲)和操作進行檢索和訪問的方式。它還定義了不同數據集相互關聯、建立關系和形成演算法的方式。
2. 描述數據結構的類型?
列表:鏈接到先前或/和後續數據項的相關事物的集合。
數組:所有相同的值的集合。
Records:欄位的集合,每個欄位都包含來自單一數據類型的數據。
樹:在分層框架中組織數據的數據結構。這種形式的數據結構遵循數據項插入、刪除和修改的順序。
表格:數據以行和列的形式保存。這些與記錄相當,因為數據的結果或更改反映在整個表中。
3. 什麼是線性數據結構?請舉例
如果數據結構的所有元素或數據項都按順序或線性順序排列,則數據結構是線性的。元素以非分層方式存儲,因此除了列表中的第一個和最後一個元素外,每個項目都有後繼者和前驅者。數組、堆棧、字元串、隊列和鏈表,都屬於線性數據結構。
4. 數據結構有哪些應用?
數值分析、操作系統、人工智慧、編譯器設計、資料庫管理、圖形、統計分析和模擬。
5、文件結構和存儲結構有什麼區別?
區別在於訪問的內存區域。存儲結構是指計算機系統內存中的數據結構,而文件結構是指輔助存儲器中的存儲結構。
6、什麼是多維數組?
多維數組的意思是指三維或者三維以上的數組。 三維數組具有高、寬、深的概念,或者說行、列、層的概念,即數組嵌套數組達到三維及其以上。是最常見的多維數組,由於其可以用來描述三維空間中的位置或狀態而被廣泛使用。
7. 什麼是鏈表數據結構?
這是最常見的數據結構面試問題之一,面試官希望你能給出全面的答案。嘗試盡可能多地解釋,而不是用一句話來完成你的答案!
它是一個線性數據結構或一系列數據對象,其中元素不存儲在相鄰的內存位置。元素使用指針鏈接以形成鏈。每個元素都是一個單獨的對象,稱為節點。每個節點有兩項:數據欄位和對下一個節點的引用。鏈表中的入口點稱為頭。如果列表為空,則頭部為空引用,最後一個節點具有對空的引用。
一個鏈表是一個動態的數據結構,其中節點的數量是不固定的,這樣的例子有擴大和縮小需求的能力。
它適用於以下情況:
我們處理未知數量的對象或不知道列表中有多少項目;
我們需要從列表中進行恆定時間的插入/刪除,就像在時間可預測性至關重要的實時計算中一樣;
不需要隨機訪問任何元素;
該演算法需要一個數據結構,無論對象在內存中的物理地址如何,都需要在其中存儲對象;
我們需要在列表中間插入項目,就像在優先隊列中一樣;
一些實現是堆棧和隊列、圖形、名稱目錄、動態內存分配以及對長整數執行算術運算
8.什麼是雙向鏈表?請舉例
它是鏈表的一種復雜類型(雙端 LL),其中一個節點有兩個鏈接,一個連接到序列中的下一個節點,另一個連接到前一個節點。這允許在兩個方向上遍歷數據元素。
舉例:
帶有下一個和上一個導航按鈕的音樂播放列表
具有 BACK-FORWARD 訪問頁面的瀏覽器緩存
瀏覽器上的撤消功能
9. 為什麼要做演算法分析?
一個問題可以使用多種解決演算法以多種方式解決。演算法分析提供對演算法所需資源的估計,以解決特定的計算問題。還確定了執行所需的時間和空間資源量。
演算法的時間復雜度量化了演算法運行所花費的時間,作為輸入長度的函數。空間復雜度量化了演算法佔用的空間或內存量,以作為輸入長度的函數運行。
;