數據結構與算法學習筆記(python)——第一節 數組應用程序實戰

前言

本人是一個長期的數據分析愛好者,最近半年的時間的在網上學習了很多關於python、數據分析、數據挖掘以及項目管理相關的課程和知識,但是在學習的過程中,過於追求課程數量的增長,長時間關注於學習了多少多少門課程。事實上,學完一門課之後真正掌握的知識並不多,主要的原因是自己沒有認真學習和理解溫故而知新的這句話的真正含義。因此,從現在開始,我在學習《數據結構與算法——基於python》的課程內容之後,抽出固定的時間對每天學習的內容進行總結和分享,一方面有助於個人更好的掌握課程的內容,另一方面能和大家一起分享個人的學習歷程和相應的學習知識。

第一節 數組應用程序實戰

在老師對課程做了簡單介紹之後,就給大家拋出了幾個簡單的數據結構問題;現將每個問題、解題思路和詳細代碼記錄如下;

  1. Arry應用1——計算一元二次方程的解
    思路:
    對於一元二次方程組,有如下的求解方法;
    aX^2+bX+c=0
    如果 b-4ac >= 0,則 x1,x2= [-b±√(b^2-4ac)]/2a
    如果 b-4ac < 0,則 無解
    代碼
def solve(a, b, c):
    r = pow(b, 2) - 4 * a * c
    if (r < 0):
        raise ValueError("No Solution") 
    return (-b + math.sqrt(r)) / (2 * a), (-b - math.sqrt(r)) / (2 * a)
solve(1, 4, 1) # 1,4,1 分別表示方程中的a,b,c
  1. Arry應用2——比賽現場計分系統
    問題描述:
    一個歌唱比賽的歌手打分,設計一個程序幫助現場去掉一個最低分和一個最高分,再計算一 個平均分;
    思路:
    根據選手的分數得到最高分和最低分,然後去掉一個最高分和一個最低分,計算平均分即可
    代碼
def singing_score(values):
    small_pos = 0
    for i in range(1, len(values)): # 找出最低分
        if values[i] < values[small_pos] :
            small_pos = i 
            
    high_pos = 0
    for i in range(1, len(values)): # 找出最高分
        if values[i] > values[high_pos] :
            high_pos = i
    values.remove(values[small_pos]) #  去掉一個最高分
    values.remove(values[high_pos]) # 去掉一個最低分
    rst = sum(values)/len(values) # 求平均分
    return rst
values =  [8,9,5,10,5,8,7,9,9.5]
singing_score(values)
  1. Arry應用3——計算圓周率的值
    方法1:
    近似計算
    代碼
def pi1(n):
    pi = 0
    sign = 1
    for i in range(1, n + 1, 2):
        pi += sign * (1 / i)
        sign *= -1
    return pi * 4
 pi1(10000)

*或者 *

def pi2():
    pi = 0
    sign = 1
    pre = 999
    i = 1
    delta = 0.000001
    
    while (abs(pi - pre) > delta):
        pre = pi
        pi += sign * (1 / i)
        sign *= -1
        i += 2
    return pi * 4  
pi2()

方法2 蒙特卡洛模擬
思路:
想象一個圓形靶子,我們不停的向靶面射擊, 命名圓內的我們算是“擊中 也就是 𝑥2+𝑦2≤1 .
假如我們不停的射擊,直到我們把這個方形的靶子全部覆蓋(打成了骰子)
圓的面積應該是 𝑆𝑐𝑖𝑟𝑐𝑙𝑒=𝜋𝑟2
方形的面積應該是
𝑆𝑠𝑞𝑢𝑎𝑟𝑒=𝑎^2
也就是說
𝑆𝑐𝑖𝑟𝑐𝑙𝑒/𝑆𝑠𝑞𝑢𝑎𝑟𝑒=𝜋𝑟^2/ 𝑎 ^2
𝑟=1,𝑎=2
hits / tries is approximately equal to the ratio of the areas of the circle 那麼𝑆𝑐𝑖𝑟𝑐𝑙𝑒/𝑆𝑠𝑞𝑢𝑎𝑟𝑒=𝜋/4
那麼預估的 𝜋=4×(𝑆𝑐𝑖𝑟𝑐𝑙𝑒/𝑆𝑠𝑞𝑢𝑎𝑟𝑒)
代碼

from random import random

def pi3(TRIES):
    hits = 0
    for i in range(TRIES) :
        # Generate two random numbers between –1 and 1
        r = random()
        x = -1 + 2 * r
        r = random()
        y = -1 + 2 * r
        # Check whether the point lies in the unit circle
        if x * x + y * y <= 1 :
            hits = hits + 1

        # The ratio hits / tries is approximately the same as the ratio
        # circle area / square area = pi / 4.
    return 4.0 * hits / TRIES
pi3(100)
  1. Arry應用4——打印9X9乘法口訣表
    代碼
