Joseph Ring Question

Source: Internet
Author: User

Joseph Ring is a mathematical application problem: known n individuals (denoted by number 1,2,3...N respectively) sit around a round table. From the number of people who are numbered K, the person who counts to M is out of the way; his next man counted from 1, and the man who counts to M. went out again, and repeated it until all the people around the table were out.

C code such as the following (Joseph.cpp):

#include <stdio.h> #include <stdlib.h> #include <malloc.h>typedef struct _node{struct _node* next;int number;} Node,*linklist;linklist Create (int n); void Joseph (Linklist head, int k, int m); int main () {linklist head;int m, N, k;printf ("Please input N:"); scanf ("%d", "&n");p rintf ("Please input M:"), scanf ("%d", &m);p rintf ("Please input K:"); scanf ( "%d", &k), head = Create (n);p rintf ("The sequences of leaving the list is:"); Joseph (Head,k,m); return 0;} linklist Create (int n) {linklist head = (linklist) malloc (sizeof (node)); node *tail;int i;head->next = head;head-> Number = 1;tail = Head;for (i=2;i<=n;i++) {node *p = (node*) malloc (sizeof (node));p->number = I;p->next = tail-> Next;tail->next = P;tail = P;} return head;} void Joseph (linklist head, int k, int m) {int j;node *p;node *q;if (m = = 1 && k = = 1) {p = head;while (p->next! = h EAD) {printf ("%d", p->number), q = P->next;free (p);p = q;} printf ("%d\n", P->number);} else if (m = = 1 && k! = 1) {p= Head;for (j=1; j<k-1; j + +) P = p->next;while (Head->next! = head) {q = P->next;p->next = q->next;printf (" %d ", q->number); if (q = = head) head = Q->next;free (q);} printf ("%d\n", Head->number);} Else{p = Head;for (j=1; j<k; j + +) P = p->next;while (Head->next! = head) {for (j=1; j<m-1; j + +) p = P->next;q = P ->next;p->next = q->next;printf ("%d", Q->number), if (q = = head) head = Q->next;free (q);p = P->next;} printf ("%d\n", Head->number);}}

Pay special attention to whether the value of M and K equals 1.


Several sets of test results for example are as follows:

1, M! = 1,k! = 1



2, M! = 1,k = = 1


3, M = = 1,k! = 1


4, M = = 1,k = = 1



The above procedure, the reason is to discuss the situation of m==1 and K==1, is because in a one-way loop linked list to delete a node, you must first find the node of the precursor node, and then change the relevant pointer field, so that the chain of circular chain, and m=1,k=1, to make the loop chain list chain, The tail node of the list must be found first, so it should be discussed in different situations.

In view of this, the thought of using a two-way circular linked list, to delete a node, do not need to find the precursor node, even if the first node is deleted, there is no need to find the tail node.

C code such as the following see (Joseph2.cpp), can see the code logic concise a lot:

#include <stdio.h> #include <stdlib.h> #include <malloc.h>typedef struct _node{struct _node* prev; struct _node* next;int number;} Node,*linklist;linklist Create (int n); void Joseph (Linklist head, int k, int m); int main () {linklist head;int m, N, k;printf ("Please input N:"); scanf ("%d", "&n");p rintf ("Please input M:"), scanf ("%d", &m);p rintf ("Please input K:"); scanf ( "%d", &k), head = Create (n);p rintf ("The sequences of leaving the list is:"); Joseph (Head,k,m); return 0;} linklist Create (int n) {linklist head = (linklist) malloc (sizeof (node)); node *tail;int i;head->next = head;head-> Prev = Head;head->number = 1;tail = Head;for (i=2;i<=n;i++) {node *p = (node*) malloc (sizeof (node));p->number = i;p ->next = Tail->next;p->prev = Tail;tail->next = P;tail = P;head->prev = tail;} return head;} void Joseph (linklist head, int k, int m) {int I;node *p;node *q;p = head;for (i=1; i<k; i++)//Get start count node P = P->next;whi Le (head->next! = head) {for (i=1; i<m; i++) p = p->next;//Gets the first node of each round count, that is, the node to be deleted q = P->next;q->prev = P->prev;p->prev->next = q;printf ("%d",p-> number); if (p = = head)//Assume that the first node is deleted, you need to set the head pointer again head = Q;free (p);p = q;//Delete a node and start counting}printf again from the next node of the node ("%d\n", Head->number);}

To get the same result as the first code:






Assuming you can use list in the C + + standard library to emulate a circular list, the logic is clearer and the code is more concise.

C + + code such as the following (Joseph3.cpp):

#include <iostream> #include <list>using namespace std;void Joseph (int n, int m, int k); int main () {int n,m,k; cout<< "Please input N:";cin>>n;cout<< "Please input M.:";cin>>m;cout<< "please Inpur K:"; cin>>k;cout<< "The sequences of leaving the list is:"; Joseph (N,m,k); return 0;} void Joseph (int n, int m, int k) {list<int> numbers;int i,j;for (i=1; i<=n; i++) Numbers.push_back (i); list<int& Gt;::iterator current = Numbers.begin (), List<int>::iterator next;for (i=1; i<k; i++) {++current;if (current = = Numbers.end ()) current = Numbers.begin ();} while (Numbers.size () >1) {to (i=1; i<m; i++) {++current;if (current = = Numbers.end ()) current = Numbers.begin ();/* Because the list itself is not a circular list, it is necessary to change the iterator to point to the first element whenever it reaches the next position of the last element */}next = ++current;if (next = = Numbers.end ()) Next = Numbers.begin ();--current;cout<<*current<< ""; numbers.erase (current); current = Next;} Cout<<*current<<endl;}

