Python 面試題(下)

接上篇。html


網絡node


1 三次握手python


  1. 客戶端經過向服務器端發送一個SYN來建立一個主動打開,做爲三路握手的一部分。客戶端把這段鏈接的序號設定爲隨機數 A。linux

  2. 服務器端應當爲一個合法的SYN回送一個SYN/ACK。ACK 的確認碼應爲 A+1,SYN/ACK 包自己又有一個隨機序號 B。nginx

  3. 最後,客戶端再發送一個ACK。當服務端受到這個ACK的時候,就完成了三路握手,並進入了鏈接建立狀態。此時包序號被設定爲收到的確認號 A+1,而響應則爲 B+1。web


2 四次揮手面試


3 ARP協議算法


地址解析協議(Address Resolution Protocol): 根據IP地址獲取物理地址的一個TCP/IP協議數據庫


4 urllib和urllib2的區別apache


這個面試官確實問過,當時答的urllib2能夠Post而urllib不能夠.


  1. urllib提供urlencode方法用來GET查詢字符串的產生,而urllib2沒有。這是爲什麼urllib常和urllib2一塊兒使用的緣由。

  2. urllib2能夠接受一個Request類的實例來設置URL請求的headers,urllib僅能夠接受URL。這意味着,你不能夠假裝你的User Agent字符串等。


5 Post和Get


