链表问题(4)-- 环形单链表的约瑟夫问题

        帮我对象做了很长时间的毕业设计,关于这个每日一算法在这段时间没有坚持下来,十分惭愧。去年到今年的几个月给她做了一个毕设的小项目,是一个关于人脸活体验证身份认证系统,我会在另一个版块给大家慢慢发一些关于其中的代码(因为她还没有答辩完,不能公开所有的代码),同时巩固自己的学习。

好了,开始今天每日一算法的总结:


题目:

关于著名的约瑟夫问题是这样的:在古罗马时期,罗马人占领乔塔帕特后,39个犹太人躲到了一个洞中,他们决定宁愿死也不要让敌人抓到,于是决定了一个自杀方式,39个人排成一个首尾相连的圆圈,由第一个人报数,报数到第3个的人就自杀,然后再由下一个人开始重新报1,报数到3的人再自杀,依次这样下去,直到只剩下最后一个人,那个人可以自己选择生死。现在请用单向链表完成该过程的表示。

分析:

输入:一个环形单向链表的头节点head和报数的值m。

返回:最后生存下来的节点

要求:

如果链表节点数为N,想要在时间复杂度为O(N)完成原问题,应该如何实现?

普通解决方法:

1. 如果链表为空或者链表节点数为1,或者m的值小于1,则不用调整就直接返回了;

2. 在环形链表中遍历每个节点,不断转圈,不断让每个节点报数;

3. 当报数到达m时,就删除当前的报数节点;

4. 删除节点货,把上一个节点指向删除节点的下一节点。继续转圈报数,继续删除。

5. 不停的删除,直到节点只剩下一个节点,过程结束。

具体代码如下:

Node.java

package algorithm_13;

public class Node {
	public int value;
	public Node next;

	public Node(int data) {
		this.value = data;
	}
}
algorithm_13.java

package algorithm_13;


public class algorithm_13 {

	public static Node josephusKill(Node head, int m){
		if(head == null || head.next == head || m < 1){
			return head;
		}
		Node last = head;
		while(last.next != head){
			last = last.next;
		}
		int count = 0;
		while(head != last){
			if(++count == m){
				last.next = head.next;
				count = 0;
			}
			else{
				last = last.next;
			}
			head = last.next;
		}
		return head;
	}
	public static Node init(Node head){
		Node start = head;
		for (int i = 2; i < 3; i++){
			head.next = new Node(i);
			head = head.next;
		}
		head.next = start;
		return head;
	}
	public static void print(Node head){
		Node cur = head;
		   do {	           
			   	System.out.print(cur.value + " ");  
           cur = cur.next;  
           }
	        while (cur != null && cur != head) ;
	        	System.out.print(" \n");
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Node test = new Node(1);
		init(test);
		System.out.println("Ring linked list: ");
		print(test);
		Node res = josephusKill(test, 3);
		System.out.println("Last living node: ");
		print(res);
	}

}
结果如下:

Double linked list: 
1 2  
Last living node: 
2  

*****注意:*******

普通的解法在实现上每次删除掉一个节点都要遍历m次,一共要删除n-1个节点,所以此方法的时间复杂度了O(n*m)。

*******************


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值