Can get the same results as the above two codes.


The above-written solution to the Joseph Ring program simulates the entire counting process, the program execution time can be accepted, very quickly can be calculated results. However, when the total number of participants n and the value m is very large, the operation speed slows down. For example, when the value of n is millions, and M is tens of thousands of, it is necessary to loop tens of thousands of times (number of M) in order to determine the number of the next dequeue in 2, even though there are only 2 people left. Obviously, in the execution of this program, a lot of steps are repeated useless loops. So, can you design a more efficient program?
In Joseph's ring, it is not necessary to simulate the whole process of the count, assuming that only the final number of the last row is required. Therefore, in order to pursue the efficiency, can consider from the mathematical angle of reckoning, find out the law and then the code can be.
In order to discuss the convenience, first of all, according to the original intention to describe the problem in mathematical language.
Problem: will be numbered 1~n this n individual round arrangement, according to the clockwise from 1 starts to count, report M's person exits the circular queue, the remainder continues to count off from 1, unceasingly repeatedly. The number of the last dequeue in the circular queue was obtained.
The following first lists the original numbers of the 0~n this n individuals such as the following:
1, 2, 3 、......、 m-2, M-1, M, m+1, m+2 、......、 n-2, n-1, n
The number of the first dequeue must be m%n. For example, in 41 people, if the person reporting 3 is out of the list, then the first out of the number must be a 3%41=3,1 person after the listing such as the following:
1, 2, 3 、......、 m-2, m-1, m+1, m+2 、......、 n-2, n-1, n
According to the rules, when someone is out of the box, the next person from 1 starts to count off, then the above list can be adjusted to the following form (that is, start with the m+1 position, n followed by 0, 1, 2 ..., forming a ring):
M+1, m+2 、......、 n-2, N-1, N, 1, 2, 3 、......、 m-2, m-1
The following relationships can be obtained by numbering again in the order listed above:
1, 2, 3, ..., n-2, n-1
M+1, m+2, m+3 、......、 m-2, m-1
That is, the data after 1 people are organized into a list of 1~n-1, and continue to seek n–1 participants, according to the number of off to M is out of the box, the last one to solve the first in the circular queue.
The scale of the problem is reduced by a single process. That is, for the problem of N personal count off, can be decomposed into the first to solve (n–1) personal count of sub-problem, and for (n–1) personal count of sub-problem, but also can be decomposed to [(n–1) –1] The sub-issue of the person, ...
What is the hour of scale in the problem? Just 1 people (n=1), the person who counted to m out of the way, when the final out of who? Of course there is only one person numbered 1. Therefore, the following functions can be provided:
F (1) = 1
Then, when n=2, Count to M of the people out of the final out of the person who? There should be only one person to get the last number of the final out of the sequence plus m+1 (because there are already 1 people out of the queue, F (n) because there are already n-1 individuals out of the queue, so need to add n-1), the formula can be expressed in the following form:
F (2) = f (1) + M + 1
When calculated from the above calculation, the result of F (2) may exceed the N value (the total number of people). For example, set n=2,m=3 (that is, 2 people, off to 3 o'clock on the dequeue), the calculated value is as follows:
F (2) = f (1) + 3 + 1 = 1 + 3 + 1 = 5
A total of just 2 people participated, and the person numbered 5 was obviously not. What to do? Because it is a ring count, so when two people reported after the number, and from the number of 1 people began to count. Based on this principle, the calculated value can be modeled with the total number of n, followed by 1, since it is not counted from 0, i.e.:
F (2) = [F (1) + M + 1]% n + 1 = [1 + 3 + 1]%2 + 1 = 2
That is, n=2,m=3 (that is, 2 people, out of a 3 of the people out of the box), the last person to cycle off the number of people is 2 (numbering starts from 1).
Based on the above derivation process, it is very easy to derive the formula when n=3:
F (3) = [F (2) + M + 2]%3 + 1
In the same vein, it is also possible to derive the formula for the last number of people in the number of participants N:
F (n) = [F (n-1) + M + n-1]%n + 1
In fact, this is a recursive formula that includes the following two equations:
F (1) = 1; n=1
F (n) = [F (n-1) + M + n-1]%n + 1; n>1
With this recursive formula, it is easy to design the program again.

Use recursive code such as the following (Joseph4.cpp):

#include <stdio.h> #include <stdlib.h>int joseph (int n, int m), int main () {int n,m;printf ("Please input N:"); scanf ("%d", &n);p rintf ("Please input M:"), scanf ("%d", &m);p rintf ("The Last number is:%d\n", Joseph (N,m)); return 0;} int Joseph (int n, int m) {if (n = = 1) return 1;elsereturn (Joseph (N-1,m) +m+n-1)%n + 1;}
Several sets of test results for example are as follows:


Using recursive functions consumes more memory from your computer and can cause programs to not run when the recursion level is too deep, so you can write the program directly to the following iteration form.
Joseph5.cpp:

#include <stdio.h> #include <stdlib.h>int joseph (int n, int m), int main () {int n,m;printf ("Please input N:"); scanf ("%d", &n);p rintf ("Please input M:"), scanf ("%d", &m);p rintf ("The Last number is:%d\n", Joseph (N,m)); return 0;} int Joseph (int n, int m) {int last = 1;//equivalent to f (1) int i;for (i=2; i<=n; i++)//Step by step F (2) to F (n) last = (last + M + i-1)%i + 1 ; return last;}
can also get the same results as above.


Joseph Ring Question

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.