GET和POST有什麼區別?及爲何網上的多數答案都是錯的(http://www.cnblogs.com/nankezhishi/archive/2012/06/09/getandpost.html)


get: RFC 2616 – Hypertext Transfer Protocol — HTTP/1.1(http://tools.ietf.org/html/rfc2616#section-9.3)

post: RFC 2616 – Hypertext Transfer Protocol — HTTP/1.1(http://tools.ietf.org/html/rfc2616#section-9.5)


6 Cookie和Session



session技術是要使用到cookie的,之因此出現session技術,主要是爲了安全。


7 apache和nginx的區別


nginx 相對 apache 的優勢:


  • 輕量級,一樣起web 服務,比apache 佔用更少的內存及資源

  • 抗併發,nginx 處理請求是異步非阻塞的,支持更多的併發鏈接,而apache 則是阻塞型的,在高併發下nginx 能保持低資源低消耗高性能

  • 配置簡潔

  • 高度模塊化的設計,編寫模塊相對簡單

  • 社區活躍


apache 相對nginx 的優勢:


  • rewrite ,比nginx 的rewrite 強大

  • 模塊超多,基本想到的均可以找到

  • 少bug ,nginx 的bug 相對較多

  • 超穩定


8 網站用戶密碼保存


  1. 明文保存

  2. 明文hash後保存,如md5

  3. MD5+Salt方式,這個salt能夠隨機

  4. 知乎使用了Bcrypy(好像)加密


9 HTTP和HTTPS



403: Forbidden

404: Not Found


HTTPS握手,對稱加密,非對稱加密,TLS/SSL,RSA


10 XSRF和XSS


  • CSRF(Cross-site request forgery)跨站請求僞造

  • XSS(Cross Site Scripting)跨站腳本攻擊


CSRF重點在請求,XSS重點在腳本


11 冪等 Idempotence


HTTP方法的冪等性是指一次和屢次請求某一個資源應該具備一樣的反作用。(注意是反作用)


GET http://www.bank.com/account/123456,不會改變資源的狀態,不論調用一次仍是N次都沒有反作用。請注意,這裏強調的是一次和N次具備相同的反作用,而不是每次GET的結果相同。GET http://www.news.com/latest-news這個HTTP請求可能會每次獲得不一樣的結果,但它自己並無產生任何反作用,於是是知足冪等性的。


DELETE方法用於刪除資源,有反作用,但它應該知足冪等性。好比:DELETE http://www.forum.com/article/4231,調用一次和N次對系統產生的反作用是相同的,即刪掉id爲4231的帖子;所以,調用者能夠屢次調用或刷新頁面而沒必要擔憂引發錯誤。


POST所對應的URI並不是建立的資源自己,而是資源的接收者。好比:POST http://www.forum.com/articles的語義是在http://www.forum.com/articles下建立一篇帖子,HTTP響應中應包含帖子的建立狀態以及帖子的URI。兩次相同的POST請求會在服務器端建立兩份資源,它們具備不一樣的URI;因此,POST方法不具有冪等性。


PUT所對應的URI是要建立或更新的資源自己。好比:PUT http://www.forum/articles/4231的語義是建立或更新ID爲4231的帖子。對同一URI進行屢次PUT的反作用和一次PUT是相同的;所以,PUT方法具備冪等性。


12 RESTful架構(SOAP,RPC)


推薦: http://www.ruanyifeng.com/blog/2011/09/restful.html


13 SOAP


SOAP(原爲Simple Object Access Protocol的首字母縮寫,即簡單對象訪問協議)是交換數據的一種協議規範,使用在計算機網絡Web服務(web service)中,交換帶結構信息。SOAP爲了簡化網頁服務器(Web Server)從XML數據庫中提取數據時,節省去格式化頁面時間,以及不一樣應用程序之間按照HTTP通訊協議,聽從XML格式執行資料互換,使其抽象於語言實現、平臺和硬件。


14 RPC


RPC(Remote Procedure Call Protocol)——遠程過程調用協議,它是一種經過網絡從遠程計算機程序上請求服務,而不須要了解底層網絡技術的協議。RPC協議假定某些傳輸協議的存在,如TCP或UDP,爲通訊程序之間攜帶信息數據。在OSI網絡通訊模型中,RPC跨越了傳輸層和應用層。RPC使得開發包括網絡分佈式多程序在內的應用程序更加容易。


總結:服務提供的兩大流派.傳統意義以方法調用爲導向通稱RPC。爲了企業SOA,若干廠商聯合推出webservice,制定了wsdl接口定義,傳輸soap.當互聯網時代,臃腫SOA被簡化爲http+xml/json.可是簡化出現各類混亂。以資源爲導向,任何操做無非是對資源的增刪改查,因而統一的REST出現了.


進化的順序: RPC -> SOAP -> RESTful


15 CGI和WSGI


CGI是通用網關接口,是鏈接web服務器和應用程序的接口,用戶經過CGI來獲取動態數據或文件等。

CGI程序是一個獨立的程序,它能夠用幾乎全部語言來寫,包括perl,c,lua,python等等。


WSGI, Web Server Gateway Interface,是Python應用程序或框架和Web服務器之間的一種接口,WSGI的其中一個目的就是讓用戶能夠用統一的語言(Python)編寫先後端。


官方說明:PEP-3333


16 中間人攻擊


在GFW裏家常便飯的,呵呵.


中間人攻擊(Man-in-the-middle attack,一般縮寫爲MITM)是指攻擊者與通信的兩端分別建立獨立的聯繫,並交換其所收到的數據,使通信的兩端認爲他們正在經過一個私密的鏈接與對方直接對話,但事實上整個會話都被攻擊者徹底控制。


17 c10k問題


所謂c10k問題,指的是服務器同時支持成千上萬個客戶端的問題,也就是concurrent 10 000 connection(這也是c10k這個名字的由來)。

推薦: http://www.kegel.com/c10k.html


18 socket


推薦: http://www.cnblogs.com/bingyun84/archive/2009/10/16/1584387.html


Socket=Ip address+ TCP/UDP + port


19 瀏覽器緩存


推薦: http://web.jobbole.com/84367/


304 Not Modified


20 HTTP1.0和HTTP1.1


推薦: http://blog.csdn.net/elifefly/article/details/3964766


  1. 請求頭Host字段,一個服務器多個網站

  2. 長連接

  3. 文件斷點續傳

  4. 身份認證,狀態管理,Cache緩存


21 Ajax


AJAX,Asynchronous JavaScript and XML(異步的 JavaScript 和 XML), 是與在不從新加載整個頁面的狀況下,與服務器交換數據並更新部分網頁的技術。


*NIX


unix進程間通訊方式(IPC)


  1. 管道(Pipe):管道可用於具備親緣關係進程間的通訊,容許一個進程和另外一個與它有共同祖先的進程之間進行通訊。

  2. 命名管道(named pipe):命名管道克服了管道沒有名字的限制,所以,除具備管道所具備的功能外,它還容許無親緣關係進程間的通訊。命名管道在文件系統中有對應的文件名。命名管道經過命令mkfifo或系統調用mkfifo來建立。

  3. 信號(Signal):信號是比較複雜的通訊方式,用於通知接受進程有某種事件發生,除了用於進程間通訊外,進程還能夠發送信號給進程自己;linux除了支持Unix早期信號語義函數sigal外,還支持語義符合Posix.1標準的信號函數sigaction(實際上,該函數是基於BSD的,BSD爲了實現可靠信號機制,又可以統一對外接口,用sigaction函數從新實現了signal函數)。

  4. 消息(Message)隊列:消息隊列是消息的連接表,包括Posix消息隊列system V消息隊列。有足夠權限的進程能夠向隊列中添加消息,被賦予讀權限的進程則能夠讀走隊列中的消息。消息隊列克服了信號承載信息量少,管道只能承載無格式字節流以及緩衝區大小受限等缺

  5. 共享內存:使得多個進程能夠訪問同一塊內存空間,是最快的可用IPC形式。是針對其餘通訊機制運行效率較低而設計的。每每與其它通訊機制,如信號量結合使用,來達到進程間的同步及互斥。

  6. 內存映射(mapped memory):內存映射容許任何多個進程間通訊,每個使用該機制的進程經過把一個共享的文件映射到本身的進程地址空間來實現它。

  7. 信號量(semaphore):主要做爲進程間以及同一進程不一樣線程之間的同步手段。

  8. 套接口(Socket):更爲通常的進程間通訊機制,可用於不一樣機器之間的進程間通訊。起初是由Unix系統的BSD分支開發出來的,但如今通常能夠移植到其它類Unix系統上:Linux和System V的變種都支持套接字。


數據結構


1 紅黑樹


紅黑樹與AVL的比較:


AVL是嚴格平衡樹,所以在增長或者刪除節點的時候,根據不一樣狀況,旋轉的次數比紅黑樹要多;


紅黑是用非嚴格的平衡來換取增刪節點時候旋轉次數的下降;


因此簡單說,若是你的應用中,搜索的次數遠遠大於插入和刪除,那麼選擇AVL,若是搜索,插入刪除次數幾乎差很少,應該選擇RB。


編程題


1 臺階問題/斐波納挈


一隻青蛙一次能夠跳上1級臺階,也能夠跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法。


fib = lambda n: n if n <= 2 else fib(n - 1) + fib(n - 2)


第二種記憶方法


def memo(func):

    cache = {}

    def wrap(*args):

        if args not in cache:

            cache[args] = func(*args)

        return cache[args]

    return wrap

 

 

@ memo

def fib(i):

    if i < 2:

        return 1

    return fib(i-1) + fib(i-2)


第三種方法


def fib(n):

    a, b = 0, 1

    for _ in xrange(n):

        a, b = b, a + b

    return b


2 變態臺階問題


一隻青蛙一次能夠跳上1級臺階,也能夠跳上2級……它也能夠跳上n級。求該青蛙跳上一個n級的臺階總共有多少種跳法。


fib = lambda n: n if n < 2 else 2 * fib(n - 1)


3 矩形覆蓋


咱們能夠用2*1的小矩形橫着或者豎着去覆蓋更大的矩形。請問用n個2*1的小矩形無重疊地覆蓋一個2*n的大矩形,總共有多少種方法?


第2*n個矩形的覆蓋方法等於第2*(n-1)加上第2*(n-2)的方法。


f = lambda n: 1 if n < 2 else f(n - 1) + f(n - 2)


4 楊氏矩陣查找


在一個m行n列二維數組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。


5 去除列表中的重複元素


用集合


list(set(l))


用字典


l1 = ['b','c','d','b','c','a','a']

l2 = {}.fromkeys(l1).keys()

print l2


用字典並保持順序


l1 = ['b','c','d','b','c','a','a']

l2 = list(set(l1))

l2.sort(key=l1.index)

print l2


列表推導式


l1 = ['b','c','d','b','c','a','a']

l2 = []

[l2.append(i) for i in l1 if not i in l2]


面試官提到的,先排序而後刪除.


6 鏈表成對調換


1->2->3->4轉換成2->1->4->3.


class ListNode:

    def __init__(self, x):

        self.val = x

        self.next = None

 

class Solution:

    # @param a ListNode

    # @return a ListNode

    def swapPairs(self, head):

        if head != None and head.next != None:

            next = head.next

            head.next = self.swapPairs(next.next)

            next.next = head

            return next

        return head


7 建立字典的方法


1 直接建立


dict = {'name':'earth', 'port':'80'}


2 工廠方法


items=[('name','earth'),('port','80')]

dict2=dict(items)

dict1=dict((['name','earth'],['port','80']))


3 fromkeys()方法


dict1={}.fromkeys(('x','y'),-1)

dict={'x':-1,'y':-1}

dict2={}.fromkeys(('x','y'))

dict2={'x':None, 'y':None}


8 合併兩個有序列表


知乎遠程面試要求編程


尾遞歸


def _recursion_merge_sort2(l1, l2, tmp):

    if len(l1) == 0 or len(l2) == 0:

        tmp.extend(l1)

        tmp.extend(l2)

        return tmp

    else:

        if l1[0] < l2[0]:

            tmp.append(l1[0])

            del l1[0]

        else:

            tmp.append(l2[0])

            del l2[0]

        return _recursion_merge_sort2(l1, l2, tmp)

 

def recursion_merge_sort2(l1, l2):

    return _recursion_merge_sort2(l1, l2, [])


循環算法


def loop_merge_sort(l1, l2):

    tmp = []

    while len(l1) > 0 and len(l2) > 0:

        if l1[0] < l2[0]:

            tmp.append(l1[0])

            del l1[0]

        else:

            tmp.append(l2[0])

            del l2[0]

    tmp.extend(l1)

    tmp.extend(l2)

    return tmp


9 交叉鏈表求交點


去哪兒的面試,沒作出來.


class ListNode:

    def __init__(self, x):

        self.val = x

        self.next = None

def node(l1, l2):

    length1, lenth2 = 0, 0

    # 求兩個鏈表長度

    while l1.next:

        l1 = l1.next

        length1 += 1

    while l2.next:

        l2 = l2.next

        length2 += 1

    # 長的鏈表先走

    if length1 > lenth2:

        for _ in range(length1 - length2):

            l1 = l1.next

    else:

        for _ in range(length2 - length1):

            l2 = l2.next

    while l1 and l2:

        if l1.next == l2.next:

            return l1.next

        else:

            l1 = l1.next

            l2 = l2.next


10 二分查找


def binarySearch(l, t):

    low, high = 0, len(l) - 1

    while low < high:

        print low, high

        mid = (low + high) / 2

        if l[mid] > t:

            high = mid

        elif l[mid] < t:

            low = mid + 1

        else:

            return mid

    return low if l[low] == t else False

 

if __name__ == '__main__':

    l = [1, 4, 12, 45, 66, 99, 120, 444]

    print binarySearch(l, 12)

    print binarySearch(l, 1)

    print binarySearch(l, 13)

    print binarySearch(l, 444)


11 快排


def qsort(seq):

    if seq==[]:

        return []

    else:

        pivot=seq[0]

        lesser=qsort([x for x in seq[1:] if x<pivot])

        greater=qsort([x for x in seq[1:] if x>=pivot])

        return lesser+[pivot]+greater

 

if __name__=='__main__':

    seq=[5,6,78,9,0,-1,2,3,-65,12]

    print(qsort(seq))


12 找零問題


def  coinChange(values, money, coinsUsed):

    #values    T[1:n]數組

    #valuesCounts   錢幣對應的種類數

    #money  找出來的總錢數

    #coinsUsed   對應於目前錢幣總數i所使用的硬幣數目

    for cents in range(1, money+1):

        minCoins = cents     #從第一個開始到money的全部狀況初始

        for value in values:

            if value <= cents:

                temp = coinsUsed[cents - value] + 1

                if temp < minCoins:

                    minCoins = temp

        coinsUsed[cents] = minCoins

        print('面值爲:{0} 的最小硬幣數目爲:{1} '.format(cents, coinsUsed[cents]) )

 

if __name__ == '__main__':

    values = [ 25, 21, 10, 5, 1]

    money = 63

    coinsUsed = {i:0 for i in range(money+1)}

    coinChange(values, money, coinsUsed)


13 廣度遍歷和深度遍歷二叉樹


給定一個數組,構建二叉樹,而且按層次打印這個二叉樹


## 14 二叉樹節點

class Node(object):

    def __init__(self, data, left=None, right=None):

        self.data = data

        self.left = left

        self.right = right

 

tree = Node(1, Node(3, Node(7, Node(0)), Node(6)), Node(2, Node(5), Node(4)))

 

## 15 層次遍歷

def lookup(root):

    stack = [root]

    while stack:

        current = stack.pop(0)

        print current.data

        if current.left:

            stack.append(current.left)

        if current.right:

            stack.append(current.right)

## 16 深度遍歷

def deep(root):

    if not root:

        return

    print root.data

    deep(root.left)

    deep(root.right)

 

if __name__ == '__main__':

    lookup(tree)

    deep(tree)


17 前中後序遍歷


深度遍歷改變順序就OK了


18 求最大樹深


def maxDepth(root):

        if not root:

            return 0

        return max(maxDepth(root.left), maxDepth(root.right)) + 1


19 求兩棵樹是否相同


def isSameTree(p, q):

    if p == None and q == None:

        return True

    elif p and q :

        return p.val == q.val and isSameTree(p.left,q.left) and isSameTree(p.right,q.right)

    else :

        return False


20 前序中序求後序


推薦: http://blog.csdn.net/hinyunsin/article/details/6315502


def rebuild(pre, center):

    if not pre:

        return

    cur = Node(pre[0])

    index = center.index(pre[0])

    cur.left = rebuild(pre[1:index + 1], center[:index])

    cur.right = rebuild(pre[index + 1:], center[index + 1:])

    return cur

 

def deep(root):

    if not root:

        return

    deep(root.left)

    deep(root.right)

    print root.data


21 單鏈表逆置


class Node(object):

    def __init__(self, data=None, next=None):

        self.data = data

        self.next = next

 

link = Node(1, Node(2, Node(3, Node(4, Node(5, Node(6, Node(7, Node(8, Node(9)))))))))

 

def rev(link):

    pre = link

    cur = link.next

    pre.next = None

    while cur:

        tmp = cur.next

        cur.next = pre

        pre = cur

        cur = tmp

    return pre

 

root = rev(link)

while root:

    print root.data

    root = root.next

相關文章
相關標籤/搜索