Python筆試題(1)


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

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

  (聽說是阿里問過的面試題)

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

  隊列(先進先出),即只能在隊列的尾部插入元素,頭部刪除元素,根據該特性,實現隊列時候使用鏈表比較好。

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

  棧和隊列

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

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

  首先是入棧:

 

 

   然后是出棧:

 

 

   實現代碼如下:

# _*_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協議在數據傳輸的過程中都是明文,所以可能存在數據泄露和篡改。

 

3.2 使用對稱密鑰進行數據加密

  為了防止數據泄露和篡改,我們隊數據進行加密,如:生成一個對稱密碼【DKUFHNAF897123F】,將對稱秘鑰分別交給瀏覽器和服務器端,他們之間傳輸的數據都使用對稱秘鑰進行加密和解密。

 

 請求和響應流程如下:

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

如此一來,數據傳輸都是密文,解決了明文傳輸數據的問題,但是,這么干有bug。

  • 瀏覽器如何獲取對稱密鑰?
  • 每個客戶端的對稱密鑰相同,瀏覽器能拿到對稱密鑰,那么黑客也能拿到,所以,數據加密也就沒有意義了。
3.3 動態對稱密鑰和非對稱密鑰

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

 

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

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

3.4 CA證書的應用

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

 

 

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

  注意:https是基於http和SSL/TLS實現的一個協議,其中前9個步驟稱為是SSL/TLS過程,之后的傳輸數據利用的就是http協議(收發數據)。

3.5 總結

  以上就是Https的實現原理,https可以保證數據安全,但是由於其過程需要反復加密解密所有訪問速度會有所下降。

4,鏈表是一個特殊的數據結構,其中每個節點包含自己的數據以及下一個值的引用(指針),鏈表的逆置就是指將鏈表下一個值的引用(指針)調換,如下圖所示:

 

   第一步,構建鏈表

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,整體向右移動一個節點,繼續指向第一,第二步

 

   代碼如下:

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM