天天看點

Python筆試題(1)

  這是小編整理的筆試題,當然有些比較難,但是也是Python面試中出現頻率比較高的知識點,以便複習和練習。

1,兩個隊列生成一個棧,如何做?

  那想要實作兩個隊列生成一個棧,我們需要先了解隊列和棧的特性:

  隊列(先進先出),即隻能在隊列的尾部插入元素,頭部删除元素,根據該特性,實作隊列時候使用連結清單比較好。

  棧(先進後出),即隻能在該線性表的一頭進行資料的插入和删除,該位置稱為“棧頂”,而另一頭稱為“棧底”;根據特性,實作棧時使用順序表比較好。

  棧和隊列

  使用兩個隊列生成一個棧的實作思路為:

  兩個隊列,隊列1和隊列2在任意時刻至少有一個為空,即如果有元素,所有元素隻能在一個隊列中,當有元素需要插入時,将元素插入到空隊列中,并将另一非空隊列的所有元素全部轉移到該隊列中,于是,插入的元素添加到了隊列的最前面。

  首先是入棧:

Python筆試題(1)

   然後是出棧:

Python筆試題(1)

   實作代碼如下:

# _*_coding:utf-8_*_
import queue


class Stack:
    def __init__(self):
        self.master_queue = queue.Queue()
        self.minor_queue = queue.Queue()

    def push(self, value):
        '''
        入棧
        :param value:
        :return:
        '''
        self.master_queue.put(value)

    def pop(self):
        '''
        出棧
        :return:
        '''
        if self.master_queue.qsize() == 0:
            return None

        while True:
            if self.master_queue.qsize() == 1:
                value = self.master_queue.get()
                break
            self.minor_queue.put(self.master_queue.get())

        self.master_queue, self.minor_queue = self.minor_queue, self.master_queue

        return value


obj = Stack()
obj.push("A")
obj.push("B")
obj.push("C")
print(obj.pop())  # C
      

 

2,兩個棧生成一個隊列,如何做?

  經典問題再現哈,那反過來怎麼做呢?

  其實思路差不多,這裡就不畫圖了。簡單說一下,這裡利用了棧的先進後出的特點,将資料先加入第一個棧,然後通過在第二個棧中添加第一個棧删除的資料,就實作了資料的先進先出。

 代碼如下:

class Queue:
    def __init__(self):
        self.master_stack = []
        self.minior_stack = []

    def push(self, value):
        '''
        入隊
        :return:
        '''
        self.master_stack.append(value)

    def pop(self):
        '''
        出隊:先判斷棧B是否為空,為空則将棧A中元素pop出來并push到B,在棧B出棧
        如果不為空,則B直接出棧
        :return:
        '''
        if self.minior_stack:
            return self.minior_stack.pop()
        else:
            if self.master_stack != []:
                while self.master_stack:
                    self.minior_stack.append(self.master_stack.pop())
                return self.minior_stack.pop()
            else:
                return None


obj = Queue()
obj.push("A")
obj.push("B")
obj.push("C")
print(obj.pop())  # A
print(obj.pop())
print(obj.pop())
      

  

3,什麼是https

  https是基于http和SSL/TLS實作的一個協定,它可以保證在網絡上傳輸的資料都是加密的,進而保證資料安全。

  接下來我們從http協定開始,提出想法并逐漸進行分析,最終實作https。

3.1 http協定是不安全的

  在https誕生之前,所有網站都使用http協定,而http協定在資料傳輸的過程中都是明文,是以可能存在資料洩露和篡改。

Python筆試題(1)
3.2 使用對稱密鑰進行資料加密

  為了防止資料洩露和篡改,我們隊資料進行加密,如:生成一個對稱密碼【DKUFHNAF897123F】,将對稱秘鑰分别交給浏覽器和伺服器端,他們之間傳輸的資料都使用對稱秘鑰進行加密和解密。

Python筆試題(1)

 請求和響應流程如下:

  • 1,用戶端使用對稱密鑰對請求進行加密,并發送給服務端。
  • 2,服務端接受密文之後,使用對稱密鑰對密文進行解密,然後處理請求。最後再使用對稱密鑰把要傳回的内容再次加密,傳回給用戶端。
  • 3,用戶端接受到密文之後,使用對稱密鑰進行解密,并擷取最終的響應内容。

如此一來,資料傳輸都是密文,解決了明文傳輸資料的問題,但是,這麼幹有bug。

  • 浏覽器如何擷取對稱密鑰?
  • 每個用戶端的對稱密鑰相同,浏覽器能拿到對稱密鑰,那麼黑客也能拿到,是以,資料加密也就沒有意義了。
3.3 動态對稱密鑰和非對稱密鑰

  為了解決對稱密鑰動态性以及讓用戶端和服務端安全的擷取對稱密鑰,可以引入非對稱密鑰機制。

