總結

面經題答案整理php

Java基礎 1.Java底層源碼分析html

String 和 StringBuilder的區別? StringBuilder和StringBuffer區別? 參考資料: https://www.jianshu.com/p/8c724dd28fa4 公共點:java中的三個類來表示和操做字符串 String是內容不可變的字符串, 被建立以後就不能改變 String類的底層使用了一個不可變的字符數組 StringBuilder和StringBuffer 是內容能夠改變的字符串,底層使用的是char數組(沒有final關鍵字修飾) char[] valuejava

String 的拼接 c = 「a」 + 「b」底層是用StringBuilder或StringBuffer的append方法來實現的 String 轉 SB 轉 String效率較低,若是存在較多的String拼接,不要使用 StringBuilder或StringBuffernode

StringBuilder是線程不安全的,效率較高,JDK1.5以後新添加的,StringBuffer是線程安全的,效率較低mysql

HashMap的相關問題linux

參考資料: https://tech.meituan.com/2016/06/24/java-hashmap.html https://leetcode.com/problems/design-hashmap/ https://juejin.im/post/59e86f9351882521ad0f4147git

說一說HashMap的存儲, 哈希衝突,擴容,併發訪問怎麼解決? HashMap的併發不安全體如今哪? HashMapz在任意時刻能夠有多個線程同時寫HashMap,會致使數據不一致。若是要知足線程安全的要求, 能夠用Colletioncs的synchronizedMap方法使HashMap具有線程安全,或者使用ConcurrentHashMap HashMap在擴容時,對讀寫操做有什麼特殊處理?程序員

概述: HashMap繼承AbstractMap 實現了Map的接口 HashMap根據鍵的hashCode值存儲數據, 大多數狀況下能夠直接定位到它的值, HashMap最多隻容許一條記錄的鍵爲null,多條記錄的值爲null。 底層的實現是 數組+鏈表+紅黑樹,核心元素包括  size loadFactor 負載因子 threshold: 閾值 用來觸發擴容機制 threashold = capacity * loadfactor Node<K,V>[] table Node<K, V> 包括 hash key value Node<K, V> nextgithub

