在程序員的職業(yè)生涯中,算法亦算是一門基礎(chǔ)課程,尤其是在面試的時候,很多公司都會讓程序員編寫一些算法實(shí)例,例如快速排序、二叉樹查找等等。
本文總結(jié)了程序員在代碼面試中最常遇到的10大算法類型,想要真正了解這些算法的原理,還需程序員們花些功夫。
1.String/Array/Matrix
在Java中,String是一個包含char數(shù)組和其它字段、方法的類。如果沒有IDE自動完成代碼,下面這個方法大家應(yīng)該記?。?nbsp;
下面列出一些需要高級算法才能解決的經(jīng)典問題:
- Evaluate Reverse Polish Notation
- Longest Palindromic Substring
- 單詞分割
- 字梯
- Median of Two Sorted Arrays
- 正則表達(dá)式匹配
- 合并間隔
- 插入間隔
- Two Sum
- 3Sum
- 4Sum
- 3Sum Closest
- String to Integer
- 合并排序數(shù)組
- Valid Parentheses
- 實(shí)現(xiàn)strStr()
- Set Matrix Zeroes
- 搜索插入位置
- Longest Consecutive Sequence
- Valid Palindrome
- 螺旋矩陣
- 搜索一個二維矩陣
- 旋轉(zhuǎn)圖像
- 三角形
- Distinct Subsequences Total
- Maximum Subarray
- 刪除重復(fù)的排序數(shù)組
- 刪除重復(fù)的排序數(shù)組2
- 查找沒有重復(fù)的最長子串
- 包含兩個獨(dú)特字符的最長子串
- Palindrome Partitioning
2.鏈表
在Java中實(shí)現(xiàn)鏈表是非常簡單的,每個節(jié)點(diǎn)都有一個值,然后把它鏈接到下一個節(jié)點(diǎn)。
比較流行的兩個鏈表例子就是棧和隊(duì)列。
棧(Stack)
值得一提的是,Java標(biāo)準(zhǔn)庫中已經(jīng)包含一個叫做Stack的類,鏈表也可以作為一個隊(duì)列使用(add()和remove())。(鏈表實(shí)現(xiàn)隊(duì)列接口)如果你在面試過程中,需要用到?;蜿?duì)列解決問題時,你可以直接使用它們。
在實(shí)際中,需要用到鏈表的算法有:
3.樹&堆
這里的樹通常是指二叉樹。
下面是一些與二叉樹有關(guān)的概念:- 二叉樹搜索:對于所有節(jié)點(diǎn),順序是:left children <= current node <= right children;
- 平衡vs.非平衡:它是一 棵空樹或它的左右兩個子樹的高度差的絕對值不超過1,并且左右兩個子樹都是一棵平衡二叉樹;
- 滿二叉樹:除最后一層無任何子節(jié)點(diǎn)外,每一層上的所有結(jié)點(diǎn)都有兩個子結(jié)點(diǎn);
- 完美二叉樹(Perfect Binary Tree):一個滿二叉樹,所有葉子都在同一個深度或同一級,并且每個父節(jié)點(diǎn)都有兩個子節(jié)點(diǎn);
- 完全二叉樹:若設(shè)二叉樹的深度為h,除第 h 層外,其它各層 (1~h-1) 的結(jié)點(diǎn)數(shù)都達(dá)到最大個數(shù),第 h 層所有的結(jié)點(diǎn)都連續(xù)集中在最左邊,這就是完全二叉樹。
堆(Heap)是一個基于樹的數(shù)據(jù)結(jié)構(gòu),也可以稱為優(yōu)先隊(duì)列( PriorityQueue),在隊(duì)列中,調(diào)度程序反復(fù)提取隊(duì)列中第一個作業(yè)并運(yùn)行,因而實(shí)際情況中某些時間較短的任務(wù)將等待很長時間才能結(jié)束,或者某些不短小,但具有重要性的作業(yè),同樣應(yīng)當(dāng)具有優(yōu)先權(quán)。堆即為解決此類問題設(shè)計(jì)的一種數(shù)據(jù)結(jié)構(gòu)。
下面列出一些基于二叉樹和堆的算法:
- 二叉樹前序遍歷
- 二叉樹中序遍歷
- 二叉樹后序遍歷
- 字梯
- 驗(yàn)證二叉查找樹
- 把二叉樹變平放到鏈表里
- 二叉樹路徑和
- 從前序和后序構(gòu)建二叉樹
- 把有序數(shù)組轉(zhuǎn)換為二叉查找樹
- 把有序列表轉(zhuǎn)為二叉查找樹
- 最小深度二叉樹
- 二叉樹最大路徑和
- 平衡二叉樹
4.Graph
與Graph相關(guān)的問題主要集中在深度優(yōu)先搜索和寬度優(yōu)先搜索。深度優(yōu)先搜索非常簡單,你可以從根節(jié)點(diǎn)開始循環(huán)整個鄰居節(jié)點(diǎn)。下面是一個非常簡單的寬度優(yōu)先搜索例子,核心是用隊(duì)列去存儲節(jié)點(diǎn)。
第一步,定義一個GraphNode
第二步,定義一個隊(duì)列
第三步,使用隊(duì)列進(jìn)行寬度優(yōu)先搜索輸出結(jié)果:value: 2 value: 3 value: 5 Find value: 5
value: 4
實(shí)際中,基于Graph需要經(jīng)常用到的算法:
5.排序
不同排序算法的時間復(fù)雜度,大家可以到wiki上查看它們的基本思想。
BinSort、Radix Sort和CountSort使用了不同的假設(shè),所有,它們不是一般的排序方法。
下面是這些算法的具體實(shí)例,另外,你還可以閱讀: Java開發(fā)者在實(shí)際操作中是如何排序的。
6.遞歸和迭代
下面通過一個例子來說明什么是遞歸。
問題:
這里有n個臺階,每次能爬1或2節(jié),請問有多少種爬法?
步驟1:查找n和n-1之間的關(guān)系
為了獲得n,這里有兩種方法:一個是從第一節(jié)臺階到n-1或者從2到n-2。如果f(n)種爬法剛好是爬到n節(jié),那么f(n)=f(n-1)+f(n-2)。
步驟2:確保開始條件是正確的
f(0) = 0;
f(1) = 1;
遞歸方法的時間復(fù)雜度指數(shù)為n,這里會有很多冗余計(jì)算。
該遞歸可以很簡單地轉(zhuǎn)換為迭代。在這個例子中,迭代花費(fèi)的時間要少些。關(guān)于迭代和遞歸,你可以去 這里看看。
7.動態(tài)編程
動態(tài)編程主要用來解決如下技術(shù)問題:
- An instance is solved using the solutions for smaller instances;
- 對于一個較小的實(shí)例,可能需要許多個解決方案;
- 把較小實(shí)例的解決方案存儲在一個表中,一旦遇上,就很容易解決;
- 附加空間用來節(jié)省時間。
上面所列的爬臺階問題完全符合這四個屬性,因此,可以使用動態(tài)編程來解決:
一些基于動態(tài)編程的算法:
8.位操作
位操作符:
從一個給定的數(shù)n中找位i(i從0開始,然后向右開始)
例如,獲取10的第二位:
典型的位算法:9.概率
通常要解決概率相關(guān)問題,都需要很好地格式化問題,下面提供一個簡單的例子:
有50個人在一個房間,那么有兩個人是同一天生日的可能性有多大?(忽略閏年,即一年有365天)
算法:
結(jié)果:calculateProbability(50) = 0.97
10.組合和排列
組合和排列的主要差別在于順序是否重要。
例1:
1、2、3、4、5這5個數(shù)字,輸出不同的順序,其中4不可以排在第三位,3和5不能相鄰,請問有多少種組合?
例2:
有5個香蕉、4個梨、3個蘋果,假設(shè)每種水果都是一樣的,請問有多少種不同的組合?
基于它們的一些常見算法
來自:ProgramCreek
學(xué)者網(wǎng)


評論 3