最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C/C++經(jīng)典算法之約瑟夫問題詳解

 更新時間:2021年07月31日 09:59:49   作者:是一只派大鑫  
這篇文章主要給大家介紹了關(guān)于C/C++經(jīng)典算法之約瑟夫問題的相關(guān)資料,約瑟夫環(huán)問題是一道經(jīng)典的數(shù)據(jù)結(jié)構(gòu)的題目,本文介紹了解決約瑟夫問題的三種方法,需要的朋友可以參考下

什么是約瑟夫問題? 

約瑟夫問題:n個人圍成一圈,初始編號從1~n排列,從約定編號為x的人開始報數(shù),數(shù)到第m個人出圈,接著又從1開始報數(shù),報到第m個數(shù)的人又退出圈,以此類推,最后圈內(nèi)只剩下一個人,這個人就是贏家,求出贏家的編號。

是不是有點點復(fù)雜,其實該問題歸結(jié)為模擬類型的算法題,根據(jù)題目要求模擬即可。

我說,一行代碼解決約瑟夫問題!

???我去

別著急,我們一步一步學(xué)習(xí)

方法一:數(shù)組

在第一次遇到這個題的時候,我是用數(shù)組做的,我猜絕大多數(shù)人也都知道怎么做。方法是這樣的:

用一個數(shù)組來存放 1,2,3 ... n 這 n 個編號,如圖(這里我們假設(shè)n = 6, m = 3)

 然后不停著遍歷數(shù)組,對于被選中的編號,我們就做一個標(biāo)記,例如編號 arr[2] = 3 被選中了,那么我們可以做一個標(biāo)記,例如讓 arr[2] = -1,來表示 arr[2] 存放的編號已經(jīng)出局的了。

然后就按照這種方法,不停著遍歷數(shù)組,不停著做標(biāo)記,直到數(shù)組中只有一個元素是非 -1 的,這樣,剩下的那個元素就是我們要找的元素了。我演示一下吧:

 

這種方法簡單嗎?思路簡單,但是編碼卻沒那么簡單,臨界條件特別多,每次遍歷到數(shù)組最后一個元素的時候,還得重新設(shè)置下標(biāo)為 0,并且遍歷的時候還得判斷該元素時候是否是 -1。用這種數(shù)組的方式做,千萬不要覺得很簡單,編碼這個過程還是挺考驗人的。

這種做法的時間復(fù)雜度是 O(n * m), 空間復(fù)雜度是 O(n);

下面給出數(shù)組方法的參考代碼:

#include<algorithm>
#include<iostream>
using namespace std;
int main(){
	int a[1001]={0}; //初始化化數(shù)組作為環(huán)
	int n,m;//n代表總的人數(shù),m代表報數(shù)到幾退出
	cin>>n>>m;
	int count=0;//記錄退出的個數(shù)
	int k=-1;//這里假定開始為第一個人,下標(biāo)為0,編號為1,如需從編號x開始,則k=x-2
	while(count<n-1){  //總共需要退出n-1個人
		int i=0;//記錄當(dāng)前報數(shù)編號
		while(i<m){
			k=(k+1)%n; //循環(huán)處理下標(biāo)
			if(a[k]==0){
				i++;
				if(i==m){
					a[k]=-1;
					count++;
				}
			}
		}
	}
	for(int i=0;i<n;i++){
		if(a[i]==0){
			printf("%d\n",i+1);
			break;
		}
	}
	return 0;
}

方法二:環(huán)形鏈表

學(xué)過鏈表的人,估計都會用鏈表來處理約瑟夫環(huán)問題,用鏈表來處理其實和上面處理的思路差不多,只是用鏈表來處理的時候,對于被選中的編號,不再是做標(biāo)記,而是直接移除,因為從鏈表移除一個元素的時間復(fù)雜度很低,為 O(1)。當(dāng)然,上面數(shù)組的方法你也可以采用移除的方式,不過數(shù)組移除的時間復(fù)雜度為 O(n)。所以采用鏈表的解決方法如下:

1、先創(chuàng)建一個環(huán)形鏈表來存放元素:

2、然后一邊遍歷鏈表一遍刪除,直到鏈表只剩下一個節(jié)點,我這里就不全部演示了

 

感興趣的友友可以自己實現(xiàn)以下代碼,這里就不放了

下面我們來看看,是如何一行代碼實現(xiàn)約瑟夫問題!

方法三:遞歸

其實這道題還可以用遞歸來解決,遞歸是思路是每次我們刪除了某一個人之后,我們就對這些人重新編號,然后我們的難點就是找出刪除前和刪除后編號的映射關(guān)系。

我們定義遞歸函數(shù) f(n,m) 的返回結(jié)果是存活士兵的編號,顯然當(dāng) n = 1 時,f(n, m) = 1。假如我們能夠找出 f(n,m) 和 f(n-1,m) 之間的關(guān)系的話,我們就可以用遞歸的方式來解決了。我們假設(shè)人員數(shù)為 n, 報數(shù)到 m 的人就自殺。則剛開始的編號為

… 1 ... m - 2

m - 1

m

m + 1

m + 2 ... n …

進(jìn)行了一次刪除之后,刪除了編號為 m 的節(jié)點。刪除之后,就只剩下 n - 1 個節(jié)點了,刪除前和刪除之后的編號轉(zhuǎn)換關(guān)系為:

刪除前 --- 刪除后

… --- …

m - 2 --- n - 2

m - 1 --- n - 1

m ---- 無(因為編號被刪除了)

m + 1 --- 1(因為下次就從這里報數(shù)了)