根據key獲取哈希桶數組索引位置詳解 Hash算法本質: 取key的hashCode、高位運算、取模運算 static final int hash(Object key) { //jdk1.8 & jdk1.7 int h; // h = key.hashCode() 爲第一步 取hashCode值 // h ^ (h >>> 16) 爲第二步 高位參與運算 return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }web

HashMap的put()方法流程

HashMap的插入使用單鏈表的頭插入方式, 在同一位置上新元素會被放在鏈表的頭部

HashMap的擴容機制: 對讀寫操做有什麼特殊處理 ? 使用2次冪擴容, 因此元素的位置要麼在原位置, 要麼在原位置再移動二次冪

擴容過程當中hash函數獲得的index可能會改變 只須要看一下新增的bit是0仍是1就能直接肯定位置, 若是是1, 擴容後索引變爲 「原索引 + oldCap」 hash衝突的肯定是一樣的HashCode(一樣的index) 可是不同的key若是是同樣的key直接覆蓋就能夠了 HashMap經過拉鍊法解決hash衝突: 建立鏈表數組,若是遇到了哈希衝突,將衝突的值加到鏈表中便可

ConcurrentHashMap如何實現線程安全的?

JDK 1.7使用的分段鎖

ConcurrentHashMap裏面包含一個Segment數組, 實現ReentrantLock,是可重入鎖, HashEntry用於存儲鍵值對數據, 每一個Segment守護HashEntry,修改數據必需要有Segment鎖

JDK 1.8使用了 synchronized關鍵字和CAS算法

synchronized只鎖定首節點,若是沒有hash衝突,就不會產生併發

Java接口和抽象類的區別:

2.多線程 參考資料: https://www.jianshu.com/p/40d4c7aebd66 50道Java線程面試題 https://www.cnblogs.com/chanshuyi/p/5351723.html Java多線程總結 https://juejin.im/post/5ba133126fb9a05ce02a6f12#heading-4 https://juejin.im/post/5bdbbc3d6fb9a0224a5e486f#heading-14

Java併發變成包含的4層含義 內存模型和一致性協議 鎖相關的理論 無鎖的數據結構 各個語言的併發模型 通常的併發基礎都是基於單機的 可是分佈式鎖也須要考慮是否重入、阻塞中斷、超時喚醒、失效取消等問題

談一下Java多線程實現的幾種方法? 繼承Thread類,重寫父類的run() 方法 實現Runnable接口 實現Callable接口

對比: 實現Runnable接口能夠避免單繼承侷限 線程池只能放入實現Runnable或Callable類的線程 Runnable接口能夠被多個Thread實現,代碼與數據能夠被共享 接口實現時,必須使用Thread.currentThread()來訪問當前線程

實現Runnable和Callable區別 Runnable是執行工做的獨立任務,但它不返回任何值, 若是但願任務在完成的時候能返回一個值, 能夠實現Callable接口而不是Runnable接口 Callable接口的call()方法容許拋異常,而Runnable接口的run()不能上拋異常

說一下線程的生命週期,線程的不一樣狀態

線程的五種狀態: 建立,就緒,運行,阻塞,死亡 建立: 聲明瞭線程對象,可是並無調用start()方法 就緒: 聲明瞭對象 + 調用了start() 方法。是此時線程調度程序尚未將該線程設置爲當前線程,當線程運行結束或從等待和睡眠中恢復以後也是處於就緒狀態 運行: 就緒的線程變爲了當前的線程,就進入運行狀態,執行run方法當中的代碼 阻塞: 線程正在運行的過程當中,被暫停 + 等待過程 sleep, suspend, wait方法均可以形成線程阻塞 死亡: run方法結束執行或者調用了stop方法以後,線程就死亡

啓動線程的兩種方法: 繼承Thread, 重寫run方法並用start 方法啓動線程 實現Runnable接口,實現run方法, 用new Thread(Runnable target).start()方法來啓動

手寫多線程計數 synchronized關鍵字 同步對象是誰?

說一下對於線程安全的理解 如何啓動,關閉線程

Thread的run() 和 start() 方法的區別是什麼? start()方法: 做用是啓動一個新線程,使得新線程處於(可運行的狀態), 一旦獲得了CPU的時間片,就開始執行相應的run() 方法(異步執行) 能夠實現多線程,start不可以被重複調用,

run()方法: 是Thread類中的一個普通方法, 直接調用run方法並不會啓動新線程,程序依然只有主線程這一個線程,其程序的執行路徑仍然只有一條,仍是要順序執行並等待run方法體執行完畢後才能繼續執行下面的代碼。用run開始線程就和多線程屁關係沒有

Java併發編程實戰

第一章 簡介 操做系統爲各個獨立的進程分配各類資源: 內存 + 文件句柄 + 安全證書等 不一樣的進程中間能夠經過粗粒度的通訊機制來交換數據: 包括套接字、信號處理器、共享內存、信號量以及文件等

Java中的鎖 參考博客: https://tech.meituan.com/2018/11/15/java-lock.

Java有哪些鎖機制, 分別有什麼特色?

樂觀鎖和悲觀鎖 樂觀鎖(讀操做多的場景使用): 不添加鎖,值在更新數據的時候判斷是否有別的線程更新了數據, 若是沒有, 則將本身的修改寫入 使用CAS算法來實現 悲觀鎖(寫操做多的場景使用): 在獲取數據的時候直接加鎖。 synchronized關鍵字和Lock的實現類都是悲觀鎖

// ------------------------- 悲觀鎖的調用方式 ------------------------- // synchronized public synchronized void testMethod() { // 操做同步資源 } // ReentrantLock private ReentrantLock lock = new ReentrantLock(); // 須要保證多個線程使用的是同一個鎖 public void modifyPublicResources() { lock.lock(); // 操做同步資源 lock.unlock(); }

// ------------------------- 樂觀鎖的調用方式 ------------------------- private AtomicInteger atomicInteger = new AtomicInteger(); // 須要保證多個線程使用的是同一個AtomicInteger atomicInteger.incrementAndGet(); //執行自增1

原子類 經過使用CAS樂觀鎖 在可伸縮性和活躍性上有優點, 可是在競爭條件較強時的性能不如鎖定 自旋鎖與適應性自旋鎖(強化版自旋鎖) 自旋鎖是爲了不CPU切換狀態而讓線程自旋來等待鎖開銷 適應性指的是 自旋的時間(次數)不固定, 由前一次在同一個鎖上的自旋時間以及鎖的擁有者的狀態來決定。 成功率大->批准自旋時間長 成功率低->直接阻塞線程 取消自旋

無鎖、偏向鎖、輕量級鎖、重量級鎖 這四個詞是用來描述鎖的狀態,針對synchronized關鍵字

鎖加在Java對象頭內部 兩個關鍵數據 Mark Word 標記字段 存儲對象的Hash Code, 分代年齡和鎖標誌信息 Class 類型指針: 對象指向它的類元數據

Monitor鎖(內部鎖) 一個同步機制, 一般被描述爲一個對象 synchronized 經過Monitor來實現線程同步,而Monitor依賴於底層操做系統的Mutex Lock互斥鎖 互斥鎖被成爲「重量級鎖」, JDK 6中爲了減小 得到鎖和釋放鎖帶來的性能消耗,引入了「偏向鎖」 和 「輕量級鎖」
無鎖: 沒有對資源綁定,全部的線程都能訪問並修改同一個資源, 但同時只有一個線程能修改爲功, 其餘失敗的線程會不斷重試。CAS就是一種無鎖實現。 偏向鎖: 若是一段同步代碼一直 被一個線程訪問, 那麼該線程會自動得到鎖,下降獲取鎖的代價, Mark Word中存儲偏向的線程ID, 在線程進入和退出同步塊時檢查Mark Word是否存儲指向當前線程的偏向鎖 偏向鎖不會被主動釋放, 只有當其餘線程嘗試競爭偏向鎖時,持有偏向鎖的線程纔會釋放鎖。 輕量級鎖: 當鎖是偏向鎖的時候, 被另外的線程訪問,偏向鎖就會升級成爲輕量級鎖, 其餘線程會經過自旋方式嘗試獲取鎖, 不會阻塞 重量級鎖: 當有第三個等待線程時,輕量級鎖升級爲重量級鎖, 鎖標誌變爲」10」,此時等待鎖的線程都會進入阻塞狀態。 總結: 偏向鎖對比Mark Word, 避免CAS操做。 輕量級鎖經過CAS和自旋來解決加鎖問題重量級鎖將線程阻塞。

公平鎖與非公平鎖 公平鎖: 按照順序 非公平鎖: 能夠插隊 能夠減小喚醒線程的開銷, 總體的效率可能會高 ReentrantLock中有內部類 Sync, Sync有 FairSync 和 NonfairSync兩個子類

公平鎖比非公平鎖多了一個 check條件 !hasQueuePredecessors() 這個方法主要是判斷當前線程是否位於同步隊列中的第一個。若是是則返回true,不然返回false。

ABA問題: 解決辦法是打時間戳 JDK1.5以後提供了 AtomicStampedReference來解決ABA問題, 調用compareAndSet() 方法先檢查當前引用和當前標誌與預期引用和預期標誌是否相等 V = 待讀寫的內存位置 A = 進行比較的值 B = 待寫入的新值, 只有當V的值等於A時, CAS纔會經過原子方式用新值B來更新A, 不然不執行操做

可重入鎖與非可重入鎖 可重入鎖: 同一個線程在外層方法獲取鎖的時候,再進入該線程的內層方法時會自動獲取鎖(前提: 同一個對象或class內部), 不會由於以前已經獲取過但還沒釋放而阻塞。 ReentrantLock 和 synchronized都是可重入鎖, 優勢是能夠避免死鎖。

public class Widget { public synchronized void doSomething() { System.out.println("方法1執行..."); doOthers(); }

public synchronized void doOthers() {
    System.out.println("方法2執行...");
}
複製代碼

} 上面的代碼裏面的兩個方法都被synchronized修飾了,由於可重入因此doSomething() 能夠調用doOthers() 的方法 內部維護了一個同步狀態status來記錄重入次數,

獨享鎖與共享鎖 獨享鎖(排它鎖): 該鎖一次只能被一個線程持有, 若是線程T對數據A加上了排它鎖以後, 其它線程不能再對A加任何類型的鎖。線程T能夠讀+寫。JDK中synchronized 和 JUC中的Lock的實現類都是互斥鎖 共享鎖: 該鎖能夠被多個線程持有, 若是線程T對數據A加上共享鎖後, 其餘線程只能對A再加共享鎖, 不能加排它鎖。得到共享鎖的線程只能讀數據, 不能改數據。 若是存在讀鎖,寫鎖不能備貨區,

讀鎖: tryAcquireShared(int unused) 若是其餘線程有寫鎖, 失敗。若是當前線程有寫鎖或寫鎖未被獲取,則當前線程增長讀狀態 + 獲取讀鎖。

談一談對線程安全的理解?

要想編寫線程安全的代碼,核心在於對狀態訪問操做進行管理,特別是對於共享的(變量能夠由多個線程同時訪問)和可變的(變量的值在生命週期內能夠發生變化)狀態的訪問

三種方式能夠保證線程安全: 不在線程之間共享該狀態變量 將狀態變量修改成不可變的變量 在訪問狀態變量時使用同步 synchronized

讀寫鎖的使用 參考資料: 讀寫鎖的實現原理 https://juejin.im/entry/5b2eeaaf6fb9a00e717edce

3.Java類相關 1.內部類 2.抽象類和接口的區別

4.集合接口+底層實現+幾個集合類的對比

List類相關內容: List集合源碼剖析-Java3y

  1. HashMap和HashTable的區別? 共同點: HashMap和HashTable均可以存儲key-value的數據,都實現了Map接口 不一樣點: 1.HashMap是能夠用null做爲key或者value的,而HashTable不能夠 2.HashMap線程不安全, HashTable線程安全 3.HashMap containsValue 和 containsKey, HashTable contains 4.繼承不一樣 HashMap繼承AbstractMap<K,V> , Hashtable<K, V> extends Dictionary<K, V>

使用場景 ConcurrentHashMap一個Map拆分紅了N個小的Segment,每一個Map分別加鎖能夠提升效率 N倍(默認16倍)

2.HashSet 和 TreeSet的區別?

3.Java裏的HashMap, ConcurrentHashMap, 紅黑樹如何實現的? HashMap實現參考美團技術博客 https://tech.meituan.com/java_hashmap.html

ConcurrentHashMap(簡稱Con)參考Java3y

ConcurrentHashMap底層:散列表 + 紅黑樹 和HashMap是相同的 頂部註釋的幾個點: 檢索時是返回的最新設置結果,且是不加鎖的操做可能會和update操做(put, remove)重疊,但保證線程安全 初始化時設置長度能提升效率 不容許key或者value是null Con 和 HashTable區別 HashTable是如今每一個方法上都加入了Synchronized來完成同步,效率低,而Con是經過部分加鎖和CAS(Compare and Swap)算法來實現同步 CAS CPU指令? 什麼是CPU指令? 簡單的流程: 1. 先比較相等 2.只有相等條件下才進行替換

volatile關鍵字: volatile僅用來保證變量對於全部線程的可見性(多線程的環境下,當這個變量修改時,全部的線程都會知道該變量被修改了),但不可以保證操做的原子性(修改變量在JVM中分爲好幾步,在這幾步以內實際上是不安全的)

簡單講講Java中的原子類? Atomic指的是一個操做是不可中斷的,即便在多個線程一塊兒執行時,一個操做一旦開始,就不會被其餘線程干擾 JUC包中的原子類 基本類型 數組類型 引用類型 對象的屬性修改類型

public final int get() //獲取當前的值 public final int getAndSet(int newValue)//獲取當前的值,並設置新的值 public final int getAndIncrement()//獲取當前的值,並自增 public final int getAndDecrement() //獲取當前的值,並自減 public final int getAndAdd(int delta) //獲取當前的值,並加上預期的值 boolean compareAndSet(int expect, int update) //若是輸入的數值等於預期值,則以原子方式將該值設置爲輸入值(update) public final void lazySet(int newValue)//最終設置爲newValue,使用 lazySet 設置以後可能致使其餘線程在以後的一小段時間內仍是能夠讀到舊的值。

AtomicInteger 主要利用CAS + volatile 和native方法來保證原子性

若是在基於鎖的類中包含有細粒度的操做, 那麼當在鎖上存在激烈競爭時,調度開銷與工做開銷的比值會很是高。 解決這個問題 咱們使用原子變量

原子變量類至關於一種泛化的volatile變量, 可以支持原子的和有條件的讀-改-寫操做, 它直接利用了硬件對併發的支持,具備更高的可伸縮性

5.JVM相關 類加載機制: 類從被加載到虛擬機內存中開始 到卸載出內存,整個生命週期包括: 加載,驗證,準備,解析,初始化,使用,卸載7個階段:

前5個階段加載,驗證,準備,解析,初始化 是類加載的極端 https://blog.csdn.net/javazejian/article/details/73413292 https://zhuanlan.zhihu.com/p/25228545 兩道實戰面試題https://www.cnblogs.com/chanshuyi/p/the_java_class_load_mechamism.html

加載: 建立一個class對象 驗證: 確保Class文件的字節流中包含信息符合當前虛擬機要求,不危害虛擬機自身安全。主要包括四種驗證: 文件格式驗證,元數據驗證,字節碼驗證,符號引用驗證 準備: 爲類變量分配內存冰潔設置該類變量的初始值爲0 解析: 將常量池中的符號替換爲直接引用過程 初始化:類加載最後階段,若當前類具備超類,則對其進行初始化

Java Runtime Environment (JRE) 類庫 JVM .java -> .class -> JVM -> 機器碼010101

JVM屬於JRE的一部分

JVM運行時數據區?

數據 + 指令 + 控制 操做系統三大要素

數據: (線程共享) 方法區: 存放被虛擬機加載的類信息、常量、靜態變量、 運行時常量池 Heap: 在虛擬機啓動時建立 用來存放對象實例 垃圾收集器管理的主要區域, 能夠爲物理上不連續的內存空間 指令: (線程獨立 和線程生死同步) 程序計數器: 指向當前線程正在執行的字節碼指令的地址 線程輪流切換、分支、跳轉、異常處理都須要用到 虛擬機棧: 每一個方法執行時候都會建立一個棧幀 存局部變量、操做棧、動態連接、等信息 當前線程運行方法時所須要的數據、指令、返回地址 局部變量表所需內存空間在編譯期間完成分配 本地方法棧 : Native方法

線程: 最小的執行單位

說一下代碼的棧溢出和堆溢出? https://blog.csdn.net/u011983531/article/details/63250

堆溢出: 在建立對象時沒有能夠分配的堆內存 OutOfMemoryError:java heap space 棧溢出: 線程請求的棧深度大於虛擬機所容許的最大深度
虛擬機在擴展棧深度時沒法申請到足夠的內存空間

內存泄露(Memory Leak): 程序沒法釋放已經申請的內存空間 內存溢出(Memory Overflow): 在是申請內存時,沒有足夠的內存空間供其使用, 申請一個integer, 給一個long

memory leak 最終會致使 memory overflow

Java的內存分區? Java的內存模型?

說一下Java的垃圾回收算法? GC要完成的三件事情: 哪些內存須要回收? 引用計數器? 效率還能夠可是沒法解決循環引用的問題 根搜索算法: 經過一些 GC Roots做爲起點,從這些節點開始向下搜索,,當一個對象和GC Roots之間沒有任何引用相連,則證實這個對象不可用 可做爲GC Roots的對象 方法區中類靜態屬性引用的對象 方法區中常量引用的對象 虛擬機棧中引用的對象 本地方法棧中Native方法
根搜索算法中涉及到 引用, Java中的4種引用類型: 強引用 不回收 軟引用 內存溢出錢考慮 弱引用 下一次GC前 虛引用

何時回收? 如何回收?

四種垃圾回收算法: 標記-清除算法 : 標記後清除
缺點: 效率 + 空間 效率不高 空間碎片太多致使沒有足夠大的連續內存來容納分配的大對象 複製算法: 內存分相等兩塊,將小塊複製到大塊,垃圾清除,交替保留 用來回收新生代對象 使用大的Eden 和 小的Survivor 由於90%+對象 死得快 缺點: 空間利用率 折半 標記-整理-清除: 將全部存活對象向一邊移動,清除餘下的內存 分代收集: 新生代-> 複製 由於死的多 老年代 -> 標記清除 或 標記整理清楚 死的少

說一說對volatile變量的理解? volatile能夠看作是最輕量級的同步機制,使用volatile修飾的變量具備特殊的訪問規則,具體來講是兩種特性: 1. 保證此變量對全部線程的可見性 2. 禁止指令重排序優化youhua 6.Java IO多路複用模式

https://www.zhihu.com/question/28594409

數據庫基礎 SQL Online Tutorial W3School http://www.w3school.com.cn/sql/sql_join_inner.asp 1.Inner join, Outer join, Left join, Right join, Full join的區別,返回結果 Inner join: 兩個表取交集,必須同時在兩個表內都匹配 Outer join: 兩個表取並集 Left join: 左邊表所有保留 右邊表若是和左邊表匹配就保留匹配結果,沒有和左邊表匹配的就用NULL 與Left join相反 Full join 全部結果都保留 == Outer join 左邊匹配不上右邊的左邊留空,右邊匹配不上左邊的右邊留空

  1. 數據庫事務的特色: 好比A有500塊 B有500塊 A給B轉帳100塊: 從A中讀取餘額: 500 A中減去100 500 - 100 = 400 結果寫入A帳號的數據庫 從B中讀取餘額 對B帳號作加法操做 500 + 100 = 600 把結果寫入B帳號的數據庫

原子性: 事務包含的全部操做要麼所有成功,要麼所有失敗回滾。保證整個數據庫事務是不可分割的工做單位 上述6步之中,任意一步出現了問題,必須回退到第一步操做以前的狀態。 一致性: 事務必需要使數據庫從一個一致性狀態轉換爲另外一個一致性狀態,事務執行以前和執行以後狀態能夠不一樣,彈藥保持一致 兩個用戶之間的轉帳 和應該保持不變

隔離性(併發控制,可串行化,鎖) :多個用戶併發訪問數據庫時,好比操做同一張表,數據庫爲每個用戶開啓的事務,不可以被其它的事務操做所幹擾。

持久性:一個事務一旦被提交了,那麼對於數據庫中的數據的改變就是永久性的,即使是在數據庫系統遇到故障的狀況下也不該該丟失提交事務的操做。 例子:JDBC操做數據庫時,在提交事務方法以後,提示用戶事務操做完成,那麼即使數據庫出問題,也能夠保證了事務已經徹底被數據庫記錄。

  1. 事務的隔離級別: 原理參考:https://www.cnblogs.com/wajika/p/6680200.html https://www.cnblogs.com/wajika/p/6680196.html https://blog.csdn.net/zht666/article/details/51691958

1.讀取未提交內容 READ UNCOMMITTED: 最低級別的隔離,容許其餘事務看到當前事務未提交的數據,應用不多,由於安全性差且性能並不會提升太多。 產生問題: 髒讀 + 不可重複 + 幻讀 髒讀:讀到了未提交的數據 事務對當前被讀取的數據不加鎖; 事務在更新某數據的瞬間(就是發生更新的瞬間),必須先對其加 行級共享鎖,直到事務結束才釋放。

2.讀取提交內容 READ COMMITTED:保證當前事務的數據只有在被提交以後才能被另外一個數據讀取。 產生問題:不可重複讀 在同一個事務中執行徹底相同select語句能夠看到不同的結果。 可能緣由: 1. 一個交叉的事務有新的commit, 致使數據改變 2. 一個數據庫被多個實例操做,使得同一事務的其餘實例在該事務處理期間有新的commit 事務對當前被讀取的數據加 行級共享鎖(當讀到時才加鎖),一旦讀完該行,當即釋放該行級共享鎖; 事務在更新某數據的瞬間(就是發生更新的瞬間),必須先對其加 行級排他鎖,直到事務結束才釋放。

3.可重讀 REPEATABLE READ:保證同一事務的多個實例在併發讀取數據時,看到相同的數據行 產生問題:幻讀(Phantom Read) : 當用戶讀取某一個範圍內的數據行時,另外一個事務又在該範圍內插入了新行,當用戶再次讀取該範圍的數據時,會發現有新的幻影行產生 事務在讀取某數據的瞬間(就是開始讀取的瞬間),必須先對其加 行級共享鎖,直到事務結束才釋放; 事務在更新某數據的瞬間(就是發生更新的瞬間),必須先對其加 行級排他鎖,直到事務結束才釋放。

4.可串行化 SERIALIZABLE:最高級別的隔離,經過強制事務排序,使事務之間不可以相互衝突,從而解決幻讀的問題,在每一個讀的數據行上加上共享鎖 產生問題: 膽量的超時現象和鎖競爭

事務在讀取數據時,必須先對其加 表級共享鎖 ,直到事務結束才釋放; 事務在更新數據時,必須先對其加 表級排他鎖 ,直到事務結束才釋放。

4.數據庫的三個範式 1NF: 列不可再分 2NF: 3NF: 一個數據庫表中不包含已經在其餘表中已包含的非主鍵信息 (外鍵)

5.數據庫的索引和索引底層數據結構?B數和B+樹的區別? 參考資料: mysql索引的數據結構 https://www.jianshu.com/p/1775b4ff123a

MySQL索引使用的數據結構主要有BTree索引 和 哈希索引 BTree M階的B-Tree要知足 每一個節點最多有M個孩子 除根節點和葉節點外,其它每一個節點有M/2個孩子

對於每一個節點主要包含一個關鍵字數組Key[],一個指針數組(指向兒子)Son[]

彙集索引: 表中數據按照索引的順序存儲 非彙集索引: 表中數據存儲順序與索引順序無關

讀書筆記 《MySQL技術內幕第二版》

第六章 鎖 共享鎖(S Lock): 容許事務讀一行數據 排他鎖(X Lock): 容許事務刪除或更新一行數據 鎖兼容(Lock Compatible): 事務T1 得到行r1 的共享鎖, T1 T2都想要讀r1, 沒有問題, T2也可以獲得r1的共享鎖, 但若是T3想要得到行r的排他鎖,等T1 T2 釋放r1的共享鎖,鎖不兼容

鎖定級別:排他鎖 > 共享鎖 排他鎖要等共享鎖, 兼容指的是對於同一行記錄的鎖

多粒度鎖定: 容許對行級別和表級別的鎖同時存在。爲了支持不一樣粒度,InnoDB存儲引擎支持額外的鎖方式,稱爲意向鎖(Intention Lock IX), 意向鎖將鎖定的對象分爲多個層次。

第七章 事務 事務是數據庫區別於文件系統的特徵,文件系統中,正在寫文件時,若是操做系統崩潰,那麼文件就可能被損壞。可是事務只會把數據庫從一種一致狀態轉移到另外一種一致狀態。 【感受事務就是讓顆粒度更大】 事務能夠是一條很是簡單的SQL語句,也能夠是一組複雜的SQL語句,事務是訪問並更新數據庫中各類數據項的一個程序執行單元。

網絡基礎

參考資料: TCP相關 https://www.jianshu.com/p/65605622234b 計算機網絡相關知識點總結 傳輸層: 提供進程和進程之間的邏輯通訊 能夠調用下層網絡層的服務: 實現主機與主機之間的邏輯通訊 複用: 分用 差錯檢查 端口: 標識主機中的應用進程 總共有16bit 服務端 客戶端 49152 FTP 21 TELNET 23 DNS 53 HTTP 80 套接字: Socker = (主機IP地址和端口號) 惟一標識了網絡中的主機和它上面的一個進程

UDP是無鏈接的,減小開銷和發送數據以前的是 1.TCP和UDP連接協議相關 User Datagram Protocol 用戶數據報 無鏈接的,減小開銷和發送前的延長 UDP使用最大努力交付,不保證可靠交付 面向報文的, 對於應用層傳來的數據包不作任何切割和處理,保留整個應用層報文到UDP報文中 沒有擁塞控制,適合實時應用 首部開銷 8B 首部格式: 2B * 4 16位源端口號 目的地端口號 UDP長度 UDP檢驗和

Transmission Control Protocol 傳輸控制協議 面向鏈接 只能有兩個端點,鏈接點對點 提供可靠交付的服務、 全雙工通訊 面向字節流: 文件被標記爲字節 TCP把應用程序交下來的數據當作僅僅是一連串的無結構字節流

TCP報文段

固定字段是20B, 此外還有選項字段 長度可變 總長度 = 固定字段 +選項字段 源端口 目的端口 16bit * 2 = 32 bit = 8B 序號 32bit : 表示本報文段所發送數據的第一個字節的序號 確認號 32bit: 指望收到對方下一個報文段的第一個數據字節序號, 若確認號爲N, 則證實到序號N - 1爲止全部數據都已經收到 數據偏移(首部長度): TCP報文段的數據起始距離 TCP報文段的起始處有多遠, 以4B爲單位 6個控制位: SYN = 1 代表是一個鏈接請求/鏈接接受報文 URG = 1 緊急字段, 表示該報文段很緊急, 要求最早處理 ACK = 1 確認號有效, 創建鏈接後, 全部傳送的報文段都必須將ACK設置爲1 FIN = 1 代表此報文段發送方數據已經發完, 要求釋放鏈接

TCP和UDP的區別 使用場景?

TCP的應用場景: 要求通訊數據準確可靠 萬維網HTTP 郵件 SMTP 文件傳輸 FTP 遠程終端接入 TELNET 大文件 有確認、流量控制、計時器及鏈接管理 UDP的應用場景: 對通訊及時性要求較高的時候 小文件 QQ語音、直播 盡最大努力交付的協議

1.TCP如何保證傳輸是安全的,TCP如何保證可靠傳輸?TCP的加密機制? 可靠: 保證接收方進程從緩存區中讀出的字節流與發送方發出的字節流是徹底同樣的 四種可靠傳輸的機制: 校驗: 與UDP校驗同樣, 增長僞首部 序號: 確認: 默認使用累計確認 來返回確認號字段 重傳: 經過確認號字段來確認 超時重傳: TCP的發送方在規定時間(也叫作重傳時間)內沒有收到確認就重傳已經發送的報文段 自適應算法 動態改變重傳時間RTTs

冗餘ACK(冗餘確認): 每當比指望序號大的失序報文段到達時, 發送一個冗餘ACK, 致命下一個期待字節的序號

快速重傳: 當發送方收到3個對於報文段1的冗餘ACK -> 認爲2報文段丟失,重傳2號報文段 TCP的無差錯傳輸?

參考講解: https://www.youtube.com/watch?v=MrZVMLppgNU&index=41&list=PLO-vrUGI62psPscir0dZPfavFm-9l84iY

基本概念: 滑動窗口協議 發送窗口 接收窗口

實現無差錯傳輸的解決方案: 核心思想:採用一些可靠傳輸協議,使得

出現差錯時,讓發送方重傳差錯數據:即 出錯重傳 當接收方來不及接收收到的數據時,可通知發送方下降發送數據的效率:即 速度匹配

方案1: 自動重傳請求 方案2: 流量控制 & 擁塞控制 擁塞控制的四種算法: 假定: 數據單方向傳送,而另外一個方向只傳送確認

慢開始 擁塞避免 快重傳: 當收到了3個重複的確認 就執行快重傳算法 重複的確認會在包丟失的時候發生 快恢復 傳輸輪次: RTT 一個往返時延 一批報文發送到接收到確認的時間 接收窗口: 接收方制定 自身能力 擁塞窗口: 發送方根據網絡狀況 設定的發送能力

開始階段: 指數增加 達到一個閾值後進入線性增加,加法增大 當遇到了網絡擁塞時, 將閾值從新設定爲當前報文段數量 / 2 擁塞窗口初始值 cwnd = 1 一個報文段 MSS

不降到1, 而降到閾值

2.TCP三次握手過程 客戶端TCP先向服務器端TCP發送一個特殊的TCP報文段,該報文段不包含應用層數據。在報文段首部中一個標誌位(SYN比特)標記爲1, 並選擇一個隨機的初始序號,並將此編號放置於起始的SYN序號字段中,該報文段會被封裝在一個IP數據報中,併發送給服務器。 客戶端進入SYN_SENT狀態 seq = x(隨機) 並不起做用,由於沒有應用層數據 當服務器收到客戶端發出的SYN報文段後,服務器會從數據報中提取出SYN報文段,併爲該TCP鏈接分配TCP緩存和變量,同時發送一個容許鏈接的SYN報文,包含三個重要信息: 1. SYN位比特設置爲1 2.該報文段首部的確認號字段設置爲client_isn + 1 3.服務器將本身的server_isn放置到TCP報文段首部序號字段中。SYNACK報文段 服務器進入SYN_RECV狀態
在收到SYNACK報文段後,客戶也要給該鏈接分配緩存和變量。並向服務器發送一個確認的報文 確認字段設定爲server_isn + 1, SYN位 = 0。ESTABLISHED

爲何須要三次握手? 防止服務器由於不合理的鏈接請求一直在等待 客戶端的請求 浪費資源

TCP報文字段

  1. 關閉鏈接四次揮手的過程

任何一端均可能終止鏈接。 1.請求關閉的一端發送一個FIN 比特設定爲1的報文 2.服務器端發送確認報文ACK 進入FIN_WAIT1 3.再次發送FIN比特 FIN_WAIT2 4.當收到FIN比特的同時發送確認報文ACK Client不會當即關閉,而是進入TIME_WAIT狀態等待2MSL時間長(一個回覆+一個發送所需的時間),咱們假定網絡是不可靠的,最後的ACK報文可能會丟失,因此須要進行等待。 Server若是沒有收到ACK,將不斷重複發送FIN片斷,若是在TIME_WAIT等待過程當中Client收到了FIN,會再多等待2MSL.

4.四次揮手的緣由 -由於網絡不可靠報文會丟失 爲了保證客戶端發送的最後一個斷開鏈接的報文可以到達服務器

極可能並不會當即關閉SOCKET,因此只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。可是可能不會當即關閉Server,只有等待全部的報文都發送後再發送一個FIN爲1的報文確承認以關閉。

報文可以到達服務器 TCP中的擁塞控制? 2.HTTP與HTTPS相關 簡單介紹一下HTTP協議? HTTP: HyperText Transfer Protocol 超文本傳輸協議 屬於應用層的協議,做用是爲了肯定進程之間通訊標準,特色是無鏈接、無狀態、傳輸格式簡單、可靠性和兼容性好

HTTP報文結構 請求行(Request Line): 請求方法、主機域名、資源路徑&版本協議 請求頭(Headers): 聲明 客戶端|服務器 的部分基本信息 請求體(Body): 發送的數據信息

通用的報文頭:

請求頭:

響應頭:

HTTP的一些缺點: 通訊使用明文(不加密), 內容可能會被竊聽 應對方案: SSL(Secure Socket Layer, 安全套接層) 加密HTTP的通訊內容,用SSL簡歷安全通訊線路後,能夠在該線路上進行HTTP通訊 不驗證通訊方的身份,可能會遭遇假裝 HTTP協議中的請求和響應不會對通訊方進行確認,也就是說存在沒法確認相似 「服務器是否就是發送請求中URI真正制定的主機?」「響應是否返回到真正的客戶端?」 等問題 會產生DoS攻擊(Denial of Service 拒絕服務攻擊) 應對方案: 查證書, 證書是由值得信任的第三方機構頒發的,用來證實服務器和客戶端是實際存在的

沒法證實報文的完整性,有可能遭遇篡改。沒法證實完整也就等於沒法判斷信息是否準確,有沒有僞造的信息?會產生MITM(Man in the Middle attack) 中間人攻擊,在請求或相應的傳輸中途遭到篡改,沒法肯定客戶端想要下載的文件就是服務器上的文件應對方案: MD5 和 SHA-1散列值校驗 或確認文件的數字簽名

HTTP + 加密+ 認證 + 完整性保護 = HTTPS

3.在瀏覽器中輸入一個URL的全過程 查詢瀏覽器緩存 DNS, 獲取域名對應的IP地址 先檢查本地hosts文件-> 本地DNS解析器緩存 -> 本地DNS 瀏覽器與服務器經過三次握手創建TCP鏈接 瀏覽器想服務器發送HTTP請求, 應用層 - 傳輸層 -網絡層 - 數據鏈路層 - 物理層 服務器收到請求後, 根據路徑參數和後端的處理生成html代碼返回給瀏覽器 瀏覽器獲得完整HTML後進行解析和渲染 瀏覽器發送AJAX請求

用到的協議:TCP IP OPSF:用來肯定路由選擇的 ARP:將IP地址轉換爲MAC地址

  1. Session 和 Cookie的區別: Session 跟蹤是Web程序中經常使用的技術,用來跟蹤用戶的整個會話。 Cookie是在客戶端記錄信息肯定用戶身份,而Session是在服務器端記錄信息肯定用戶身份, Session的實現依賴於Cookie, seesionId

cookie存放在瀏覽器端,session用在服務器端

cookie不太安全,別人能夠分析存放在本地的cookie進行cookie欺騙,考慮到安全應當使用session. session會在必定時間內保存在服務器上,當訪問增多,會佔用服務器的性能,若是想要減輕服務器壓力,考慮使用cookie

應用場景: 登陸信息等重要信息放在session之中,而其餘須要保留的信息可使用cookie, 購物車最好使用cookie, 可是cookie是能夠在客戶端禁用的,可使用cookie + 數據庫的實現,若是cookie不能取數據時,就從客戶端獲取

https://juejin.im/entry/5766c29d6be3ff006a31b84e

ping命令使用的網絡協議? DNS : 域名 -> IP ARP: IP -> MAC 地址 ICMP: 用來測試另外一臺主機是否聯通 Internet Control Message Ptotocol 是TCP/IP協議族的一個子協議,用於在IP主機、路由器之間傳遞控制消息。控制消息是指網絡通不通、主機是否可達、路由是否可用等網絡自己的消息。 斷點續傳功能如何實現?

HTTP1.1協議(RFC2616)中定義了斷點續傳相關的HTTP頭 Range和Content-Range字段,一個最簡單的斷點續傳實現大概以下: 1.客戶端下載一個1024K的文件,已經下載了其中512K 2. 網絡中斷,客戶端請求續傳,所以須要在HTTP頭中申明本次須要續傳的片斷: Range:bytes=512000- 這個頭通知服務端從文件的512K位置開始傳輸文件 3. 服務端收到斷點續傳請求,從文件的512K位置開始傳輸,而且在HTTP頭中增長: Content-Range:bytes 512000-/1024000 而且此時服務端返回的HTTP狀態碼應該是206,而不是200。

若是在這期間文件出現了改動,能夠經過Last-Modified Header 實現Last-Modified來標識文件的最後修改時間,這樣便可判斷出續傳文件時是否已經發生過改動 終端在發起續傳請求時應該在HTTP頭中申明If-Match 或者If-Modified-Since 字段,幫助服務端判別文件變化

存取方式 隱私策略 有效期 服務器壓力不一樣 瀏覽器支持 跨域支持 Spring框架基礎

學習一種框架最早須要知道的是爲何須要使用這個框架, 任何一個框架的發明都是爲了解決編程的痛點。

Don’t Repeat Yourself 原則 抽象爲方法, 抽象爲類, 抽象爲多個類的組合(容器類) 是爲了幫助咱們編寫代碼而被設計出來的 設計模式級別的抽象(對於具有必定規模的代碼纔有效) 框架層面上的應用

設計模式的使用場景: 舉例: 一個簡單的數據庫事務,雖然只有一個查詢和一個更新,可是想要將其繼續簡化卻並不容易,雖然其中有關於業務邏輯的部分只是少許幾行代碼,可是初始化,異常,提交,回滾操做讓咱們很難抽取出一個合適的方法來。

咱們發現之因此咱們難以抽取方法,主要是由於流程,由於裏面牽扯到流程控制,而流程控制通常是由咱們程序員來控制的,因此也就必然須要咱們手動編碼來完成。

框架其實就是一個或一組特殊的類庫,特殊在什麼地方?特殊在控制權轉移!

JavaWeb的發展脈絡: 靜態網頁時代 Servlet時代 JSP包打天下的時代 Servlet + JSP 時代 MVC模式時代

Spring的第一步 理解IOC 和 AOP, 而後學習Spring MVC即便就是Java EE開發? 什麼是Java EE?

Tomcat Tomcat提供可以讓別人遠程訪問本身寫的頁面的一個程序

1.Spring的理解? IOC + AOP 爲何要把建立對象交給Spring容器?

Spring是一個J2EE開源框架,核心思想是IOC和AOP。 Spring讓java開發模塊化,而且能夠全面貫穿邏輯層,表現層與持久層。讓每個功能模塊均可以獨立分開,下降耦合,提升代碼複用率。爲簡化企業級應用開發而生, 使用Spring可使得簡單的JavaBean實現之前只有EJB才能實現的功能。

聲明式事務?? 輕量級: Spring是非侵入式的,用Spring不須要實現任何藉口,繼承父類就可以使用 依賴注入(DI - dependency injection, IOC) 面向切面編程: AOP-aspect oriented programming 一站式: 在IOC和AOP的基礎上能夠整合各類企業應用的開源框架和優秀的第三方類庫(Spring實現了展示層的SpringMVC和持久層的Spring JDBC)

搭建環境: 將下面的包加入到工程中的classpath下面 Spring的配置文件: 一個或多個配置文件, 用於在Spring IOC容器裏配置Bean, Bean的配置文件能夠放在ClassPath下, 也能夠在其它目錄下 spring-beans spring-core spring-context spring-expression

Spring bean configuration file applicationContext.xml

  1. 建立SpringIOC容器對象 ApplicationContext ctx = new ClassPathXmlApplicationContext(「applicationContext.xml」);

ApplicationContext表明Spring裏面的IOC容器,是一個接口, ClassPathXmlApplicationContext 表示配置文件在類路徑下 applicationContext.xml 配置文件的名字

  1. 從IOC容器中獲取Bean實例 HelloWorld helloWorld = (HelloWorld) ctx.getBean(「helloWorld」); bean 名字 = getBean() 是重載方法

建立容器的時候會進行一個初始化方法 以及調用set方法

幾個基本問題: 什麼是ServletContext, 和tomcat等web容器的關係是什麼? 依賴注入,控制反轉和非侵入式。

Servle

工廠設計模式: 參考Java3y

簡單/靜態工廠模式 工廠方法模式 抽象工廠模式 爲何要用工廠模式,工廠模式的好處是什麼?工廠模式衍生出的三種形式是什麼?

舉例: 讀取文件須要調用BufferReader方法 讓建立對象變得簡單並且修改對象時能很方便呢? 工廠將建立對象的過程給屏蔽了

public class ReaderFactory { public static Reader getReader() throws FileNotFoundException { File file = new File("aa.txt"); FileReader fileReader = new FileReader(file); BufferedReader reader = new BufferedReader(fileReader); return reader; } }

public class FileOperateA {

public static void main(String[] args) throws FileNotFoundException {


    //-------我有工廠了,還用本身搞嗎?不用了!
    //File file = new File("aa.txt");
    //FileReader fileReader = new FileReader(file);
    //BufferedReader bufferedReader = new BufferedReader(fileReader);
    //-------我有工廠了,還用本身搞嗎?不用了!

    // 用工廠來建立出對象
    Reader reader = ReaderFactory.getReader();

    // 讀寫文件....
}
複製代碼

}

linux基礎 用戶權限相關的命令

線程和進程的區別: 進程是具備必定獨立功能的程序關於某個數據集合上的運行活動, 進程是系統進行資源分配和調度的獨立單位。

線程是進程的一個實體,CPU調度和分派的基本單位,比進程更小,基本上本身不擁有系統資源,只擁有程序運行必不可少的資源(程序計數器,寄存器,棧),能夠同屬一個進程的其它線程共享進程的資源,提升程序的運行效率。

一個線程能夠建立和撤銷另外一個線程,同一個進程中多個線程能夠併發執行。每一個獨立的線程有一個程序運行的入口、順序執行序列和程序的出口,可是線程不可以獨立執行。

JUC java.util.concurrent

ThreadLocal類 經過將共享數據封裝爲不共享數據來保證同步,被稱爲線程封閉,常應用於JDBC的Connection對象 將JDBC的鏈接保存到ThreadLocal對象中,每一個線程都會擁有屬於本身的鏈接

synchronized關鍵字以及實現原理 能夠修飾 1.普通方法 2.靜態方法 3.代碼塊

synchronized關鍵字通過編譯後,會在同步塊的先後分別造成moniterenter和monitorexit兩個字節碼指令,這兩個字節碼指令須要一個reference類型參數來致命要鎖定和解鎖的對象,獲取對象的鎖,沒被鎖定或當前線程已經擁有那個對象的鎖,就把鎖的計數器加一,執行monitorexit指令時將計數器-1。

Java中的鎖結構

悲觀鎖(適合寫多讀少)/樂觀鎖(適合寫少讀多): 本身用數據的時候必定有/沒有別的線程來修改數據,要/不要在獲取數據的時候加上鎖 補充: 樂觀鎖修改數據時不加鎖,只會在更新數據的時候判斷以前有沒有別的線程更新了該數據,若是沒有更新,將本身的修改寫入,不然執行其餘操做(報錯或重試) synchronized關鍵字和Lock實現類都是悲觀鎖, 關係型數據庫中也常見,好比行級鎖,寫入鎖都在操做以前上鎖

樂觀鎖最常採用CAS算法來實現, CAS全稱Compare And Swap, 是一種無鎖算法,在不使用鎖的狀況下實現多線程之間的變量同步,atomic類就經過CAS來實現樂觀鎖

CAS用到三個操做數字: 內存值V, 進行比較的值A,須要寫入的新值B, 當前僅當V的值等於A時,CAS經過原子方式用新值B更新V。

潛在問題:

  1. ABA問題,看似沒變其實變了又變, 打時間戳
  2. 循環時間開銷大
  3. 只能保證對於一個共享變量的原子操做

JUC 類圖 是爲java併發編程設計的工具類: locks 提供顯式鎖相關功能 atomic 提供原子變量功能,構建非阻塞算法基礎 executor 提供線程池功能 collections 提供併發容器功能 tools 提供同步工具類,如信號量,閉鎖,柵欄等功能

數據結構基礎 設計一個高效率獲取第K大和前K個元素的數據結構 實現HashMap

OO Design Design Twitter 實現

算法基礎

基礎排序算法

手寫快排 public class Quick { private Quick() {}

private static void sort(int[] a, int lo, int hi) {
	if (hi <= lo) return;
	int pivot = partition(a, lo, hi);
	sort(a, lo, pivot - 1);
複製代碼

sort(a, pivot + 1, hi); }

private static int partition(int[] a, int lo, int hi) { int i = lo; int j = hi + 1; int v = a[lo]; // select first element as the pivot point while (true) { while (a[++i] < v)) { if (i == hi) break; } // 停在了從左邊數起第一個比v大的元素 (out of place) while (v < a[--j]) { if (j == lo) break; } //停在了從右邊數起第一個比v小的元素 (out of place) if (i >= j) break; swap(a, i, j); } // 如今的j停在了比 v小的全部元素中的最後一個元素 swap(a, lo, j); return j; // j 和 lo交換以後 v就回到了應該在的位置 }

private static void swap(int[] a, int i, int j) { int swap = a[i]; a[i] = a[j]; a[j] = swap; }

public static void main(String[] args) { int[] a = new int[]{1, 97, 3, 45, 5, 8}; Quick.sort(a, 0, a.length - 1); }

}

手寫堆排序? void heapSort(int[] arr, int n){ for (int i = n / 2 - 1; i >= 0; i--) { heapify(arr, n, i); // creates a max heap } for (int i = n - 1; i >= 0; i--) { swap(arr[0], arr[i]); // swap first and last node heapify(arr, i, 0); } }

手寫歸併排序

不一樣排序算法的時間複雜度?排序的穩定性?

https://zhuanlan.zhihu.com/p/36120420 https://blog.csdn.net/u010983881/article/details/76383527

堆排序、快速排序、希爾排序、直接選擇排序不是穩定的排序算法; 基數排序、冒泡排序、直接插入排序、折半插入排序、歸併排序是穩定的排序算法。

穩定性定義:排序先後兩個相等的數相對位置不變,則算法穩定。 詳解: 冒泡排序 小的元素向前或大的元素向後, 比較的對象也是相鄰的兩個元素 -> 穩定 選擇排序 每一個位置都選擇當前最小的,若是一趟選擇中,當前元素比一個元素小,而小的元素前一個元素又和要交換的值相等,穩定性被破壞 例如:序列5 8 5 2 9, 咱們知道第一遍選擇第1個元素5會和2交換,那麼原序列中2個5的相對先後順序就被破壞了 -> 不穩定 插入排序 在已經有序的序列上作操做,一次插入一個元素, 想要插入的元素和已經有序的最大者開始比較,若是比它大直接插入到其後面,不然一致向前找直到找到該插入的位置,若是遇見相等的,放在相等的後面,先到先得 快速排序 中樞元素交換的時候會打破穩定性 舉例: 序列爲 5 3 3 4 3 8 9 10 11, 如今中樞元素5和3(第5個元素,下標從1開始計)交換就會把元素3的穩定性打亂 歸併排序 穩定 堆排序 堆的結構是節點i的孩子爲2 * i 和 2 * i +1節點,大頂堆 void heapSort(int[] arr, int n) { for 9

海量數據處理 大量的url如何去重? 1.若是內存夠用,將url做爲key存入hash表 將hash值做爲value, HashSet 去重

找數字類: 在內存不夠的狀況下,如何從 2億個整數中找出不重複的整數? 40億個非負整數中找出全部沒有出現過的數字? 最多使用1GB內存

2-Bitmap方法: 對於每個整數分配2bit 00表明沒出現 01表明出現一次 10表明出現兩次 11無心義 , 掃描2億個整數, 並修改Bitmap中對應位, 00 -> 01 10 -> 11 10不變, 掃描結束後,輸出對應位爲 01的全部整數

32位無符號整數範圍 0 - 4294967295 2^32 = 4 294 967 296 * 2 bit
1GB = 8 000 000 000 bit = 1 000 000 000 B

哈希表 key: 數字 value: 該數字出現的次數 32位整數取值(0 - 42億) 4B key 和 value都是4B就足夠, 那麼一條Hash表的記錄就是8B, 當哈希表的記錄數爲40億個時,40億 × 8 = 320億字節 = 32 GB內存 內存中放不下, 改成BitMap來記錄 2^32 / 8 = 2 ^ 29 = 536870912 大概500MB 掃描這個40億個數,將每一個數對應位的0 -> 1,最後掃一遍BitMap, 其中bit位爲0的就是沒出現的數字, 返回該數字便可。

進階: 若是隻給10MB內存,找到40億中一個沒出現的數字? 由於 500MB/64 < 10MB 因此將40億個數分爲64個區間, 4 294 967 296 / 64 = 67108864個數字, 統計落在每一個區間上的數字有多少, 確定有一個區間上的計數小於67108864, 而後找到這個區間以後,再按照0 / 1 對應每一個數字 此次的索引是 [num - 67108864 * N] N爲區間的序號

Amazon OA面經

OA1 Debug:. check 1point3acres for more. https://www.evernote.com/client/ ... %2F636f07d57c2eb3ea

Reasoning: https://www.evernote.com/client/ ... %2F0ebd7ed6e9399009

file:///home/auguskong/Downloads/AmazonOA%E6%95%B4%E7%90%862019.02.pdf

OA2

https://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=480213&extra=page%3D1%26filter%3Dsortid%26sortid%3D311%26orderby%3Ddateline%26sortid%3D311%26orderby%3Ddateline https://docs.google.com/document/d/1uQAAe21jQzJiuNzJs2WZ7bdzM5Rx2gHiRghflLxEx8c/edit?usp=sharing

Longest Palindrome Substring
Most Common Word
複製代碼
  1. Longest Substring with At Most K Distinct Characters sliding window Dungeon Game
  2. Subtree with Maximum Average class ResultType { TreeNode node; int sum; int size; public ResultType(TreeNode node, int sum, int size) { this.node = node; this.sum = sum; this.size = size; } } private ResultType result = null; 找出全部長度爲K, 含有K-1個不一樣字符的子串

https://leetcode.com/discuss/interview-question/124652/Amazon-onsite-interview-question

https://github.com/jayshah19949596/CodingInterviews/tree/master/Amazon%20SDE%20-%201%20-%20FBA%20Team

https://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=480213 https://drive.google.com/file/d/1TjufxeW4LZzfsGfzJ9dPU2lJqGMMEC3d/view

subStringLessKDist getFastestComponent

given an array of n point, and the problem is to find out the top k closest pair of points in the array.

Shorest Path

  • Given a M*N array. 1point3acres
  • Start from right left corner, end at 9
  • Path can only build on value of 1
  • Find the shortest path from the start to target

https://www.1point3acres.com/bbs/forum.php?mod=viewthread&tid=485925&extra=page%3D3%26filter%3Dsortid%26sortid%3D311%26searchoption%5B3046%5D%5Bvalue%5D%3D5%26searchoption%5B3046%5D%5Btype%5D%3Dradio%26sortid%3D311%26orderby%3Ddateline

相關文章
相關標籤/搜索