Classic Algorithm-----Joseph's Problem (C Language)

 Table of contents

Preface

story background

Joseph problem

Circular linked list solution

 Array solution


Preface

        Today we are going to play an interesting problem, which is the Joseph problem. This problem comes from a story in the European Middle Ages. Now we will solve this interesting problem through programming. Let’s take a look!

story background

        It is said that the famous Jewish historian Josephus had the following story: After the Romans captured Chotapat, 39 Jews hid in a cave with Josephus and his friends. The 39 Jews decided that they would rather die than be caught by the enemy. , so a suicide method was decided. 41 people lined up in a circle, and the first person started counting. Every time the third person was counted, the person must commit suicide, and then the next person counted again until everyone committed suicide. Until death. However, Josephus and his friends did not want to comply. First start with one person, cross k-2 people (because the first person has been crossed), and kill the k -th person. Then, go past k-1 people and kill the k -th person. This process continues along the circle until finally only one person remains, and this person can continue to live. The question is, given and , where to stand initially to avoid being executed. Josephus asked his friend to pretend to obey first. He placed his friend and himself in the 16th and 31st positions, thus escaping the death game.

        The 17th-century French mathematician Gaspar told such a story in "The Game of Numbers": 15 believers and 15 non-believers were in danger in the deep sea. Half of them had to be thrown into the sea before the rest could survive. It was difficult, so I came up with a way: 30 people gathered in a circle, counting from the first person, and every ninth person was thrown into the sea. This cycle continued until there were only 15 people left. Asking how to arrange it so that every time those thrown into the sea are non-believers.

Joseph problem

Get two data from the keyboard, n and s. n represents the number of people, and s represents counting from the first person. When the sth person is counted, that person will be out. Question: Who is the last person left? several?

Circular linked list solution

        Here we can solve this problem in the form of a circular linked list. The process diagram is as follows:

First create a corresponding circular linked list based on the currently entered number of people, and store the location of each person in it in turn.

 Then start counting from the first person, and perform the deletion operation when the third person is counted, as shown below, and then start a new round from the fourth node...

The code looks like this: 

#include <stdio.h>
#include<stdlib.h>
//节点
typedef struct node {
	int num;
	struct node* next;
}Node;

//创建一个环形链表
Node* create_list(int n) {
	Node* head, * tail;
	head = tail = NULL;
	for (int i = 0; i < n; i++) {
		Node* p = (Node*)malloc(sizeof(Node));
		p->num = i + 1;    //依次标记当前位置
		if (head == NULL) {
			head = p;
			tail = p;
			head->next = NULL;
		}
		else
		{
			tail->next = p;
			tail = p;
		}
		tail->next = head;
	}
	return head;  //返回头结点
}

int main() {
	int n, s;
	printf("请输入:");
	scanf("%d %d", &n, &s);
	Node* cur = create_list(n);
	int count = 1; //此时cur指向的是第一个节点,所以count为1
	while (n != 1) {	//当n=1时候,结束循环,此时剩下最后一个人
		count++;//先进行count统计
		if (count == s) {
			n--;	
			//进行删除节点操作
			Node* del_node = cur->next;	
			cur->next = del_node->next;
			free(del_node);//释放掉这个节点
			//此时count回归到1,也就是重新开始新的一轮
			count = 1;
		}
		cur = cur->next;
	}
	printf("最后剩下的是:%d\n", cur->num);
}

 Array solution

         Different from the linked list, the array cannot customize the number of people, which means that the number of the array here is written in advance, and the execution efficiency of the array is higher. The circular linked list needs to be executed through traversal, which has a higher time complexity. is O(n), and the array can directly find this position with a time complexity of O(1). There is no need to traverse one by one. The code is as follows:

//数组实现
#include<stdio.h>
void function(int* num, int length, int s, int start) {
	int count = 0;
	int i = start - 1;//标记起始位置
	int n = length;	//当前人数
	while (n != 1) {
		i = (i + s - 1) % n;	//下一个出局人的位置
		for (int j = i + 1; j < length; j++)
			num[j - 1] = num[j];	//进行删除操作,把要删除的数字后面的依次往前移动,覆盖掉这个要删除的数字
		n--;//删除操作完成,减少一个人
		if (i == n) {	//当i超出数组范围的时候,i就回归到第一个为止
			i = 0;
		}
	}
	printf("最后一个 :%d", num[i]);
	return;
}

int main() {
	int num[6];//这里就已经定义好了6个人
	int s;	//每次数到s,出局一个
	printf("请输入:");
	scanf("%d", &s);
	for (int i = 0; i < sizeof(num) / sizeof(int); i++)
		num[i] = i+1;
	function(num, sizeof(num) / sizeof(int), s, 0);
}

That’s it for today, see you next time!

Share a wallpaper:

Guess you like

Origin blog.csdn.net/m0_73633088/article/details/133031010