for i in range(1,10):
	for j in range(1,i+1):
		print(j, "*", i,"=",i*j,end = " ")
	print 
  1. Arry應用5——設計一個洗牌程序
    問題描述:
    假設現在有1到10按照順序排列,需要設計一個程序將這個數列變成亂序的數列,使得每個元素出現在每個位置的概率相同;
    思路:
    利用隨機數將數據元素更換順序
    方法1: 用random.shuffle()函數
    代碼
    構造隨機替換函數
import random
def shuffle_system(cards):
    random.shuffle(cards)  

檢驗每個元素在每個位置出現的概率

def test_shuffle(f):
    result = [[0 for i in range(10)] for j in range(10)]

    for i in range(1000):
        A = [i for i in range(0, 10)]
        f(A)
        for j in range(len(A)):
            result[A[j]][j] += 1
        
    print('\n'.join([''.join(['{:6}'.format(item) for item in row]) 
          for row in result]))
test_shuffle(shuffle_system)

輸出結果:
在這裏插入圖片描述
從輸出結果可以看出,將上述隨機替換函數執行1000次,得到每個數出現在每個位置的次數基本爲100,說明上述函數較爲合理;
方法2: 隨機生成兩個數,並交換位置
代碼

def shuffle_1st(cards):
    for k in range(len(cards)):
        i = random.randint(0, len(cards) - 1)
        j = random.randint(0, len(cards) - 1)
        cards[i], cards[j] = cards[j], cards[i]

利用test_shuffle()檢驗每個元素在每個位置出現的概率

test_shuffle(shuffle_1st)

輸出結果:
在這裏插入圖片描述
從輸出結果可以看出,將上述隨機替換函數執行1000次,得到每個數出現在每個位置的次數不相等,對角線上的輸出結果較大,說明上述洗牌函數隨機性不強,使結果不能均勻分佈。
方法3: 隨機生成一個數,i與這個數相加,然後交換元素的位置
代碼

def shuffle_correct(cards):
    for i in range(len(cards)):
        randomi = i + random.randint(0, (len(cards) - i - 1))
        cards[i], cards[randomi] = cards[randomi], cards[i]

利用test_shuffle()檢驗每個元素在每個位置出現的概率

test_shuffle(shuffle_correct)	

輸出結果
在這裏插入圖片描述
從輸出結果可以看出,將上述隨機替換函數執行1000次,得到每個數出現在每個位置的次數不相等,但是總體差別不大,說明上述洗牌函數隨機性較強,使結果能均勻分佈。
6. Arry應用6——計算素數 (質數)
問題描述:
給定一個正整數n,計算出小於等於n的質數有多少個。 比如17,則返回7,因爲小於等於7的質數有2,3,5,7,13,17;
思路:
對從2到根號n的數,排除每個數的倍數,剩下的即爲質數,然後剩下的質數輸出並計數即可。
代碼

def count_prime(n):
    is_prime = [True] * (n + 1)
    i = 2
    while (i * i <= n):
        if (is_prime[i]):
            j = i
            while (j * i <= n): # i從2到100,將i的倍數全部變爲false
                is_prime[i * j] = False
                j += 1
        i += 1    
    # is_prime[i] 爲True的序號全爲質數,輸出即可
    count = 0
    for i in range(2, n+1):
        if (is_prime[i]):
            count += 1
            print(i, end = " ") # 輸出每個質數
    return count # 輸出質數的個數

計算100以內的質數計個數

count_prime(1000)

輸出即可得到每個質數及個數,如下圖所示;
在這裏插入圖片描述
7. Arry應用7——證明哥德巴赫猜想
問題描述:
1742年,哥德巴赫提出了著名的哥德巴赫猜想。即:任一大於2的偶數都可寫成兩個質數之和。比如說16=3+13。試着編碼寫出程序:只包含N作爲參數並且給出N爲兩個質數之和的表達式。哥德巴赫猜想至今沒有被證明,但是目前已知其在N小於10^14的時候都是成立的;
思路:
根據計算質數的思路得到n以內的所有質數,然後對於滿足相加等於n的質數進行篩選並輸出即可,在尋找滿足相加等於n的質數時,可先將質數從小到大排序,再從首尾兩端相加,即可快速確定。
代碼

def goldbach(n):
    is_prime = [True] * (n + 1)
    i = 2
    while (i * i <= n):
        if (is_prime[i]):
            j = i
            while (j * i <= n):
                is_prime[i * j] = False
                j += 1
        i += 1
    count = 0
    for i in range(2, n+1):
        if (is_prime[i]):
            count += 1

    primes = [None] * count 
    
    idx = 0
    for i in range(2, n + 1):
        if (is_prime[i]): # 將質數賦值給primes數組
            primes[idx] = i
            idx += 1
    left = 0
    right = count - 1
    while (left < right):
        if (n == primes[left] + primes[right]):
            print(n," = ", primes[left], " + ", primes[right])
            left += 1
            right -= 1
        elif (n > primes[left] + primes[right]):
            left += 1
        else:
            right -= 1
goldbach(100)

輸出結果爲100拆解成兩個質數之和,如下所示;
在這裏插入圖片描述

持續更新,歡迎大家點贊收藏

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章