A general solution to the n-digit Sorting Problem

Source: Internet
Author: User
This article requires readers to understand the following syntax knowledge: yield return, generics, lambda, and extension methodsI saw this post two days ago: the two interview questions I saw were very representative of the second question, so I did it with my heart. Algorithm question: how many different three-digit numbers can be combined in different order for any three-digit number (different digits? What are the differences? (C #) Example: 123: 123,132,213,231,312,321. The idea at the beginning was to write three cycles to gather the answers. But what if n digits are used to write n loops? So I immediately thought of using recursion to solve the problem. Each time a number is obtained, the first number is obtained from the remaining number, and so on until the last number is obtained. But there is a small problem: for 1, there are two results: 123 and 132, this requires the use of list to save the results, but this is not elegant enough, so I chose the favorite yield return to simplify the code. The most important thing for recursive Programs is to find the endpoint. At the beginning, I tried several termination conditions and they failed, finally, I calmed down and figured out that the sorting process is to enumerate all N numbers, so the ending condition is the number of digits. The last problem is saved. There cannot be duplicates in the arrangement. You just need to simulate the sorting process and understand it: Start:Select the leftmost number 1, and the string subscript is 0. Currently, 1 is enumerated. First recursion:Traverse from the beginning. Because the number with the subscript 0 has been obtained in the previous round, use the number with the subscript 1 to determine whether the subscript 1 has been used because it is not used, continue recursion. Currently, 2 counts are enumerated. The second recursion:Because the number of currently enumerated items is 3rd, the end point is reached. 3 is returned. During this sorting process, we need to record the subscript of the selected number each time, next time, you need to determine whether the number already exists. Therefore, I use an array of the same size as the number of digits to record the subscript of the number selected in each sorting process.

Okay, it doesn't matter if you haven't understood the above. Code is the best document. But before you paste the specific code, I will introduce two of my auxiliary functions:

// Apply an operation to each retrieved element. Public static void for <t> (this ienumerable <t> itor, Action <t> proc) {foreach (T item in itor) proc (item) ;}// determines whether an element is in an array public static bool exist <t> (this t [] arr, func <t, bool> predicate) {for (INT I = 0; I <arr. length; ++ I) {If (predicate (ARR [I]) return true;} return false;} // OK, the core code comes: public static ienumerable <string> combin (string source) {int [] Trace = new int [source. length]; for (INT I = 0; I <source. length; ++ I) {foreach (string item in combin (source, I, 1, trace) {yield return item ;}}} /// <summary> /// recursive Sorting Algorithm /// </Summary> /// <Param name = "Source"> Number </param> /// <Param name = "cur"> current subscript </param> /// <Param name = "deep"> current enumeration count </param> /// <Param name = "trace"> tracking, used for deduplication </param> /// <returns> return the sorted number </returns> Private Static ienumerable <string> combin (string source, int cur, int deep, int [] Trace) {char TMP = source [cur]; // obtain the currently enumerated number trace [Deep-1] = cur; // put the current subscript into the trace if (deep = source. length) // The final condition yield return TMP. tostring (); else {for (INT I = 0; I <source. length; ++ I) // enumerative {for (Int J = deep; j <trace. length; ++ J) // trace cleared trace [J] =-1; //-1 indicates if (cur = I | trace. exist (P => // repeated filtering {If (P =-1) return false; return P = I;}) continue; foreach (string tail in combin (source, I, deep + 1, trace) {yield return TMP + tail ;}}// check the effect. Public static void main () {combin ("1234 "). for (I => console. writeline (I ));}

It's not bad, but now we can only process strings. If the input is like this, "Zhi Cheng Dao, Hebei district, Tianjin, China", what should I do? Or if the input is not a string but a group of objects? Well, it's time to go to the generic model. I don't know if you have found that there is no such thing as processing the number sorting problem. In fact, it can be generalized to handling the Sorting Problem of an array. "1234" is actually a char array, therefore, it can be replaced with any other type. careful readers do you feel the advantage of repeating With Trace. well, I don't need to allow custom INHERITANCE OF THE icomparer <t> interface, and this efficiency is also very high. however, because it is generic, I cannot determine whether to return a string because it can return a string for char []. Other types are hard to say, therefore, I just want to make the User-Defined return type more flexible. For example, I can return results like "1-3-2-4. now let's take a look at the generic version combination algorithm:

// This class is only used to facilitate the creation of a combination <t> instance's public class combination {public static combination <t> New <t> (T [] source) {return new combination <t> (source) ;}} public class combination <t> {T [] _ source; Public combination (T [] source) {This. _ source = source;} public ienumerable <r> combin <r> (func <t, R, R> Format) {var trace = new int [this. _ source. length]; for (VAR I = 0; I <this. _ source. length; ++ I) {foreach (VAR item in combin (I, 1, Trace, format) {yield return item ;}}} /// <summary> /// core recursive algorithm of sorting /// </Summary> /// <typeparam name = "R"> return type </typeparam> // /<Param name = "Source"> data source to be sorted </param> // <Param name = "cur"> current selected location </param> // <Param name = "deep"> current recursive depth </param> // <Param name = "trace"> trace, used for deduplication </param> /// <Param name = "format"> output format </param> /// <returns> formatted return type </returns> private ienumerable <r> combin <r> (INT cur, int deep, int [] Trace, func <t, R, R> Format) {var TMP = This. _ source [cur]; // obtain the trace [Deep-1] = cur; // record trace if (deep = This. _ source. length) // determine whether the recursion ends. Yield return format (TMP, default (R); // return the formatted result else {for (VAR I = 0; I <this. _ source. length; ++ I) {for (VAR J = deep; j <trace. length; ++ J) // initialize trace [J] =-1; if (cur = I | trace. exist (P => {// deduplication if (P =-1) return false; return P = I;}) continue; // recursively execute foreach (VAR tail in combin (I, deep + 1, Trace, format) {yield return format (TMP, tail ); // merge the result and output the result. The result is perfect. For example, public static void main9 () {// multiple combinations of keywords during query string STR = "Zhi Cheng Dao, Hebei district, Tianjin, China"; combination. new (Str. split ('')). combin <string> (P, R) => P + "-" + r ). for (I => console. writeline (I. trimend ('-'); // n-digit sorting string num = "1234"; combination. new (Num. tochararray ()). combin <string> (P, R) => P + r ). for (I => console. writeline (I ));}
 
This method I wrote may cause losses (because yield return is used). However, I think its versatility is the key. I hope some enthusiastic netizens can help me optimize the code. Thank you for watching it!

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.