簡述我是如何在2020春招中拿到10+個OFFER的
- Java基礎
- 1.Java和JavaSciprt
- 2.構造函數?
- 3.方法覆蓋和方法重載
- 4.abstract class和interface的區別
- 5.Overload和Override的區別
- 6.面向對象三大特徵
- 7.接口和抽象類的區別
- 8.ArrayList、Vector、LinkedList的存儲性能和特性
- 9.HashMap和Hashtable的區別
- Java 進階
- 計算機網絡
- 數據庫
- 常見代碼題
Java基礎
1.Java和JavaSciprt
概念
- Java 是原Sun公司推出的面向對象的程序設計語言,特別適合於互聯網應用程序開發;
- JavaScript是Netscape公司的產品,爲了擴展Netscape瀏覽器的功能而開發的一種可以嵌入Web頁面中運行的基於對象和事件驅動的解釋性語言。
基於對象和麪向對象
- Java是一種真正的面向對象的語言,即使是開發簡單的程序,必須設計對象;
- JavaScript是種腳本語言,它可以用來製作與網絡無關的,與用戶交互作用的複雜軟件。
- JavaScript是一種基於對象(Object-Based)和事件驅動(Event-Driven)的編程語言,因而它本身提供了非常豐富的內部對象供設計人員使用。
解釋和編譯
- Java的源代碼在執行之前,必須經過編譯。
- JavaScript是一種解釋性編程語言,其源代碼不需經過編譯,由瀏覽器解釋執行。(目前的瀏覽器幾乎都使用了JIT(即時編譯)技術來提升JavaScript的運行效率)
強類型變量和類型弱變量
- Java採用強類型變量檢查,即所有變量在編譯之前必須作聲明;
- JavaScript中變量是弱類型的,甚至在使用變量前可以不作聲明,JavaScript的解釋器在運行時檢查推斷其數據類型。
2.構造函數?
什麼是構造函數?
- 當新對象被創建的時候,構造函數會被調用。每一個類都有構造函數。在程序員沒有給類提供構造函數的情況下,Java編譯器會爲這個類創建一個默認的構造函數。
構造函數重載
- Java中構造函數重載和方法重載很相似。可以爲一個類創建多個構造函數。每一個構造函數必須有它自己唯一的參數列表。
複製構造函數
- Java不支持像C++中那樣的複製構造函數,這個不同點是因爲如果你不自己寫構造函數的情況下,Java不會創建默認的複製構造函數。
3.方法覆蓋和方法重載
方法重載(Overloading)
- Java中的方法重載發生在同一個類裏面兩個或者是多個方法的
方法名相同
但是參數不同
的情況。
方法覆蓋(Overriding)
- 方法覆蓋是說子類重新定義了父類的方法。方法覆蓋必須有相同的方法名,參數列表和返回類型。
覆蓋者可能不會限制它所覆蓋的方法的訪問。
4.abstract class和interface的區別
抽象類
- 聲明方法的存在,而不去實現它的類被叫做抽象類(abstract class),它用於要創建一個體現某些基本行爲的類,併爲該類聲明方法,但不能在該類中實現該類的情況。
- 不能創建abstract 類的實例。然而可以創建一個變量,其類型是一個抽象類,並讓它指向具體子類的一個實例。
- 不能有抽象構造函數或抽象靜態方法。
- Abstract 類的子類爲它們父類中的所有抽象方法提供實現,否則它們也是抽象類爲。取而代之,在子類中實現該方法。知道其行爲的其它類可以在類中實現這些方法。
接口
- 接口(interface)是抽象類的變體。
- 在接口中,所有方法都是抽象的。
- 多繼承性可通過實現這樣的接口而獲得。
- 接口中的所有方法都是抽象的,沒有一個有程序體。
- 接口只可以定義static final成員變量。
- 接口的實現與子類相似,除了該實現類不能從接口定義中繼承行爲。
- 由於有抽象類,它允許使用接口名作爲引用變量的類型。通常的動態聯編將生效。
- 引用可以轉換到接口類型或從接口類型轉換,instanceof 運算符可以用來決定某對象的類是否實現了接口。
5.Overload和Override的區別
- 方法的重寫Overriding和重載Overloading是Java多態性的不同表現。
- 重寫Overriding是父類與子類之間多態性的一種表現重載Overloading是一個類中多態性的一種表現。
- 如果在子類中定義某方法與其父類有相同的名稱和參數,我們說該方法被重寫(Overriding)。子類的對象使用這個方法時,將調用子類中的定義,對它而言,父類中的定義如同被”屏蔽”了。
- 如果在一個類中定義了多個同名的方法,它們或有不同的參數個數或有不同的參數類型,則稱爲方法的重載(Overloading)。
- Overloaded的方法是可以改變返回值的類型。
6.面向對象三大特徵
封裝
- 封裝是把過程和數據包圍起來,對數據的訪問只能通過已定義的界面。
- 面向對象計算始於這個基本概念,即現實世界可以被描繪成一系列完全自治、封裝的對象,這些對象通過一個受保護的接口訪問其他對象。
繼承
- 繼承是一種聯結類的層次模型,並且允許和鼓勵類的重用,它提供了一種明確表述共性的方法。
- 對象的一個新類可以從現有的類中派生,這個過程稱爲類繼承。
- 新類繼承了原始類的特性,新類稱爲原始類的派生類(子類),而原始類稱爲新類的基類(父類)。
- 派生類可以從它的基類那裏繼承方法和實例變量,並且類可以修改或增加新的方法使之更適合特殊的需要。
多態
- 多態性是指允許不同類的對象對同一消息作出響應。
- 多態性包括參數化多態性和包含多態性。
- 多態性語言具有靈活、抽象、行爲共享、代碼共享的優勢,很好的解決了應用程序函數同名問題。
7.接口和抽象類的區別
- 接口中所有的方法隱含的都是抽象的。而抽象類則可以同時包含抽象和非抽象的方法。
- 類可以實現很多個接口,但是隻能繼承一個抽象類。
- 類可以不實現抽象類和接口聲明的所有方法,當然,在這種情況下,類也必須得聲明成是抽象的。
- 抽象類可以在不提供接口方法實現的情況下實現接口。
- Java接口中聲明的變量默認都是final的。抽象類可以包含非final的變量。
- Java接口中的成員函數默認是public的。抽象類的成員函數可以是private,protected或者是public。
- 接口是絕對抽象的,不可以被實例化。抽象類也不可以被實例化,但是,如果它包含main方法的話是可以被調用的。
8.ArrayList、Vector、LinkedList的存儲性能和特性
ArrayList
和Vector
都是使用數組方式存儲數據,此數組元素數大於實際存儲的數據以便增加和插入元素,它們都允許直接按序號索引元素,但是插入元素要涉及數組元素移動等內存操作,所以索引數據快而插入數據慢。- Vector中的方法由於添加了synchronized修飾,因此Vector是線程安全的容器,但性能上較ArrayList差,因此已經是Java中的遺留容器。
- LinkedList使用雙向鏈表實現存儲(將內存中零散的內存單元通過附加的引用關聯起來,形成一個可以按序號索引的線性結構,這種鏈式存儲方式與數組的連續存儲方式相比,內存的利用率更高),按序號索引數據需要進行前向或後向遍歷,但是插入數據時只需要記錄本項的前後項即可,所以
插入速度較快
。 - Vector屬於遺留容器(Java早期的版本中提供的容器,除此之外,Hashtable、Dictionary、BitSet、Stack、Properties都是遺留容器),已經不推薦使用.
- 由於
ArrayList
和LinkedListed
都是非線程安全的,如果遇到多個線程操作同一個容器的場景,則可以通過工具類Collections中的synchronizedList方法將其轉換成線程安全的容器
後再使用(這是對裝潢模式的應用,將已有對象傳入另一個類的構造器中創建新的對象來增強實現)。
9.HashMap和Hashtable的區別
- HashMap和Hashtable都實現了Map接口,因此很多特性非常相似
- HashMap允許鍵和值是null,而Hashtable不允許鍵或者值是null。
- Hashtable是同步的,而HashMap不是。因此,HashMap更適合於單線程環境,而Hashtable適合於多線程環境。
- HashMap提供了可供應用迭代的鍵的集合,因此,HashMap是快速失敗的。
- 另一方面,Hashtable提供了對鍵的列舉(Enumeration)。
- 一般認爲Hashtable是一個遺留的類。
Java 進階
1 什麼是線程池(thread pool)
- 在面向對象編程中,創建和銷燬對象是很費時間的,因爲創建一個對象要獲取內存資源或者其它更多資源。
- Java虛擬機將試圖跟蹤每一個對象,以便能夠在對象銷燬後進行垃圾回收,所以提高服務程序效率的一個手段就是儘可能減少創建和銷燬對象的次數,特別是一些很耗資源的對象創建和銷燬,這就是”池化資源”技術產生的原因。
- 線程池顧名思義就是事先創建若干個可執行的線程放入一個池(容器)中,需要的時候從池中獲取線程不用自行創建,使用完畢不需要銷燬線程而是放回池中,從而減少創建和銷燬線程對象的開銷。
- Java 5+中的Executor接口定義一個執行線程的工具。它的子類型即線程池接口是ExecutorService。
- 要配置一個線程池是比較複雜的,尤其是對於線程池的原理不是很清楚的情況下,因此在工具類Executors面提供了一些靜態工廠方法,生成一些常用的線程池,如下所示.
newSingleThreadExecutor:
創建一個單線程的線程池。這個線程池只有一個線程在工作,也就是相當於單線程串行執行所有任務。如果這個唯一的線程因爲異常結束,那麼會有一個新的線程來替代它。此線程池保證所有任務的執行順序按照任務的提交順序執行。newFixedThreadPool:
創建固定大小的線程池。每次提交一個任務就創建一個線程,直到線程達到線程池的最大大小。線程池的大小一旦達到最大值就會保持不變,如果某個線程因爲執行異常而結束,那麼線程池會補充一個新線程。- newCachedThreadPool:創建一個可緩存的線程池。如果線程池的大小超過了處理任務所需要的線程,那麼就會回收部分空閒(60秒不執行任務)的線程,當任務數增加時,此線程池又可以智能的添加新線程來處理任務。此線程池不會對線程池大小做限制,線程池大小完全依賴於操作系統(或者說JVM)能夠創建的最大線程大小。
newScheduledThreadPool:
創建一個大小無限的線程池。此線程池支持定時以及週期性執行任務的需求。newSingleThreadExecutor:
創建一個單線程的線程池。此線程池支持定時以及週期性執行任務的需求。
2 懶漢式和餓漢式對比
對比項 | 懶漢式 | 餓漢式 |
---|---|---|
望文生義 | 非常懶,不到必要時候不創建單例實例 | 類加載時,就創建單例實例 |
線程安全(多線程環境下,能否確保對象只被創建一次) | 不安全 | 安全 |
單例實例創建時機 | 當Singleton.getUniqueInstance()方法被調用時,纔會創建實例。如果程序始終沒有調用該方法,則單例實例永遠不會被創建,節省了內存空間和資源。 | 在Singleton被類加載器加載時,創建單例實例對象,並且把單例對象一直存放在內存的方法區,直到程序結束纔會把單例對象銷燬。如果程序始終沒有使用該對象,將會造成資源浪費 |
3 UML中有哪些常用的圖?
- UML定義了多種圖形化的符號來描述軟件系統部分或全部的靜態結構和動態結構,包括:用例圖(use case diagram)、類圖(class diagram)、時序圖(sequence diagram)、協作圖(collaboration diagram)、狀態圖(statechart diagram)、活動圖(activity diagram)、構件圖(component diagram)、部署圖(deployment diagram)等。
- 在這些圖形化符號中,有三種圖最爲重要,分別是:用例圖(用來捕獲需求,描述系統的功能,通過該圖可以迅速的瞭解系統的功能模塊及其關係)、類圖(描述類以及類與類之間的關係,通過該圖可以快速瞭解系統)、時序圖(描述執行特定任務時對象之間的交互關係以及執行順序,通過該圖可以瞭解對象能接收的消息也就是說對象能夠向外界提供的服務)。
4 面向對象思想
4.1 面向對象的SOLID原則
1 單一職責原則
一個類只應承擔一種責任。換句話說,讓一個類只做一件事。如果需要承擔更多的工作,那麼分解這個類。
2 開放封閉原則
實體應該對擴展是開放的,對修改是封閉的。即,可擴展(extension),不可修改(modification)。
3 里氏替換原則
一個對象在其出現的任何地方,都可以用子類實例做替換,並且不會導致程序的錯誤。換句話說,當子類可以在任意地方替換基類且軟件功能不受影響時,這種繼承關係的建模纔是合理的。
4 接口分離原則
客戶(client)不應被強迫依賴它不使用的方法。即一個類實現的接口中,包含了它不需要的方法。將接口拆分成更小和更具體的接口,有助於解耦,從而更容易重構、更改。
5 依賴倒置原則
- 高層次的模塊不應依賴低層次的模塊,他們都應該依賴於抽象。
- 抽象不應依賴於具體實現,具體實現應依賴抽象。
6 擴展:IOC和DI
控制反轉(IOC)和依賴注入(DI)是Spring中最重要的核心概念之一,而兩者實際上是一體兩面的。
- 依賴注入
- 一個類依賴另一個類的功能,那麼就通過注入,如構造器、setter方法等,將這個類的實例引入。
- 側重於實現。
- 控制反轉
- 創建實例的控制權由一個實例的代碼剝離到IOC容器控制,如xml配置中。
- 側重於原理。
- 反轉了什麼:原先是由類本身去創建另一個類,控制反轉後變成了被動等待這個類的注入。
2 類與對象
-
類的成員變量:對象狀態
-
類的成員函數:對象行爲
-
類的靜態變量、類的靜態函數
-
沒有this引用,靜態變量全局只有一份
-
普通函數引用靜態變量、函數?可以
-
對象上引用靜態變量、函數?編譯警告
-
靜態函數引用普通成員變量、函數:編譯錯誤
-
計算機網絡
1 HTTP協議
1.1 客戶端與服務器
- 通過發送請求獲取服務器資源的web瀏覽器叫做客戶端
- web瀏覽器通過指定的訪問地址獲取服務器上的資源
- HTTP客戶端和HTTTP服務器共同構成萬維網的基本組件
1.1 URI和URL
- URI,服務器資源名,統一資源標識符,分爲URL和URN
- URL,統一資源定位符,表示服務器上資源的特定位置
- URN,統一資源名,是特定內容的唯一名稱
2 TCP連接的建立與釋放
2.1 三次握手
- 第一次握手
- 建立連接,客戶端發送連接請求報文段
- 把標有SYN的數據包發給服務器
- 第二次握手
- 服務器收到客戶端的SYN報文段
- 服務器發送標有SYN / ACK的數據包
- 第三次握手
- 客戶端收到服務器端的SYN / ACK數據包
- 向服務端發送標有ACK的數據包
2.2 四次揮手
- 第一次揮手
- 客戶端向服務器發送FIN=1報文段
- 表示客戶端沒有數據要發送給服務端
- 第二次揮手
- 服務器收到客戶端發送的FIN報文段
- 服務器向客戶端發送ACK報文段
- 第三次揮手
- 服務器向客戶端發送FIN報文段,請求關閉連接
- 第四次揮手
- 客戶端收到服務器發送的FIN報文段,向服務器發送ACK報文段
- 服務器收到客戶端的ACK報文段,關閉連接
- 客戶端等待2MSL後,關閉連接
3 網絡模型分層
3.1 OSI參考模型分層
編號 | 名稱 | 描述 |
---|---|---|
7 | 應用層 | 提供應用程序之間通信 |
6 | 表示層 | 處理數據格式,數據加密等 |
5 | 會話層 | 建立維護和管理會話 |
4 | 傳輸層 | 建立主機端到端的連接 |
3 | 網絡層 | 尋址和路由選擇 |
2 | 數據鏈路層 | 提供介質訪問、鏈路管理 |
1 | 物理層 | 比特流傳輸 |
3.2 TCP/IP 分層模型
4 TCP和UDP
4.1 面向報文(UDP)和麪向字節流(TCP)的區別
4.2 面向報文(UDP)和麪向字節流(TCP)的比較
協議 | TCP | UDP |
---|---|---|
可靠性 | 可靠 | 不可靠 |
連接性 | 面向連接 | 無連接 |
報文 | 面向字節流 | 面向報文(保留報文的邊界) |
效率 | 傳輸效率低 | 傳輸效率高 |
雙工性 | 全雙工 | 一對一,一對多,多對一,多對多 |
流量控制 | 滑動窗口 | 無 |
擁塞控制 | 慢開始,擁塞避免,快重傳,快恢復 | 無 |
5 www(萬維網)
www是world wide web的簡稱,也稱web、3w等。www是基於客戶機/服務器方式的信息發現技術和超文本傳輸技術的綜合。www服務器通過超文本標記語言(HTML)把信息組織成爲圖文並茂的超文本,利用鏈接從一個站點跳轉到另一個站點。這樣一來,徹底擺脫了以前查詢工具只能按特定路徑一步步地查詢信息地限制。
5.1 萬維網
- WWW (World Wide Web,萬維網)是存儲在Internet計算機中、數量巨大的文檔的集合。
- 這些文檔稱爲頁面,它是一種超文本( Hypertext)信息,可以用於描述超媒體。
- 文本、圖形、視頻、音頻等多媒體,稱爲超媒體( Hypermedia)。
- Web上的信息是由彼此關聯的文檔組成的,而使其連接在一起的是超鏈接( Hyperlink)
5.2 超文本
- 超文本(Hypertext)是由一個叫做網頁瀏覽器(Web browser)的程序顯示。
- 網頁瀏覽器從網頁服務器取回稱爲“文檔”或“網頁”的信息並顯示。
- 通常是顯示在計算機顯示器。
- 人可以跟隨網頁上的超鏈接(Hyperlink),再取回文件,甚至也可以送出數據給服務器。
- 順着超鏈接走的行爲又叫瀏覽網頁。相關的數據通常排成一羣網頁,又叫網站。
5.3 網上衝浪
- 網上衝浪(Surfing the Internet,瀏覽網絡)
- 最早由一個叫簡・阿莫爾・泡利(Jean Armour Poly)的作家通過他的作品《網上衝浪》使這個概念被大衆接受。
- 這本書由威爾遜出版社在1992年6月正式出版。泡利在互聯網領域被稱作“網絡媽媽”(Netmom)
5.4 網頁、網頁文件、網站
- 網頁是網站的基本信息單位,是WWW的基本文檔。它由文字、圖片、動畫、聲音等多種媒體信息以及鏈接組成,是用HTML編寫的,通過鏈接實現與其他網頁或網站的關聯和跳轉
- 網頁文件是用HTML(標準通用標記語言下的一個應用)編寫的,可在WWW上傳輸,能被瀏覽器識別顯示的文本文件。其擴展名是.htm和.html
- 網站由衆多不同內容的網頁構成,網頁的內容可體現網站的全部功能。通常把進入網站首先看到的網頁稱爲首頁或主頁(homepage),例如,新浪、網易、搜狐就是國內比較知名的大型門戶網站.
5.5 HTTP 協議
HTTP是Hypertext Transfer Protocol 的縮寫,即超文本傳輸協議。 顧名思義,HTTP提供了訪問超文本信息的功能,是WWW瀏覽器和WWW服務器之間的應用層通信協議。HTTP協議是用於分佈式協作超文本信息系統的、通用的、面向對象的協議。通過擴展命令,它可用於類似的任務,如域名服務或分佈式面向對象系統。WWW使用HTTP協議傳輸各種超文本頁面和數據
HTTP協議會話過程包括4個步驟。
(1)建立連接:客戶端的瀏覽器向服務端發出建立連接的請求,服務端給出響應就可以建立連接了。
(2)發送請求:客戶端按照協議的要求通過連接向服務端發送自己的請求。
(3)給出應答:服務端按照客戶端的要求給出應答,把結果(HTML文件)返回給客戶端。
(4)關閉連接:客戶端接到應答後關閉連接.
HTTP協議是基於TCP/IP之上的協議,它不僅保證正確傳輸超文本文檔,還確定傳輸文檔中的哪一部分,以及哪部分內容首先顯示(如文本先於圖形)等。
5.6 FTP 協議
- 文件傳輸協議(FTP)是Internet中用於訪問遠程機器的一個協議,它使用戶可以在本地機和遠程機之間進行有關文件的操作。
- FTP協議允許傳輸任意文件並且允許文件具有所有權與訪問權限。
- 通過FTP協議,可以與internet上的FTP服務器進行文件的上傳或下載等動作。
- 和其他Internet應用一樣,FTP也採用了客戶端/服務器模式,它包含客戶端FTP和服務器FTP
- 客戶端FTP啓動傳送過程,而服務器FTP對其做出應答。
- 在Internet上有一些網站,它們依照FTP協議提供服務,讓網友們進行文件的存取
- 網上的用戶要連上FTP服務器,就是用到FTP的客戶端軟件。
- 通常Windows都有ftp命令,這實際就是一個命令行的FTP客戶端程序,
- 另外常用的FTP客戶端程序還有CuteFTP、Leapftp、FlashFXP等
- HTTP將用戶的數據,包括用戶名和密碼都明文傳送,具有安全隱患,容易被竊聽到.
- 對於具有敏感數據的傳送,可以使用具有保密功能的HTTPS(Secure Hypertext Transfer Protocol)協議。
6 圖靈獎
- 圖靈獎(Turing Award),全稱“A.M. 圖靈獎(A.M Turing Award)”,由美國計算機協會(ACM)於1966年設立,專門獎勵那些對計算機事業作出重要貢獻的個人。
- 其名稱取自計算機科學的先驅、英國科學家艾倫·麥席森·圖靈(Alan M. Turing)。
- 由於圖靈獎對獲獎條件要求極高,評獎程序又是極嚴,一般每年只獎勵一名計算機科學家,只有極少數年度有兩名合作者或在同一方向作出貢獻的科學家共享此獎。
- 因此它是計算機界最負盛名、最崇高的一個獎項,有“計算機界的諾貝爾獎”之稱。
- 每一年的圖靈獎一般在下一年的3月下旬頒發,從1966年至2019年的圖靈獎共授予了72名獲獎者。
- 按國籍分,美國學者最多,歐洲學者偶見之,華人學者目前僅有2000年圖靈獎得主姚期智(現在清華大學、香港中文大學)。
- 據相關資料統計,截止至2020年3月,世界各高校的校友、教授以及研究人員中,美國斯坦福大學的圖靈獎人數位列世界第一(28位)、美國麻省理工學院(26位)位列世界第二、美國加州大學伯克利分校(25位)位列世界第三,美國哈佛大學(14位)、美國普林斯頓大學(14位)並列世界第四
數據庫
1 數據庫設計的範式
1.1 概念
- 設計數據庫時,需要遵循的規範,越高的範式,數據庫冗餘度越小
- 要遵循後邊的範式要求,必須遵循前邊的範式要求
1.2 第一範式
- 每一列都是不可分割的原子數據項
1.3第二範式
-
在1NF的基礎上,非碼屬性必須完全依賴於候選碼
-
在1NF的基礎上,消除了非主屬性對主碼的部分函數依賴
-
函數依賴:A–>B
- 如果通過A屬性(屬性組)的值,可以確定唯一B屬性的值,則稱B依賴於A
- 例如:學號–>姓名;(學號,課程名稱)–> 分數
-
完全函數依賴:A->B
- 如果A是一個屬性組,則B屬性值的確定需要依賴於屬性組中所有的屬性值
- 例如:(學號,課程名稱)–> 分數
-
部分函數依賴:A->B
- 如果A是一個屬性組 ,則B屬性值的確定只需要依賴於A屬性組中某一些值即可
- 例如:(學號,課程名稱)-> 姓名
-
傳遞函數依賴:A–>B,B->C
- 如果通過A屬性(屬性組)的值,可以確定唯一B屬性值,再通過B屬性(屬性組)的值可以唯一確定C屬性的值,則稱C傳遞A
- 例如:學號 --> 系名,系名 –> 系主任
-
碼:
- 如果在一張表中,一個屬性或屬性組,被其他所有屬性所完全依賴,則稱這個屬性或屬性組爲該表的碼
- 例如:(學號,課程名稱)
1.4 第三範式
- 在2NF基礎上,任何非主屬性不依賴於其他非主屬性
- 在2NF基礎上,消除了傳遞依賴
2 事務的四大特徵
- 原子性:事務是不可分割的最小操作單位,要麼同時成功,要麼同時失敗
- 持久性:當事務提交或回滾後,數據庫會持久化的保存數據
- 隔離性:多個事務之間相互獨立
- 一致性:事務操作前後數據總量不變
常見代碼題
1.鏈表
容易理解,代碼難寫
public class Node {
private final int value;
private Node next;
public int getValue() {
return value;
}
public Node getNext() {
return next;
}
public void setNext(Node next) {
this.next = next;
}
Node(int value) {
this.value = value;
this.next = null;
}
public static void printList(Node head) {
while (head != null) {
System.out.print(head.getValue() + " ");
head = head.next;
}
System.out.println();
}
}
1.1 創建鏈表
- 遞歸方式
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class LinkedListCreator {
/**
* Create a linked list.
*
* @param values The data to create a list.
* @return Head of the linked list
* The returned linked list ends with last node with getNext() == null.
*/
public Node createLinkedList(List<Integer> values) {
if (values.isEmpty()) {
return null;
}
Node firstNode = new Node(values.get(0));
Node headOfSublist = createLinkedList(values.subList(1, values.size()));
firstNode.setNext(headOfSublist);
return firstNode;
}
}
- 非遞歸方式
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class LinkedListCreator {
/**
* Create a linked list.
*
* @param values The data to create a list.
* @return Head of the linked list
* The returned linked list ends with last node with getNext() == null.
*/
public Node createLinkedList(List<Integer> values) {
Node prev = null;
Node head = null;
for (Integer value : values) {
Node node = new Node(value);
if (prev != null) {
prev.setNext(node);
} else {
head = node;
}
prev = node;
}
return head;
}
public Node createLargeLinkedList(int size) {
Node prev = null;
Node head = null;
for (int i = 0; i < size; i++) {
Node node = new Node(i);
if (prev != null) {
prev.setNext(node);
} else {
head = node;
}
prev = node;
}
return head;
}
}
1.2 反轉列表
- 遞歸方式
import java.util.ArrayList;
import java.util.Arrays;
public class LinkedListReverser {
public Node reverseLinkedList(Node head) {
if (head == null || head.getNext() == null) {
return head;
}
Node newHead = reverseLinkedList(head.getNext());
head.getNext().setNext(head);
head.setNext(null);
return newHead;
}
}
- 非遞歸方式
import edu.sust.list.LinkedListCreator;
import edu.sust.list.Node;
import java.util.ArrayList;
import java.util.Arrays;
public class LinkedListReverser {
public Node reverseLinkedList(Node head) {
Node newHead = null;
Node curHead = head;
//Loop invariant.
//newHead points to the linked list already reversed.
//curHead points to the linked list not yet reversed.
while (curHead != null) {
Node next = curHead.getNext();
curHead.setNext(newHead);
newHead = curHead;
curHead = next;
}
return newHead;
}
}
1.3刪除指定值
public class LinkedListDeleter {
public Node deleteIfEquals(Node head, int value) {
if (head != null && head.getValue() == value) {
head = head.getNext();
}
if (head == null) {
return null;
}
Node prev = head;
/*
loop invariant:
list nodes from head up to prev has been processed.
Nodes with values equal to value are deleted.
*/
while (prev.getNext() != null) {
if (prev.getNext().getValue() == value) {
//delete it
prev.setNext(prev.getNext().getNext());
}
}
return head;
}
}
2.二分查找
import javax.xml.bind.SchemaOutputResolver;
public class BinarySearch {
/**
* Searches element k in a sorted array
*
* @param arr a sorted array
* @param k the element to search
* @return index in arr where k is. -1 if not found.
*/
public static int binarySearch(int[] arr, int k) {
int a = 0;
int b = arr.length;
//Loop invariant:[a,b) is a valid range.(a<=b)
//k may only be within range [a,b)
while (a < b) {
int m = a + (b - a) / 2;
if (k < arr[m]) {
b = m;
} else if (k > arr[m]) {
a = m + 1;
} else {
return m;
}
}
return -1;
}
}