Python筆試題(1)

   如此一來,解決了動态對稱密鑰和資料加密的問題,因為每個使用者的對稱密鑰都是随機生成且傳輸的過程中都使用了公鑰加密(公鑰加密的資料隻有私鑰能解密),所有黑客無法截獲對稱密鑰。而資料傳輸是通過對稱密鑰加密過的,是以黑客即使能擷取資料也無法去解密看到真實的内容。看似無懈可擊,但是,還是有bug。

  如果黑客按照上圖步驟2劫持,黑客吧自己的公鑰傳回給用戶端,那麼用戶端會使用黑客的公鑰來加密對稱密鑰,黑客在步驟6,截獲請求,使用自己的私鑰擷取對稱密鑰,那麼後面過程全都完蛋,,

3.4 CA憑證的應用

  使用CA憑證可以解決黑客劫持的問題:

Python筆試題(1)

  如此一來,就解決了黑客劫持的問題,因為即使黑客劫持後的給浏覽器即使傳回了證書也無法通過校驗,同時浏覽器也會提示錯誤資訊。

  注意:https是基于http和SSL/TLS實作的一個協定,其中前9個步驟稱為是SSL/TLS過程,之後的傳輸資料利用的就是http協定(收發資料)。

3.5 總結

  以上就是Https的實作原理,https可以保證資料安全,但是由于其過程需要反複加密解密所有通路速度會有所下降。

4,連結清單是一個特殊的資料結構,其中每個節點包含自己的資料以及下一個值的引用(指針),連結清單的逆置就是指将連結清單下一個值的引用(指針)調換,如下圖所示:

Python筆試題(1)

   第一步,建構連結清單

class Node:
    def __init__(self, value, next):
        self.value = value
        self.next = next


head = Node('head', None)
last = head
for i in range(5):
    node = Node('v%s' % i, None)
    last.next = node
    last = node

# 檢視連結清單關系
print("原始連結清單資訊為:  ")
print(head.value)

print(head.next.value)
print(head.next.next.value)
print(head.next.next.next.value)
print(head.next.next.next.next.value)
print(head.next.next.next.next.next.value)
'''
原始連結清單資訊為:  
head
v0
v1
v2
v3
v4
'''
      

  第二步,連結清單逆置

  實作思路:

1,設定三個周遊分别指向如下三個值

2,将current.next設定為prev

3,整體向右移動一個節點,繼續指向第一,第二步

Python筆試題(1)

   代碼如下:

def reverse_linked_list(head):
    '''
    連結清單逆置
    :param head:
    :return:
    '''
    if not head or not head.next:
        return head

    prev_node = None
    current_node = head
    next_node = head.next

    while True:
        current_node.next = prev_node
        if not next_node:
            break
        prev_node = current_node
        current_node = next_node
        next_node = current_node.next
    return current_node

new_head = reverse_linked_list(head)

print('逆置之後的連結清單')
print(new_head.value)
print(new_head.next.value)
print(new_head.next.next.value)
print(new_head.next.next.next.value)
print(new_head.next.next.next.next.value)
print(new_head.next.next.next.next.next.value)
'''
逆置之後的連結清單
v4
v3
v2
v1
v0
head
'''
      

5,做為Apple Store App獨立開發者,你要搞限時促銷,為你的應用生成激活碼(或者優惠券),使用Python如何生成200個激活碼(或者優惠券)?

簡介:通用唯一識别碼(英語:Universally Unique Identifier,簡稱UUID)是一種軟體建構的标準,亦為開放軟體基金會組織在分散式計算環境領域的一部份。

UUID的目的,是讓分散式系統中的所有元素,都能有唯一的辨識資訊,而不需要透過中央控制端來做辨識資訊的指定。如此一來,每個人都可以建立不與其它人沖突的UUID。在這樣的情況下,就不需考慮資料庫建立時的名稱重複問題。目前最廣泛應用的UUID,是微軟公司的全局唯一辨別符(GUID),而其他重要的應用,則有Linux ext2/ext3檔案系統、LUKS加密分區、GNOME、KDE、Mac OS X等等。另外我們也可以在e2fsprogs套件中的UUID函式庫找到實作。

