He Haitao's Netease blog is responsible for the selection of blog topics for the programmer interview. This blog only records its own implementations for learning.
Portal: programmer interview questions featured 100 questions (14)-the last number left in the circle [algorithm]
Question: N numbers (0, 1 ,..., N-1) to form a circle, starting from the number 0, each time from this circle to delete the M number (the first is the current number itself, the second is the next number of the current number ). After a number is deleted, the M number is deleted from the next one. Find the remaining number in the circle.
Analysis: this is the famous Joseph ring question. Since the subject has a digital circle, it is natural that we use a Data Structure to simulate this circle. In common data structures, we can easily use a Circular List. We can create a ring list with a total of M numbers, and then delete the MTH element from this list each time.
In reference code, we use STD: List in STL to simulate this Circular List. Because the list is not a circular structure, remember to move the drop agent to the header of the list every time the drop agent scans the end of the list. In this way, the list is traversed in the order of a circle.
Personal implementation:
# Include <iostream> # include <list> using namespace STD; # define M 2
// Delete the MTH element cyclically until only the following element is left: void removemthnumber (list <int> & cancelist) {list <int>: iterator first = cancelist. begin (); While (cyclelist. size ()> 1) {list <int >:: iterator iter = first; List <int >:: iterator todeleteiter; // manually implement the cyclic list for (int count = 1; count <m; ++ count) {If (++ iter = cancelist. end () iter = cancelist. begin ();} todeleteiter = ITER; // determine the start position of the next count if (++ iter = cyclelist. end () First = cancelist. begin (); else first = ITER; cyclelist. erase (todeleteiter );}}
TIPS:
In the list implementation, it is depressing that the List iterator does not support ITER + N operations. In this way, the operator iterator needs to be auto-reduced after auto-increment, which increases the judgment complexity and is inconvenient.
In addition, you can also use a custom circular linked list to implement this function without calling the standard library.
Finally, paste the original code:
View code
///////////////////////////////////////////////////////////////////////// n integers (0, 1, ... n - 1) form a circle. Remove the mth from // the circle at every time. Find the last number remaining // Input: n - the number of integers in the circle initially// m - remove the mth number at every time// Output: the last number remaining when the input is valid,// otherwise -1///////////////////////////////////////////////////////////////////////int LastRemaining_Solution1(unsigned int n, unsigned int m){ // invalid input if(n < 1 || m < 1) return -1; unsigned int i = 0; // initiate a list with n integers (0, 1, ... n - 1) list<int> integers; for(i = 0; i < n; ++ i) integers.push_back(i); list<int>::iterator curinteger = integers.begin(); while(integers.size() > 1) { // find the mth integer. Note that std::list is not a circle // so we should handle it manually for(int i = 1; i < m; ++ i) { curinteger ++; if(curinteger == integers.end()) curinteger = integers.begin(); } // remove the mth integer. Note that std::list is not a circle // so we should handle it manually list<int>::iterator nextinteger = ++ curinteger; if(nextinteger == integers.end()) nextinteger = integers.begin(); -- curinteger; integers.erase(curinteger); curinteger = nextinteger; } return *(curinteger);}