java约瑟夫环迭代器_约瑟夫环问题的动态规划解法

约瑟夫环问题

已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为0的人开始报数,数到k的那个人出列;他的下一个人又从1开始报数,数到k的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列,求出最后一个出列的人。

链表模拟解法

今天上数据结构课,讲到约瑟夫环问题,手动实现的方法不再赘述。对于STL,可以直接只用list,使用迭代器实现查找和删除操作,但是这种方法的复杂度是O(N×K)的,非常耗时

动态规划解法

设dp[i]为当前还剩i个人,重新从[0, i)编号后,出列第k个人后,下一个开始报数的人的编号。容易发现dp[1]=0,那么直接从dp[i-1]递推出dp[i]即可。递推的过程类似于数列的左右滑动,递推式为dp[i] = (dp[i-1] + k) % i。这种方法的时间复杂度为O(N)

STL链表实现代码

#include

using namespace std;

int main() {

int n, k;

while(cin >> n >> k) {

list v;

for(int i = 1; i <= n; ++i)

v.push_back(i);

auto pos = v.begin();

while(v.size() > 1) {

for(int i = 1; i < k; ++i) {

++pos;

if(pos == v.end())

pos = v.begin();

}

pos = v.erase(pos);

if(pos == v.end())

pos = v.begin();

}

cout << v.front() << endl;

}

return 0;

}

C++动态规划实现代码

#include

using namespace std;

const int maxn = 1024;

int n, k, dp[maxn]; //n为初始总人数,k为出列的数

int main() {

while(cin >> n >> k) {

dp[1] = 0; //初始化

for(int i = 2; i <= n; ++i)

dp[i] = (dp[i-1] + k) % i; //递推

cout << dp[n] << endl; //最后出列人数的‘下标’

}

return 0;

}

OJ真题演练(HDU2925)

#include

using namespace std;

const int maxn = 1024000;

int n, k, dp[maxn];

int main() {

while(scanf("%d%d", &n, &k), n||k) {

dp[1] = 0;

for(int i = 2; i <= n; ++i)

dp[i] = (dp[i-1] + k) % i;

printf("%d %d %d\n", n, k, dp[n]+1);

}

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值