约瑟夫环问题

80 阅读1分钟

题干略,话说这个约瑟夫好贱啊,坑了自己士兵,然后自己投降了

1:自创答案

int lastOne(int N){
	// 将数组所有值赋值为0 代表没自杀 
	int a[MAXSIZE] = {0}, i;
	
	int outCount = 0, num = 1;
	for(i=1; outCount<N-1; i = (i == N ? 1 : i+1)){
		if(a[i] == 0){
			if(num == 3){
				num = 0;
				a[i] = 1;
				++outCount;
			}
			++num;
		}
	}
	// 循环找到 没有被删除的元素 
	for(int i=1; i<=N; ++i){
		if(a[i] == 0){
			return i;
		}
	}
} 

2:数组法实现,人员从0开始编号

//  不符合题意的“标准答案” 
void jsf(int a[], int n, int m){
	int i, j, k=0;
	
	for(i=0; i<n; ++i){
		j = 1;
		while(j<m){
			while(a[k] == 0){
				k = (k+1) % n;
			}
			++j;
			k = (k+1) % n;
		}
		while(a[k] == 0){
			k = (k+1) % n;
		}
		a[k] = 0; 
		printf("%d ", k); 
	}
} 

3:循环链表实现

// 循环链表法适合大规模数据,时间复杂度较低是O(n),数组法是O(n^2) 
// 固定 100个人  数到3的人去死      1: 没死  0: 死 
void jsf_linked(Node* head){
// 注意: 用a存储结果,注意跳过头节点, p->data 存储了结点的编号 1...100 
	int t=0; // 统计删了几个了
	int a[100];
	Node* p = head->next;
	
	while(t<100){
		for(int i=1; i<=3; ++i){
			if(i==3){
				while(p->data == 0){
					p = p->next;
					if(p == head){
						p = p->next;
					}
				}
				a[t] = p->data; 
				p->data = 0; 
				// ↓ 
				p = p->next;
				if(p == head){
					p = p->next;
				}
				// ↑ 这一部分可以去掉 
				++t;
			}else{
				while(p->data == 0){
					p = p->next;
					if(p == head){
						p = p->next;
					}
				}
				p = p->next;
				if(p == head){
					p = p->next;
				}
			}
		}
	}
	
	for(int i=0; i<100; ++i){
		printf("%d ", a[i]);
	}
}