for a in range(0,1001): for b in range(0,1001): for c in range(0,1001): if a+b+c == 1000 and a**2+b**2 == c**2: print(a,b,c)
for a in range(0,1001): for b in range(0,1001): c = 1000-a-b if a+b+c == 1000 and a**2+b**2 == c**2: print(a,b,c)
def sumOfN(n): theSum = 0 #1 for i in range(1,n+1): theSum = theSum + i #n return theSum #1 print(sumOfN(10)) #n+2 #O(n)
a=5 b=6 c=10 for i in range(n): for j in range(n): x = i * i y = j * j z = i * j for k in range(n): w = a*k + 45 v = b*b d = 33 #4+3n**2+2n #O(n**2)
概念:對於數據(基本類型的數據(int,float,char))的組織方式就被稱做爲數據結構。數據結構解決的就是一組數據如何進行保存,保存形式是怎樣的。html
案例: 須要存儲一些學生的學生信息(name,score),那麼這些數據應該如何組織呢?查詢某一個具體學生的時間複雜度是什麼呢?(三種組織方式)node
[{ 'name':'xxx', 'score':'xxx' },{ 'name':'xxx', 'score':'xxx' },{ 'name':'xxx', 'score':'xxx' }]
[{'name': 'xxx', 'score': 'xxx'}, {'name': 'xxx', 'score': 'xxx'}, {'name': 'xxx', 'score': 'xxx'}]
[ ('name','score'), ('name','score'), ('name','score') ]
[('name', 'score'), ('name', 'score'), ('name', 'score')]
{ 'zhangsan':{'score':'xxx'}, 'lisi':{'score':'xxx'} }
{'zhangsan': {'score': 'xxx'}, 'lisi': {'score': 'xxx'}}
三種組織形式基於查詢的時間複雜度?python
使用不一樣的形式組織數據,在基於查詢時的時間複雜度是不同的。所以認爲算法是爲了解決實際問題而設計的,數據結構是算法須要處理問題的載體。程序員
在列表的操做有一個很是常見的編程任務就是是增長一個列表。咱們立刻想到的有兩種方法能夠建立更長的列表,可使用 append 方法或拼接運算符。可是這兩種方法那種效率更高呢。這對你來講很重要,由於它能夠幫助你經過選擇合適的工具來提升你本身的程序的效率。web
實例化一個空列表,而後將0-n範圍的數據添加到列表中。(四種方式)面試
def test01(): alist = [] for i in range(0,100): alist += [i] return alist def test02(): alist = [] for i in range(0,100): alist.append(i) return alist if __name__ == '__main__': pass
timeit模塊:該模塊能夠用來測試一段python代碼的執行速度/時長。算法
Timer類:該類是timeit模塊中專門用於測量python代碼的執行速度/時長的。原型爲:class timeit.Timer(stmt='pass',setup='pass')。編程
stmt參數:表示即將進行測試的代碼塊語句。數組
setup:運行代碼塊語句時所須要的設置。瀏覽器
timeit函數:timeit.Timer.timeit(number=100000),該函數返回代碼塊語句執行number次的平均耗時。
from timeit import Timer def test01(): alist = [] for i in range(0,100): alist += [i] return alist def test02(): alist = [] for i in range(0,100): alist.append(i) return alist if __name__ == '__main__': timer = Timer('test01()','from __main__ import test01') print(timer.timeit(1000)) t = Timer('test02()','from __main__ import test02') print(t.timeit(1000))
0.02650774001085665 0.02491867200296838
特性:先進後出的數據結構
棧頂,棧尾
應用:每一個 web 瀏覽器都有一個返回按鈕。當你瀏覽網頁時,這些網頁被放置在一個棧中(實際是網頁的網址)。你如今查看的網頁在頂部,你第一個查看的網頁在底部。若是按‘返回’按鈕,將按相反的順序瀏覽剛纔的頁面。
Stack() 建立一個空的新棧。 它不須要參數,並返回一個空棧。
push(item)將一個新項添加到棧的頂部。它須要 item 作參數並不返回任何內容。
pop() 從棧中刪除頂部項。它不須要參數並返回 item 。棧被修改。
isEmpty() 測試棧是否爲空。不須要參數,並返回布爾值。
size() 返回棧中的 item 數量。不須要參數,並返回一個整數。
class Stack(): def __init__(self): # 實例化一個空棧 self.items = [] # 容器 def push(self,item): # item就是向棧中添加的元素(從棧頂添加到棧底) self.items.append(item) def pop(self): # 彈出棧頂的元素 return self.items.pop() def isEmpty(self): # 是否爲空 return self.items == [] def size(self): # 棧的大小 return len(self.items)
stack = Stack() # 實例化一個空棧 stack.push(1) stack.push(2) stack.push(3) print(stack.pop()) print(stack.pop()) print(stack.pop()) """ 3 2 1 """
class Queue(): def __init__(self): self.items = [] def enqueue(self,item): self.items.insert(0,item) def dequeue(self): return self.items.pop() def isEmpty(self): return self.items == [] def size(self): return len(self.items) q = Queue() q.enqueue(1) q.enqueue(2) q.enqueue(3) print(q.dequeue()) print(q.dequeue()) print(q.dequeue()) """ 1 2 3 """
""" 思路: 七秒傳遞六次, 每一次傳遞時都將獲得山芋的孩子移到隊列首(也就是將上一個孩子從隊列中移除放在隊列末), 判斷只剩一個隊列元素時,循環結束 """ kids = ['A', 'B', 'C', 'D', 'E', 'F'] # 人員 kids_queue = Queue() # 建立隊列 for kid in kids: kids_queue.enqueue(kid) # 加入隊列 while kids_queue.size() > 1: for i in range(6): # 傳遞次數 first_kid = kids_queue.dequeue() # 移除 kids_queue.enqueue(first_kid) # 加入 kids_queue.dequeue() # 淘汰 print(kids_queue.dequeue()) # E
計算機的做用
問題:計算機如何計算1+2?
變量的概念
大小
地址
理解a=10的內存圖(引用,指向)
引用:變量。a=10,a就是變量或者引用。a實際存儲的是10對應內存空間的地址
指向:若是某一個引用存儲的是一塊內存空間的地址,則該引用就指向了該塊內存空間
不一樣數據佔用內存空間的大小
集合中存儲的元素是有順序的,順序表的結構能夠分爲兩種形式:單數據類型(數組)和多數據類型(列表)。
python中的列表和元組就屬於多數據類型的順序表
單數據類型順序表的內存圖(內存連續開啓)
多數據類型順序表的內存圖(內存非連續開闢)
順序表的弊端:順序表的結構須要預先知道數據大小來申請連續的存儲空間,而在進行擴充時又須要進行數據的搬遷。
#節點的數據結構封裝 class Node(): def __init__(self,item): self.item = item self.next = None #指向下一個節點的地址 node = Node('A') #實例化了一個節點對象,該節點存儲的數據爲A,next爲None
# 封裝鏈表 class Link(): def __init__(self): # 構建空鏈表 self._head = None # 空離鏈表_head指向None def add(self, item):# 在鏈表頭部插入一個節點 node = Node(item) node.next = self._head # 將新插入的節點的next指向以前的頭節點 self._head = node # _head永遠指向頭節點 def is_Empty(self): return self._head == None def travel(self): # 遍歷鏈表 循環查找並打印item值, 直到next爲None cur = self._head # 新賦值一個臨時變量保存_head的值, 防止改變_head的指向 while cur: print(cur.item) cur = cur.next def length(self): # 統計節點的數量 count = 0 cur = self._head while cur: count += 1 cur = cur.next return count def search(self, item): # 查看鏈表中是否有此節點,返回布爾值 cur = self._head find = False while cur: if cur.item == item: find = True break cur = cur.next return find def append(self, item): # 向鏈表尾部添加一個節點 node = Node(item) cur = self._head pre = cur # 建立臨時變量用來保存cur前一個節點的信息 while cur: # 在中止循環時,cur已經指向了None pre = cur cur = cur.next pre.next = node # 將最後一個節點的next指向新的節點 def insert(self,pos,item):#pos用整數值 node = Node(item) if self._head == None:#鏈表爲空 #將插入的節點做爲鏈表的第一個節點便可 self._head = node return #若是插入的位置大於鏈表的長度或者小於0 if pos > self.length(): self.append(item) return if pos < 0: self.add(item) return #分析:必須找到插入位置對應的節點和其前一個節點就能夠實現插入了 pre = None #cur前一個節點 cur = self._head #當前節點 for i in range(pos): #循環pos次(控制pre和cur向後偏移) pre = cur cur = cur.next pre.next = node node.next = cur def remove(self,item): if self._head == None: return #鏈表爲空則直接結束程序 #須要定位到刪除的節點和其前一個節點 cur = self._head pre = None #若是刪除的是第一個節點則須要單獨作處理 if cur.item == item: self._head = cur.next #讓head指向第二個節點 return #刪除除了第一個節點其餘的節點操做 while True: pre = cur cur = cur.next if cur == None:#沒有找到刪除的節點.cur==None遍歷到最後一個節點 return if cur.item == item:#找到了刪除的節點 break #定位到了刪除的節點cur和其前一個節點pre pre.next = cur.next link = Link()#構建了一個新的空鏈表 link.add('D') link.add('C') link.add('B') link.add('A') link.append('E') link.insert(0, 'F') link.insert(5, 'G') link.remove('F') link.travel()
A B C D E
. is_empty():鏈表是否爲空
. length():鏈表長度
. travel():遍歷整個鏈表
. add(item):鏈表頭部添加元素
. append(item):鏈表尾部添加元素
. insert(pos, item):指定位置添加元素
. remove(item):刪除節點
. search(item):查找節點是否存在
class Node(): def __init__(self,item): self.item = item #將left和right當成鏈表中的next self.left = None #指向該節點的左葉子節點 self.right = None#指向該節點的右葉子節點 class Tree(): def __init__(self):#構造一個空樹 self.root = None#root就能夠視爲鏈表中的head,root永遠要指向二叉樹的根節點 def addNode(self,item): #實例化一個新的節點對象 node = Node(item) #若是樹爲空,則插入的節點爲根節點 if self.root == None:#樹爲空 self.root = node return #樹爲非空 cur = self.root node_list = [cur] #將根節點加入到列表中,該列表中存放的爲左右葉子節點部位空的節點 while True: p_node = node_list.pop(0) #非空的節點須要再次加入到node_list列表中 if p_node.left != None: node_list.append(p_node.left) else: p_node.left = node break if p_node.right != None: node_list.append(p_node.right) else:#當前節點的右葉子節點爲空 p_node.right = node break def travel(self): if self.root == None:#樹爲空 print('空樹') return cur = self.root node_list = [cur] print(cur.item) while node_list: p_node = node_list.pop(0) if p_node.left != None: print(p_node.left.item) node_list.append(p_node.left) if p_node.right != None: print(p_node.right.item) node_list.append(p_node.right) #深度遍歷 def forward(self,root):#root表示的是某一個子樹的根節點 #結束遞歸的條件 if root == None: return #跟,左,右 print(root.item) #打印子樹的左節點(另外一個子樹的根節點) self.forward(root.left) #右 self.forward(root.right) def middle(self,root): if root == None: return self.middle(root.left) print(root.item) self.middle(root.right) def back(self,root): if root == None: return self.back(root.left) self.back(root.right) print(root.item) tree = Tree() #實例化了一顆空樹。tree.root == None tree.addNode(1) tree.addNode(2) tree.addNode(3) tree.addNode(4) tree.addNode(5) tree.addNode(6) tree.back(tree.root)
class Node(): def __init__(self,item): self.item = item #將left和right當成鏈表中的next self.left = None #指向該節點的左葉子節點 self.right = None#指向該節點的右葉子節點 class SortTree(): def __init__(self): self.root = None def insert(self,item): node = Node(item) if self.root == None:#樹爲空則插入的第一個節點爲跟節點 self.root = node return #樹爲非空 cur = self.root #將插入的節點和根節點進行大小比較 while True: if item >= cur.item:#插入的節點大於根節點,該節點應該插入到根節點的右側 #再次進行判斷:若是根節點的右葉子節點爲空,則將item插入到右葉子節點的位置 if cur.right == None: cur.right = node return else:#根節點的右葉子節點不爲空 cur = cur.right else:#插入的節點小於根節點,該節點插入到根節點的左側 if cur.left == None: cur.left = node return else: cur = cur.left def middle(self,root): if root == None: return self.middle(root.left) print(root.item) self.middle(root.right) tree = SortTree() alist = [3,8,5,7,6,2,1,0] for i in alist: tree.insert(i) tree.middle(tree.root) #只有中序遍歷在排序二叉樹中遍歷的結果爲有序結果
def find(alist,item): #left&right表示序列的起始位置的下標 left = 0 right = len(alist)-1 isFind = False#是否找到的標識 while left <= right: mid_index = (right+left)//2 #序列中間元素的下標(序列中元素的個數整除2) #須要使用中間元素和要找尋的item進行比較 if alist[mid_index] > item: #中間元素的值大於了要找尋的item的值。結論:item必定是存在於中間元素的左側 #將中間元素左側做爲一個新序列 right = mid_index - 1 else:#中間元素小於等於找尋的item if alist[mid_index] == item:#找到了 isFind = True break else:#找的值大於中間元素,找尋的值在中間元素的右側 left = mid_index + 1 #將中間元素右側做爲了新的子序列 return isFind alist = [1,2,3,4,5,6] print(find(alist,41))
#將亂序序列中的最大值找出逐步偏移(讓兩兩元素進行大小比較,大的元素逐步向後移動)到最後 def sort(alist): length = len(alist) #讓兩兩元素進行比較(n-1) for i in range(0,length-1): if alist[i] > alist[i+1]:#第一個元素大於第二個元素 #兩個元素交換位置 alist[i],alist[i+1] = alist[i+1],alist[i] return alist alist = [3,8,5,2,0,7,6] print(sort(alist))
[3, 5, 2, 0, 7, 6, 8]
#冒泡排序完整代碼 #上述代碼操做須要做用n-1才能夠將整個序列變成有序的 def sort(alist): length = len(alist) for j in range(0,length-1): #讓兩兩元素進行比較(n-1) for i in range(0,length-1-j): if alist[i] > alist[i+1]:#第一個元素大於第二個元素 #兩個元素交換位置 alist[i],alist[i+1] = alist[i+1],alist[i] return alist alist = [3,8,5,2,0,7,6] print(sort(alist))
[0, 2, 3, 5, 6, 7, 8]
#將亂序序列中的最大值直接找出,而後將最大值和序列最後一個元素交換位置,最終咱們就將最大值找出放置到了最後的位置 def sort(alist): max_index = 0 #表示的是最大值的下標,一開始咱們假設列表中的第0個元素爲最大值 for i in range(len(alist)-1):#控制比較的次數 if alist[max_index] < alist[i+1]: max_index = i+1 #將最大值和最後一個元素交換位置,就能夠將最大值放置到序列的最後位置 alist[max_index],alist[len(alist)-1] = alist[len(alist)-1],alist[max_index] return alist alist = [3,8,5,2,0,7,6] print(sort(alist))
[3, 6, 5, 2, 0, 7, 8]
#完整代碼 def sort(alist): for j in range(0,len(alist)-1): max_index = 0 #表示的是最大值的下標,一開始咱們假設列表中的第0個元素爲最大值 for i in range(len(alist)-1-j):#控制比較的次數 if alist[max_index] < alist[i+1]: max_index = i+1 #將最大值和最後一個元素交換位置,就能夠將最大值放置到序列的最後位置 alist[max_index],alist[len(alist)-1-j] = alist[len(alist)-1-j],alist[max_index] return alist alist = [3,8,5,2,0,7,6] print(sort(alist))
[0, 2, 3, 5, 6, 7, 8]
須要將原始的序列僞裝拆分紅兩部分
定義一個變量叫作i
原始序列:[3,8,5,2,6,10,1]
[3, 8,5,2,6,10,1] ==》i=1
[3,8, 5,2,6,10,1] ==》i=2
#[3, 8,5,2,6,10,1] ==》i=1 i = 1 #i表示的是有序部分元素的個數 #alist[i]:無序部分的第一個元素 #alist[i-1]:有序部分的最後一個元素 if alist[i] < alist[i-1]: #有序部分的最後一個元素大於無序部分的第一個元素 alist[i],alist[i-1] = alist[i-1],alist[i] else: pass
#[6,8, 7,2,6,10,1] ==》i=2 i = 2 #i表示的是有序部分元素的個數 while i > 0: if alist[i] < alist[i-1]: alist[i],alist[i-1] = alist[i-1],alist[i]#[6,5,8, 2,6,10,1] i -= 1 #i是不能夠爲負數 else: break
#i的取值範圍是1-(n-1) for i in range(1,len(alist)): #i = 2 #有序部分有兩個元素 while i > 0: if alist[i] < alist[i-1]: alist[i],alist[i-1] = alist[i-1],alist[i]#[6,5,8, 2,6,10,1] i -= 1 #i是不能夠爲負數 else: break
#完整代碼 def sort(alist): #i的取值範圍是1-(n-1) for i in range(1,len(alist)): #i = 2 #有序部分有兩個元素 while i > 0: if alist[i] < alist[i-1]: alist[i],alist[i-1] = alist[i-1],alist[i]#[6,5,8, 2,6,10,1] i -= 1 #i是不能夠爲負數 else: break return alist alist = [3,8,5,2,0,7,6] print(sort(alist))
[0, 2, 3, 5, 6, 7, 8]
alist = [66,13,51,76,81,26,57,69,23]
基數:
將列表中第一個元素設定爲基準數字,賦值給mid變量,而後將整個列表中比基準小的數值放在基準的左側,比基準到的數字放在基準右側。而後將基準數字左右兩側的序列在根據此方法進行排放。
定義兩個指針,low指向最左側,high指向最右側
而後對最右側指針進行向左移動,移動法則是,若是指針指向的數值比基準小,則將指針指向的數字移動到基準數字原始的位置,不然繼續移動指針。
若是最右側指針指向的數值移動到基準位置時,開始移動最左側指針,將其向右移動,若是該指針指向的數值大於基準則將該數值移動到最右側指針指向的位置,而後中止移動。
若是左右側指針重複則,將基準放入左右指針重複的位置,則基準左側爲比其小的數值,右側爲比其大的數值。
#原始序列中比基數大的值放置到基數右側,比基數小的值放置到基數左側 def sort(alist): #low&hight表示的序列的起始位置的下標 low = 0 high = len(alist)-1 mid = alist[low] #基數 while low < high: #將原始序列中比基數小的值放置在基數的左側,比基數大的值放置在基數的右側 #注意:一開始的時候先將high向左偏移 while low < high: if alist[high] < mid: #high小於基數 alist[low] = alist[high] break else:#基數若是小於了high,將high向左偏移 high -= 1 #high想左偏移了覺得 #low向右偏移 while low <high: if alist[low] < mid:#若是low小於mid則讓low想右偏移 low += 1#讓low向右偏移一位 else: alist[high] = alist[low] break if low == high:#low和high重複,將基數賦值到low或者high的位置 alist[low] = mid #alist[high] = mid return alist
#加入遞歸後完整的代碼 def sort(alist,left,right): #low&hight表示的序列的起始位置的下標 low = left high = right #結束遞歸的條件 if low > high: return mid = alist[low] #基數 while low < high: #將原始序列中比基數小的值放置在基數的左側,比基數大的值放置在基數的右側 #注意:一開始的時候先將high向左偏移 while low < high: if alist[high] < mid: #high小於基數 alist[low] = alist[high] break else:#基數若是小於了high,將high向左偏移 high -= 1 #high想左偏移了覺得 #low向右偏移 while low <high: if alist[low] < mid:#若是low小於mid則讓low想右偏移 low += 1#讓low向右偏移一位 else: alist[high] = alist[low] break if low == high:#low和high重複,將基數賦值到low或者high的位置 alist[low] = mid #alist[high] = mid #指定操做做用到基數左側的子序列中 sort(alist,left,low-1) #指定操做做用到基數右側的子序列中 sort(alist,high+1,right) return alist
alist = [66,13,51,76,81,26,57,69,23] print(sort(alist,0,len(alist)-1))