Josephubs(約瑟夫環)解

問題描述:

Josephubs(約瑟夫環):假設有n我的圍坐一圈, 如今要求從k我的開始報數, 報到第m個數的人退出。而後從下一我的開始繼續報數並按一樣規則退出,直到全部人退出。要求按順序輸出各出列人的編號python

問題分析:

  • 初始算法

    • 創建一個包含n我的(的編號)的表。
    • 找到第k我的, 那裏開始。
  • 處理過程當中採用把相應表元素修改成0的方式表示已出列, 反覆作:app

    • 數m我的(尚在座的人),遇到表的末端就轉回下標0繼續。
    • 把表示第m我的的 表元素修改成0。
  • n我的出列即結束spa

採用python自帶的list ADT模塊

思路描述:建立一個list, 當第m個位置被排出的時候該元素位置爲0, 那麼下次繼續設置初始下標爲 i+1 % n , count用於統計, 肯定在排出全部空位置以後的真實第m個位置。設計

def josephus(n, k, m):
    people_num = list(range(1, n + 1))
    print(people_num)
    i = k - 1  # 第k我的的下標值
    for num in range(n):
        count = 0  # 用於計算是第幾我的
        
        while count < m:
            if people_num[i] != 0:
                count += 1
           
            if m == count:
                print("找到該同窗爲:{}".format(people_num[i]))
                people_num[i] = 0
            i = (i+1) % n # 下標反轉, 第二次查找時因爲前面排出一個同窗,因此須要+1
        
        if num < n-1:
            print('第{}次查找結束'.format(num))
        else:
            print('結束')
		   
複製代碼
  • 時間複雜度分析
    • 當m=1的時候, 內循環每次只要執行一次,因此內循環的時間複雜度爲O(1), 因此綜合時間度爲O(n)
    • 當 m = n時,那麼內循環須要把整個表遍歷一遍,以後須要執行 i = (i+1) % n 語句,因此它的時間複雜度爲O(n2)。

基於順序表的解

設計思路:用python list 的pop取出須要元素, 從新計算i值,code

def josephus1(n, k, m):
    people_num = list(range(1, n + 1))
    num, i = n, k-1
    
    for num in range(n, 0, -1): # 倒排
        i = (i + m - 1) % num
        print('第{}同窗被排出'.format(people_num.pop(i)))
			
複製代碼
  • 時間複雜度分析orm

    該算法用了一個for循環,時間複雜度爲O(n), python list pop()方法也是O(n),因此該方法的綜合時間複雜度仍是O(n2)string

基於循環單鏈表的解

設計思路: 把圍坐一圈的人當成循環鏈表, 經過next鏈接,先到初始第k後第m個next時, 刪除該節點, 由於是循環節點, 因此能夠按照節點順序依次執行下去, 直到刪除最後一個元素it

# 首先要建立一個簡單的鏈表節點
class LNode(object):
	def __init__(self, elem, next_=None)
		self.elem = elem
		self.next = next_

# 循環單鏈表基類
class LClist(objects):
	
	def __init__(self):
		self._rear = None
	
	def is_empty(self):
		return self._rear is None
	
	def prepend(self, elem):
		""" 從頭部加入 """
		p = LNode(elem)
		if self._rear is None:
			p.next = p # 單節點組成環
			self._rear.next = p
		else:
			p.next = self._rear.next
			self._rear.next = p
	
	def append(self, elem):
		""" 從尾部插入 """
		self. prepend(elem)
		self._rear = self._rear.next
	
	def pop(self):
		""" 頭部彈出 """
		if self._rear._rear is None:
			return False
		
		p = self._rear.next:
		if self._reear is p:
			self._rear = None
		else:
			self._rear = None
		
		return p.elem
	
class Josehups(LCList):
	def turn(self, m):
		for i in range(m):
			self._rear = self._rear.next
		
	
	def __init__(self, n, k, m):
		LCList.__init__(self)
		for i in range(n):
			self.append(i+1)
		
		self.turn(k-1)
		while not self.is_empty():
			self.turn(m-1)
			print(self.pop() if self.is_empty() else "")
	
	
複製代碼
  • 時間複雜度分析io

    初建表的複雜度爲O(n), 後面循環的算法複雜度爲O(m x n), 每次旋轉的時間複雜度爲O()

相關文章
相關標籤/搜索