分析:這裡參考(http://www.blogjava.net/BearRui/archive/2010/10/19/unique_random_code.html)

主鍵+随機碼的方式.

這種方法優點:使用也比較簡單,不用直接去查詢資料庫,而最大的優點是查詢的時候,可以根據邀請碼直接得到主鍵id, 然後根據id去資料庫查詢(速度很快),再比較查詢出來的邀請碼和使用者送出的邀請碼是否一緻。

  1. 生成:id(資料庫primary key )->16進制 + "L(辨別符)" +随機碼
  2. 擷取id:擷取16進制的id再轉回10進制
import random
import string

def activation_code(id,length = 10):
    '''
    id+L+随機碼
    string子產品中的三個函數為:string.letters,string.printable.string.printable

    '''
    prefix = hex(int(id))[2:]+'L'  #prefix為字首
    length =length -len(prefix)
    chars = string.ascii_letters+string.digits
    return prefix + ''.join([random.choice(chars) for i in range(length)])

def get_id(code):
    '''hex to dec'''
    return str(int(code.upper(),16))

if __name__ =="__mian__":
    for i in range(10,500,35):
        code = activation_code(i)
        id_hex = code.split('L')[0]
        id = get_id(id_hex)
        print (code,id)

if __name__=="__main__":
    for i in range(10,200,35):
        code = activation_code(i)
        id_hex = code.split('L')[0]
        id  = get_id(id_hex)
        print (code,id)
        #print(code)      

6,任一個英文的純文字檔案,統計其中的單詞出現的個數

1.strip()沒有參數時,删除空白符,包括、n\r\t空格,strip()函數隻能用于str類型,list類型等不可用。

2.split()用于分割,分隔符可以自己制定

def world_count(inputfile):
    if os.path.isfile(inputfile) !=True:
        print("inputfile not exits")
        sys.exit()

    word_count = 0
    words = open(inputfile , "r").readlines()
    for word in words:
        print("word: %s" %word)
        temp = word.strip().split('')
        word_count += len(temp)

    print("word count:%s" %word_count)
    return word_count      

7,用 Python 寫一個爬圖檔的程式

   這個就是一個簡單的爬蟲,隻要模拟浏覽器即可

import urllib.request
import re

url = 'http://tieba.baidu.com/p/2166231880'
headers = ("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36")
opener = urllib.request.build_opener()
opener.assheaders = [headers]
urllib.request.install_opener(opener)
data = urllib.request.urlopen(url).read()
data2 = data.decode("utf-8","ignore")
pattern = '<img pic_type="0" class="BDE_Image" src="(.*?)" bdwater="杉本有美吧,.*?" width=".*?" height=".*?" changedsize="true">'
allurl = re.compile(pattern).findall(data2)
#print(allurl)

for i in range(0,len(allurl)):
    #print(allurl[i])
    thisimg = allurl[i]
    file = "D:/pycode/"+str(i)+".jpg"
    urllib.request.urlretrieve(thisimg,filename = file)
    print("第" + str(i) + "次爬去成功")      

8,一個HTML檔案,找出裡面的正文

9,有個目錄,裡面是你自己寫過的程式,統計一下你寫過多少行代碼。包括空行和注釋,但是要分别列出來。

import os
import string
import re

os.chdir('C:/workspace')

fh=open('test_test.py')
read_fh=fh.readlines()
fh.close()
number_code=0
number_empty=0
number_note=0
pattern='.*#' #正則比對模式

for x in read_fh:
    if '#' in x: #計算注釋數目
        if re.findall(pattern,x)[0][:-1].isspace() or re.findall(pattern,x)[0][:-1]=='':
            number_note+=1
        else:
            number_code+=1

    elif x.isspace():
        number_empty+=1
    else:
        number_code+=1
print('code number is %d'%(number_code+number_empty+number_note))
print('empty number is %d'%number_empty)
print('note number is %d'%number_note)      

10,有1、2、3、4個數字,能組成多少個互不相同且無重複數字的三位數?都是多少?

d = [1,2,3,4]
def threenums():
    print(None)
    count = 0
    nums = []
    for index1 in range(1,5):
        for index2 in range(1,5):
            for index3 in range(1,5):
                if index1 != index2 and index2 != index3 and index3 !=index1:
                    num = 100*index1 +10*index2 +index3
                    if num not in nums:
                        nums.append(num)
                        count +=1
    print(count)
    print(nums)      

11,題目如下:

企業發放的獎金根據利潤提成。

利潤(I)低于或等于10萬元時,獎金可提10%;

利潤高于10萬元,低于20萬元時,低于10萬元的部分按10%提成,高于10萬元的部分,可可提成7.5%;

20萬到40萬之間時,高于20萬元的部分,可提成5%;

40萬到60萬之間時高于40萬元的部分,可提成3%;

60萬到100萬之間時,高于60萬元的部分,可提成1.5%,

高于100萬元時,超過100萬元的部分按1%提成,

從鍵盤輸入當月利潤I,求應發放獎金總數?

def reward(profit):
    reward = 0.0
    if profit <=100000:
        return profit*0.1
    elif profit <=20 and profit >10:
        return (profit-10000)*0.075+100000*0.1
    elif profit <=40 and profit >20:
        return (profit-10000)*0.05+100000*0.1+10000*0.075
    elif profit <=60 and profit >40:
        return (profit-10000)*0.03+100000*0.1+10000*0.075+100000*0.05
    elif profit <=100 and profit >60:
        return (profit-10000)*0.015+100000*0.1+10000*0.075+100000*0.05+100000*0.03
    else:
        return (profit-10000)*0.01+100000*0.1+10000*0.075+100000*0.05+100000*0.03+100000*0.015


if __name__ == "__mian__":
    profit = int(input("請輸入當月利潤:"))
    print(reward(profit))      

12,一個整數,

它加上100後是一個完全平方數,再加上168又是一個完全平方數,

請問該數是多少?

import math

for i in range(10000):
    x = int(math.sqrt(i+100))
    y = int(math.sqrt(i+168))

    if (x*x == i+100) and (y*y == i+168):
        print(i)      

(未完待續,有時間會繼續上傳,http://www.cnblogs.com/bakoom/p/5251293.html)

不經一番徹骨寒 怎得梅花撲鼻香

繼續閱讀