m + 2 ---- 2

… ---- …

新的環(huán)中只有 n - 1 個節(jié)點。且刪除前編號為 m + 1, m + 2, m + 3 的節(jié)點成了刪除后編號為 1, 2, 3 的節(jié)點。

假設(shè) old 為刪除之前的節(jié)點編號, new 為刪除了一個節(jié)點之后的編號,則 old 與 new 之間的關(guān)系為 old = (new + m - 1) % n + 1。

 注:有些人可能會疑惑為什么不是 old = (new + m ) % n 呢?主要是因為編號是從 1 開始的,而不是從 0 開始的。如果 new + m == n的話,會導(dǎo)致最后的計算結(jié)果為 old = 0。所以 old = (new + m - 1) % n + 1. 這樣,我們就得出 f(n, m) 與 f(n - 1, m)之間的關(guān)系了,而 f(1, m) = 1.所以我們可以采用遞歸的方式來做。

 代碼如下:

int f(int n, int m){
    return n == 1 ? n : (f(n - 1, m) + m - 1) % n + 1;
}

臥槽,以后有人讓你手寫約瑟夫問題,你就扔這一行代碼給它。 

總結(jié)

到此這篇關(guān)于C/C++經(jīng)典算法之約瑟夫問題的文章就介紹到這了,更多相關(guān)C/C++約瑟夫問題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 分享C++面試中string類的一種正確寫法

    分享C++面試中string類的一種正確寫法

    C++ 的一個常見面試題是讓你實現(xiàn)一個 String 類,限于時間,不可能要求具備 std::string 的功能,但至少要求能正確管理資源
    2013-11-11
  • 基于c++中的默認(rèn)拷貝函數(shù)的使用詳解

    基于c++中的默認(rèn)拷貝函數(shù)的使用詳解

    本篇文章對c++中默認(rèn)拷貝函數(shù)的使用進(jìn)行了詳細(xì)的分析介紹。需要的朋友參考下
    2013-05-05
  • Qt物聯(lián)網(wǎng)管理平臺之實現(xiàn)自動清理早期數(shù)據(jù)功能

    Qt物聯(lián)網(wǎng)管理平臺之實現(xiàn)自動清理早期數(shù)據(jù)功能

    隨著時間的增加,存儲的歷史記錄也在不斷增加,如果設(shè)備數(shù)量很多,存儲間隔很短,不用多久,數(shù)據(jù)庫中的記錄就非常多,至少是百萬級別起步,而且有些用戶還是需要存儲每一次的采集的數(shù)據(jù)。本文將利用Qt實現(xiàn)自動清理早期數(shù)據(jù),需要的可以參考一下
    2022-07-07
  • 深入C中常用的三種排序方法總結(jié)以及探討分析

    深入C中常用的三種排序方法總結(jié)以及探討分析

    本篇文章是對C中常用的三種排序方法總結(jié)以及探討分析的概述,需要的朋友參考下
    2013-05-05
  • 關(guān)于C++中strcpy函數(shù)例題講解

    關(guān)于C++中strcpy函數(shù)例題講解

    在本篇文章里小編給大家整理的是關(guān)于C++中strcpy函數(shù)例題講解內(nèi)容,需要的朋友們可以參考下。
    2020-05-05
  • C語言中數(shù)組常用的一些排序算法小結(jié)

    C語言中數(shù)組常用的一些排序算法小結(jié)

    數(shù)組的排序方法有很多,效率也各不相同,下面這篇文章主要給大家介紹了關(guān)于C語言中數(shù)組常用的一些排序算法的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • C++實現(xiàn)LeetCode(135.分糖果問題)

    C++實現(xiàn)LeetCode(135.分糖果問題)

    這篇文章主要介紹了C++實現(xiàn)LeetCode(135.分糖果問題),本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • 一文解析C語言中動態(tài)內(nèi)存管理

    一文解析C語言中動態(tài)內(nèi)存管理

    這篇文章主要為大家詳細(xì)介紹了C語言中動態(tài)內(nèi)存管理的相關(guān)知識,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,有需要的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-02-02
  • C語言二維數(shù)組應(yīng)用之井字棋游戲

    C語言二維數(shù)組應(yīng)用之井字棋游戲

    這篇文章主要為大家詳細(xì)介紹了C語言二維數(shù)組應(yīng)用之井字棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C++結(jié)構(gòu)體與類的區(qū)別詳情

    C++結(jié)構(gòu)體與類的區(qū)別詳情

    這篇文章主要介紹了C++結(jié)構(gòu)體與類的區(qū)別,C++中的struct對C中的struct進(jìn)行了擴充,它已經(jīng)不再只是一個包含不同數(shù)據(jù)類型的數(shù)據(jù)結(jié)構(gòu)了,它已經(jīng)獲取了太多的功能。下面我們一起進(jìn)入文章倆姐具體內(nèi)容,需要的朋友也可以參考一下
    2021-11-11

最新評論

康马县| 搜索| 文昌市| 玉屏| 长白| 阿荣旗| 元江| 南雄市| 丹江口市| 阿尔山市| 鹤壁市| 富民县| 阳信县| 兴仁县| 嵊泗县| 元氏县| 肥东县| 涞源县| 海丰县| 桂阳县| 若羌县| 怀仁县| 彭阳县| 永川市| 黔西| 璧山县| 樟树市| 嘉祥县| 浠水县| 阿荣旗| 腾冲县| 潜江市| 武隆县| 张北县| 平江县| 织金县| 谢通门县| 民县| 防城港市| 开封市| 泽普县|