Listing all permutations of a string/integer

后端 未结 29 1987
没有蜡笔的小新
没有蜡笔的小新 2020-11-22 00:44

A common task in programming interviews (not from my experience of interviews though) is to take a string or an integer and list every possible permutation.

Is there

相关标签:
29条回答
  • 2020-11-22 01:19

    Here is one more implementation of the algo mentioned.

    public class Program
    {
        public static void Main(string[] args)
        {
            string str = "abcefgh";
            var astr = new Permutation().GenerateFor(str);
            Console.WriteLine(astr.Length);
            foreach(var a in astr)
            {
                Console.WriteLine(a);
            }
            //a.ForEach(Console.WriteLine);
        }
    }
    
    class Permutation
    {
        public string[] GenerateFor(string s)
        {  
    
            if(s.Length == 1)
            {
    
                return new []{s}; 
            }
    
            else if(s.Length == 2)
            {
    
                return new []{s[1].ToString()+s[0].ToString(),s[0].ToString()+s[1].ToString()};
    
            }
    
            var comb = new List<string>();
    
            foreach(var c in s)
            {
    
                string cStr = c.ToString();
    
                var sToProcess = s.Replace(cStr,"");
                if (!string.IsNullOrEmpty(sToProcess) && sToProcess.Length>0)
                {
                    var conCatStr = GenerateFor(sToProcess);
    
    
    
                    foreach(var a in conCatStr)
                    {
                        comb.Add(c.ToString()+a);
                    }
    
    
                }
            }
            return comb.ToArray();
    
        }
    }
    
    0 讨论(0)
  • 2020-11-22 01:21

    First of all, sets have permutations, not strings or integers, so I'll just assume you mean "the set of characters in a string."

    Note that a set of size n has n! n-permutations.

    The following pseudocode (from Wikipedia), called with k = 1...n! will give all the permutations:

    function permutation(k, s) {
        for j = 2 to length(s) {
            swap s[(k mod j) + 1] with s[j]; // note that our array is indexed starting at 1
            k := k / j; // integer division cuts off the remainder
        }
        return s;
    }
    

    Here's the equivalent Python code (for 0-based array indexes):

    def permutation(k, s):
        r = s[:]
        for j in range(2, len(s)+1):
            r[j-1], r[k%j] = r[k%j], r[j-1]
            k = k/j+1
        return r
    
    0 讨论(0)
  • 2020-11-22 01:21

    Here's a purely functional F# implementation:

    
    let factorial i =
        let rec fact n x =
            match n with
            | 0 -> 1
            | 1 -> x
            | _ -> fact (n-1) (x*n)
        fact i 1
    
    let swap (arr:'a array) i j = [| for k in 0..(arr.Length-1) -> if k = i then arr.[j] elif k = j then arr.[i] else arr.[k] |]
    
    let rec permutation (k:int,j:int) (r:'a array) =
        if j = (r.Length + 1) then r
        else permutation (k/j+1, j+1) (swap r (j-1) (k%j))
    
    let permutations (source:'a array) = seq { for k = 0 to (source |> Array.length |> factorial) - 1 do yield permutation (k,2) source }
    

    Performance can be greatly improved by changing swap to take advantage of the mutable nature of CLR arrays, but this implementation is thread safe with regards to the source array and that may be desirable in some contexts. Also, for arrays with more than 16 elements int must be replaced with types with greater/arbitrary precision as factorial 17 results in an int32 overflow.

    0 讨论(0)
  • 2020-11-22 01:25

    Here's my solution in JavaScript (NodeJS). The main idea is that we take one element at a time, "remove it" from the string, vary the rest of the characters, and insert the element at the front.

    function perms (string) {
      if (string.length == 0) {
        return [];
      }
      if (string.length == 1) {
        return [string];
      }
      var list = [];
      for(var i = 0; i < string.length; i++) {
        var invariant = string[i];
        var rest = string.substr(0, i) + string.substr(i + 1);
        var newPerms = perms(rest);
        for (var j = 0; j < newPerms.length; j++) {
          list.push(invariant + newPerms[j]);
        }
      }
      return list;
    }
    
    module.exports = perms;
    

    And here are the tests:

    require('should');
    var permutations = require('../src/perms');
    
    describe('permutations', function () {
      it('should permute ""', function () {
        permutations('').should.eql([]);
      })
    
      it('should permute "1"', function () {
        permutations('1').should.eql(['1']);
      })
    
      it('should permute "12"', function () {
        permutations('12').should.eql(['12', '21']);
      })
    
      it('should permute "123"', function () {
        var expected = ['123', '132', '321', '213', '231', '312'];
        var actual = permutations('123');
        expected.forEach(function (e) {
          actual.should.containEql(e);
        })
      })
    
      it('should permute "1234"', function () {
        // Wolfram Alpha FTW!
        var expected = ['1234', '1243', '1324', '1342', '1423', '1432', '2134', '2143', '2314', '2341', '2413', '2431', '3124', '3142', '3214', '3241', '3412', '3421', '4123', '4132'];
        var actual = permutations('1234');
        expected.forEach(function (e) {
          actual.should.containEql(e);
        })
      })
    })
    
    0 讨论(0)
  • 2020-11-22 01:25

    Base/Revise on Pengyang answer

    And inspired from permutations-in-javascript

    The c# version FunctionalPermutations should be this

    static IEnumerable<IEnumerable<T>> FunctionalPermutations<T>(IEnumerable<T> elements, int length)
        {
            if (length < 2) return elements.Select(t => new T[] { t });
            /* Pengyang answser..
              return _recur_(list, length - 1).SelectMany(t => list.Where(e => !t.Contains(e)),(t1, t2) => t1.Concat(new T[] { t2 }));
            */
            return elements.SelectMany((element_i, i) => 
              FunctionalPermutations(elements.Take(i).Concat(elements.Skip(i + 1)), length - 1)
                .Select(sub_ei => new[] { element_i }.Concat(sub_ei)));
        }
    
    0 讨论(0)
  • 2020-11-22 01:26

    Here I have found the solution. It was written in Java, but I have converted it to C#. I hope it will help you.

    Enter image description here

    Here's the code in C#:

    static void Main(string[] args)
    {
        string str = "ABC";
        char[] charArry = str.ToCharArray();
        Permute(charArry, 0, 2);
        Console.ReadKey();
    }
    
    static void Permute(char[] arry, int i, int n)
    {
        int j;
        if (i==n)
            Console.WriteLine(arry);
        else
        {
            for(j = i; j <=n; j++)
            {
                Swap(ref arry[i],ref arry[j]);
                Permute(arry,i+1,n);
                Swap(ref arry[i], ref arry[j]); //backtrack
            }
        }
    }
    
    static void Swap(ref char a, ref char b)
    {
        char tmp;
        tmp = a;
        a=b;
        b = tmp;
    }
    
    0 讨论(0)
提交回复
热议问题