约瑟夫问题(动态规划解法)

博客介绍了约瑟夫问题的动态规划求解方法,通过分析不同循环次数下的规律,得出公式,并利用该公式通过循环计算出最终答案,提高了效率,避免了m*n的复杂度,展示了算法的魅力。

Josephus problem solution with o(n)

1.Description

People are standing in a circle waiting to be executed. Counting begins at a specified point in the circle and proceeds around the circle in a specified direction. After a specified number of people are skipped, the next person is executed. The procedure is repeated with the remaining people, starting with the next person, going in the same direction and skipping the same number of people, until only one person remains, and is freed.

2.Introduction

We have seen this kind of problems before. You can stimulate the whole process to get the answer you want. But its time cost is large, which holds a m*n complexity. This method can be accepted when n and m are accepted small, but fail to handle those situations when n or m is quite large. Thus, today let’s introduce a new method with a complexity of o(n).

3.Dynamic planning

To find the formula to solve this problem, we need to go through several loops to get the inner principle.
Suppose we have n people initially, and the m th person will be executed.
when loop=1, undoubtedly, the (m-1)%n th person will be executed.
when loop=2, let’s see the current situation:
the people list become:
m,m+1,...,n-2,n-1,0,1,2,...,m-2
it will be convenience for us if we map the list above to a new list like this
0,1,2,3,...,n-3,n-2
the map looks like this:

m   -> 0  
m+1 -> 1  
...  
...  
k-3 -> n-3  
k-2 -> n-2  

the map here can be summarized as f(x)=(x-m)%n.
Now, let’s define an expression to represent our final answer: f(n,m).Then, it’s common sense that f(1,m)=0. The main problem is to find the relationship between f(1,m) and f(n,m). How can we think?
If we can find the relationship between f(n,m) and f(n-1,m), then we can repeatedly use this relationship to find the relationship between f(n,m) and f(1,m).
As I mentioned above, we use a map from f(n) to f(n-1). Now, we can map it back, then we get what we want:
f(n,m)=(f(n-1,m)+m)%n
Now we can use this formula to get the final answer using a for loop.

4.Code

#include <iostream>
using namespace std;
int main(void){
    int n,m;
    int answer=0;           //we initial answer equals to 0 because for the last f(1,m)=0
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        answer=(answer+m)%i;
    }
    cout<<answer<<endl;
}

You can see this code is incredible simple but much faster than just stimulating the whole process. And that’s charm of algorithm, I think.

本教程为授权出品课程介绍:1.算法是程序的灵魂,优秀的程序在对海量数据处理时,依然保持高速计算,就需要高效的数据结构和算法支撑。2.网上数据结构和算法的课程不少,但存在两个问题:1)授课方式单一,大多是照着代码念一遍,数据结构和算法本身就比较难理解,对基础好的学员来说,还好一点,对基础不好的学生来说,基本上就是听天书了2)说是讲数据结构和算法,但大多是挂羊头卖狗肉,算法讲的很少。 本课程针对上述问题,有针对性的进行了升级 3)授课方式采用图解+算法游戏的方式,让课程生动有趣好理解 4)系统全面的讲解了数据结构和算法, 除常用数据结构和算法外,还包括程序员常用10大算法:二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法、马踏棋盘算法。可以解决面试遇到的最短路径、最小生成树、最小连通图、动态规划问题及衍生出的面试题,让你秒杀其他面试小伙伴3.如果你不想永远都是代码工人,就需要花时间来研究下数据结构和算法。教程内容:本教程是使用Java来讲解数据结构和算法,考虑到数据结构和算法较难,授课采用图解加算法游戏的方式。内容包括: 稀疏数组、单向队列、环形队列、单向链表、双向链表、环形链表、约瑟夫问题、栈、前缀、中缀、后缀表达式、中缀表达式转换为后缀表达式、递归与回溯、迷宫问题、八皇后问题、算法的时间复杂度、冒泡排序、选择排序、插入排序、快速排序、归并排序、希尔排序、基数排序(桶排序)、堆排序、排序速度分析、二分查找、插值查找、斐波那契查找、散列、哈希表、二叉树、二叉树与数组转换、二叉排序树(BST)、AVL树、线索二叉树、赫夫曼树、赫夫曼编码、多路查找树(B树B+树和B*树)、图、图的DFS算法和BFS、程序员常用10大算法、二分查找算法(非递归)、分治算法、动态规划算法、KMP算法、贪心算法、普里姆算法、克鲁斯卡尔算法、迪杰斯特拉算法、弗洛伊德算法马踏棋盘算法。学习目标:通过学习,学员能掌握主流数据结构和算法的实现机制,开阔编程思路,提高优化程序的能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值