环形单链表约瑟夫问题

一个环形单链表,从头结点开始向后,指针每移动一个结点,就计数加1,当数到第m个节点时,就把该结点删除,然后继续从下一个节点开始从1计数,循环往复,直到环形单链表中只剩下了一个结点,返回该结点。

思路:当链表为空或者链表只有一个节点或者m<1时,不做处理,直接返回原链表即可。

if (head==null||head.next==head||m<1){
		return head;			
	}

           否则:1:首先遍历整个链表,得到链表的最后一个节点 last , 此时 last.next=head

Node last=head;
while (last.next!=head) {
	last=last.next;			
}

                       2:通过两个指针(last,head)的循环操作,删除遍历到的第m个节点即可。             

int count=0;
while (head.next!=head) {
    if (++count==m) {
		last.next=head.next;//删除节点head
		count=0;
	}
	else{
		last=last.next;		
	}
	head=last.next;
}
return head;
		

整个代码:

public class Node{
		public int value;
		public Node next;
		public Node(int value){
			this.value=value;
		}
		
	}
public Node josephuskill(Node head,int m){
		if (head==null||head.next==head||m<1){
			return head;			
		}
		//首先找到单链表的最后一个节点last,此时last.next=head
		Node last=head;
		while (last.next!=head) {
			last=last.next;			
		}
		//循环删除第m个节点,直到只剩下一个节点为止,此时这个节点的next=他自己
		int count=0;
		while (head.next!=head) {
			if (++count==m) {
				last.next=head.next;//删除节点head
				count=0;
			}
			else{
				last=last.next;		
			}
			head=last.next;
		}
		return head;
		
	}

 

循环单链表是一个环形链表,最后一个节点的 next 指针指向头结点。求解约瑟夫问题可以利用循环单链表模拟,具体步骤如下: 1. 构建循环单链表,将每个人的编号作为节点的数据域,将每个节点的 next 指针指向下一个节点。 2. 定义一个计数器 count,用于记录当前数到了第几个节点。 3. 从头节点开始遍历链表,每次计数器加1,直到计数器的值等于 m 时,就找到了要删除的节点。将该节点从链表中删除,并将计数器 count 重置为 0。 4. 重复步骤 3,直到链表中只剩下一个节点,此时该节点即为最后一个幸存者的编号。 下面是具体的代码实现: ```c++ #include <iostream> using namespace std; struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(nullptr) {} }; int josephus(int n, int m) { ListNode* head = new ListNode(1); ListNode* cur = head; for (int i = 2; i <= n; i++) { cur->next = new ListNode(i); cur = cur->next; } cur->next = head; // 构造循环链表 int count = 0; while (cur->next != cur) { // 链表中还有多于一个节点 count++; if (count == m) { ListNode* temp = cur->next; cur->next = temp->next; delete temp; // 释放要删除的节点 count = 0; } else { cur = cur->next; } } int ans = cur->val; delete cur; // 释放最后一个节点 return ans; } int main() { int n = 5, m = 2; int ans = josephus(n, m); cout << "The last survivor's number is: " << ans << endl; return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值