在给定字符串的排列的排序列表中查找给定排列的索引

发布于 2024-10-19 07:29:59 字数 122 浏览 4 评论 0原文

我们得到一个字符串和该字符串的排列。

例如,输入字符串 sandeep 和排列 psdenae

查找给定排列在原始字符串排列的排序列表中的位置。

We're given a string and a permutation of the string.

For example, an input string sandeep and a permutation psdenae.

Find the position of the given permutation in the sorted list of the permutations of the original string.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

肥爪爪 2024-10-26 07:29:59

给定长度为 n 的字符串的排列总数将为 n! (如果所有字符都不同),因此不可能探索所有组合。

这道题其实就像数学P& C 题

求单词“stack”按字典顺序排列时的排名。

给定输入字符串 NILSU
取一个单词,我们要找到它的排名。以“SUNIL”为例。

现在按字母顺序排列“SUNIL”的字母。

一定会的。 “ILNS U”。

现在取出第一个字母。是“我”。现在检查一下,是字母“I”吗?
“SUNIL”的第一个字母?序号 可以组成的单词数
从 I will be 4! 开始,所以我们知道会有 4!字
在“SUNIL”之前。

我=4! = 24

现在看第二个字母。它的“L”。现在再次检查是否是这样
我们想要在第一个位置的字母?不会。所以字数可以是
以“L”开头的组成将是4!。

L = 4! = 24

现在选择“N”。这是我们想要的吗?否。写下字数
可以组成以“N”开头的,又是4!

N = 4! = 24

现在选择“S”。这是我们想要的吗?是的。现在删除这封信
按字母顺序排列的单词。现在将是“ILN U”

写下 S 并在列表中再次检查该单词。我们想要 SI 吗?不。
所以以SI开头可以组成的单词数是3!

[S]:I-> 3! =6

选择 L。我们想要 SL 吗?不,所以是 3!。

[S]:L-> 3! =6

选择N。我们想要SN吗?没有。

[S]:N-> 3! =6

去苏。这是我们想要的吗?是的。从列表中删除字母 U 并
那么它将是“IL N”。现在尝试一下,我们想要 SUI 吗?不,所以这个数字
从SUI开始可以组成的单词数为2!

[SU]:我-> 2! = 2 现在选择 L。我们想要“SUL”吗?没有,所以数量
以 SUL 开头的单词将为 2!。

[SU]:L-> 2! = 2

现在选择 N。我们想要 SUN 吗?是的,现在删除该字母。还有这个
将是“I L”。我们想要“SUNI”吗?是的。删除那封信。唯一的
左边的字母是“L”。

现在去找 L。我们要 SUNIL 吗?是的。 SUNIL 是第一个选择,所以
我们有 1! [太阳][I][L] = 1! = 1

现在将我们得到的整数相加。总和将为。

24 + 24 + 24 + 6 + 6 + 6 + 2 + 2 + 1 = 95。

因此,如果我们计算使用 SUNIL 字母按字典顺序排列可以创建的单词,则 SUNIL 一词将位于第 95 位。

因此通过这个方法你可以很轻松的解决这个问题。

The total number of permutation of a given string of length n would be n! (if all characters are different), thus it would not be possible to explore all the combinations.

This question is actually like the mathematics P & C question

Find the rank of the word "stack" when arranged in dictionary order.

Given the input string as NILSU
Take a word which we have to find the rank. Take "SUNIL" for example.

Now arrange the letter of "SUNIL" in alphabetical order.

It will be. "I L N S U".

Now take the first letter. Its "I". Now check, is the letter "I" the
first letter of "SUNIL"? No. The number of words that can be formed
starting with I will be 4!, so we know that there will be 4! words
before "SUNIL".

I = 4! = 24

Now go for the second letter. Its "L". Now check once again if this
letter we want in first position? No. So the number of words can be
formed starting with "L" will be 4!.

L = 4! = 24

Now go for "N". Is this we want? No. Write down the number of words
can be formed starting with "N", once again 4!

N = 4! = 24

Now go for "S". Is this what we want? Yes. Now remove the letter from
the alphabetically ordered word. It will now be "I L N U"

Write S and check the word once again in the list. Is we want SI? No.
So the number of words can be formed starting with SI will be 3!

[S]:I-> 3! = 6

Go for L. is we want SL? No. So it will be 3!.

[S]:L-> 3! = 6

Go for N. is we want SN? No.

[S]:N-> 3! = 6

Go for SU. Is this we want? Yes. Cut the letter U from the list and
then it will be "I L N". Now try I. is we want SUI? No. So the number
of words can be formed which starts from SUI will be 2!

[SU]:I-> 2! = 2 Now go for L. Do we want "SUL". No. so the number of
words starting with SUL will be 2!.

[SU]:L-> 2! = 2

Now go for N. Is we want SUN? Yes, now remove that letter. and this
will be "I L". Do we want "SUNI"? Yes. Remove that letter. The only
letter left is "L".

Now go for L. Do we want SUNIL? Yes. SUNIL were the first options, so
we have 1!. [SUN][I][L] = 1! = 1

Now add the whole numbers we get. The sum will be.

24 + 24 + 24 + 6 + 6 + 6 + 2 + 2 + 1 = 95.

So the word SUNIL will be at 95th position if we count the words that can be created using the letters of SUNIL arranged in dictionary order.

Thus through this method you could solve this problem quite easily.

可爱暴击 2024-10-26 07:29:59

构建@Algorithmist的答案以及他对答案的评论,并使用这篇文章中讨论的原则是重复的字母,我在 JavaScript 中编写了以下算法,该算法适用于所有基于字母的单词,即使有重复的字母实例也是如此。

function anagramPosition(string) {
  var index = 1;
  var remainingLetters = string.length - 1;
  var frequencies = {};
  var splitString = string.split("");
  var sortedStringLetters = string.split("").sort();

  sortedStringLetters.forEach(function(val, i) {
    if (!frequencies[val]) {
      frequencies[val] = 1;
    } else {
      frequencies[val]++;
    }
  })

  function factorial(coefficient) {
    var temp = coefficient;
    var permutations = coefficient;
    while (temp-- > 2) {
      permutations *= temp;
    }
    return permutations;
  }

  function getSubPermutations(object, currentLetter) {
    object[currentLetter]--;
    var denominator = 1;
    for (var key in object) {
      var subPermutations = factorial(object[key]);
      subPermutations !== 0 ? denominator *= subPermutations : null;
    }
    object[currentLetter]++;
    return denominator;
  }

  var splitStringIndex = 0;
  while (sortedStringLetters.length) {
    for (var i = 0; i < sortedStringLetters.length; i++) {
      if (sortedStringLetters[i] !== splitString[splitStringIndex]) {
        if (sortedStringLetters[i] !== sortedStringLetters[i+1]) {
          var permutations = factorial(remainingLetters);
          index += permutations / getSubPermutations(frequencies, sortedStringLetters[i]);
        } else {
          continue;
        }
      } else {
        splitStringIndex++;
        frequencies[sortedStringLetters[i]]--;
        sortedStringLetters.splice(i, 1);
        remainingLetters--;
        break;
      }
    }
  }
  return index;
}

anagramPosition("ARCTIC") // => 42

我没有评论代码,但我确实尝试使变量名称尽可能具有解释性。如果您使用开发工具控制台通过调试器进程运行它,并放入一些 console.logs,您应该能够看到它如何使用上面链接的 SO 帖子中的公式。

Building off @Algorithmist 's answer, and his comment to his answer, and using the principle discussed in this post for when there are repeated letters, I made the following algorithm in JavaScript that works for all letter-based words even with repeated letter instances.

function anagramPosition(string) {
  var index = 1;
  var remainingLetters = string.length - 1;
  var frequencies = {};
  var splitString = string.split("");
  var sortedStringLetters = string.split("").sort();

  sortedStringLetters.forEach(function(val, i) {
    if (!frequencies[val]) {
      frequencies[val] = 1;
    } else {
      frequencies[val]++;
    }
  })

  function factorial(coefficient) {
    var temp = coefficient;
    var permutations = coefficient;
    while (temp-- > 2) {
      permutations *= temp;
    }
    return permutations;
  }

  function getSubPermutations(object, currentLetter) {
    object[currentLetter]--;
    var denominator = 1;
    for (var key in object) {
      var subPermutations = factorial(object[key]);
      subPermutations !== 0 ? denominator *= subPermutations : null;
    }
    object[currentLetter]++;
    return denominator;
  }

  var splitStringIndex = 0;
  while (sortedStringLetters.length) {
    for (var i = 0; i < sortedStringLetters.length; i++) {
      if (sortedStringLetters[i] !== splitString[splitStringIndex]) {
        if (sortedStringLetters[i] !== sortedStringLetters[i+1]) {
          var permutations = factorial(remainingLetters);
          index += permutations / getSubPermutations(frequencies, sortedStringLetters[i]);
        } else {
          continue;
        }
      } else {
        splitStringIndex++;
        frequencies[sortedStringLetters[i]]--;
        sortedStringLetters.splice(i, 1);
        remainingLetters--;
        break;
      }
    }
  }
  return index;
}

anagramPosition("ARCTIC") // => 42

I didn't comment the code but I did try to make the variable names as explanatory as possible. If you run it through a debugger process using your dev tools console and throw in a few console.logs you should be able to see how it uses the formula in the above-linked S.O. post.

山川志 2024-10-26 07:29:59

我尝试用js实现这个。它适用于没有重复字母的字符串,但否则我会得到错误的计数。这是我的代码:

function x(str) {
var sOrdinata = str.split('').sort()
console.log('sOrdinata = '+ sOrdinata)
var str = str.split('')
console.log('str = '+str)
console.log('\n')
var pos = 1;

for(var j in str){
//console.log(j)

for(var i in sOrdinata){
if(sOrdinata[i]==str[j]){
  console.log('found, position: '+ i)
  sOrdinata.splice(i,1)
  console.log('Nuovo sOrdinata = '+sOrdinata)
  console.log('\n')
  break;
}
else{
  //calculate number of permutations
  console.log('valore di j: '+j)

  //console.log('lunghezza stringa da permutare: '+str.slice(~~j+1).length);
  if(str.slice(j).length >1 ){sub = str.slice(~~j+1)}else {sub = str.slice(j)}
  console.log('substring to be used for permutation: '+ sub)

  prep = nrepC(sub.join(''))
  console.log('prep = '+prep)

  num = factorial(sub.length)
  console.log('num = '+num)

  den = denom(prep)
  console.log('den = '+ den)

  pos += num/den
  console.log(num/den)
  console.log('\n')
 }
 }
}
console.log(pos)
return pos
}



/* ------------ functions used by main --------------- */ 

function nrepC(str){
var obj={}
var repeats=[]
var res= [];

for(x = 0, length = str.length; x < length; x++) {
var l = str.charAt(x)
obj[l] = (isNaN(obj[l]) ? 1 : obj[l] + 1);
}
//console.log(obj)

for (var i in obj){
if(obj[i]>1) res.push(obj[i])
}
if(res.length==0){res.push(1); return res}
else return res
}

function num(vect){
var res =  1

}


function denom(vect){
var res = 1
for(var i in vect){
res*= factorial(vect[i])
}
return res
}


function factorial (n){
if (n==0 || n==1){
return 1;
}
return factorial(n-1)*n;
}  

I tried to implement this in js. It works for string that have no repeated letters but I get a wrong count otherwise. Here is my code:

function x(str) {
var sOrdinata = str.split('').sort()
console.log('sOrdinata = '+ sOrdinata)
var str = str.split('')
console.log('str = '+str)
console.log('\n')
var pos = 1;

for(var j in str){
//console.log(j)

for(var i in sOrdinata){
if(sOrdinata[i]==str[j]){
  console.log('found, position: '+ i)
  sOrdinata.splice(i,1)
  console.log('Nuovo sOrdinata = '+sOrdinata)
  console.log('\n')
  break;
}
else{
  //calculate number of permutations
  console.log('valore di j: '+j)

  //console.log('lunghezza stringa da permutare: '+str.slice(~~j+1).length);
  if(str.slice(j).length >1 ){sub = str.slice(~~j+1)}else {sub = str.slice(j)}
  console.log('substring to be used for permutation: '+ sub)

  prep = nrepC(sub.join(''))
  console.log('prep = '+prep)

  num = factorial(sub.length)
  console.log('num = '+num)

  den = denom(prep)
  console.log('den = '+ den)

  pos += num/den
  console.log(num/den)
  console.log('\n')
 }
 }
}
console.log(pos)
return pos
}



/* ------------ functions used by main --------------- */ 

function nrepC(str){
var obj={}
var repeats=[]
var res= [];

for(x = 0, length = str.length; x < length; x++) {
var l = str.charAt(x)
obj[l] = (isNaN(obj[l]) ? 1 : obj[l] + 1);
}
//console.log(obj)

for (var i in obj){
if(obj[i]>1) res.push(obj[i])
}
if(res.length==0){res.push(1); return res}
else return res
}

function num(vect){
var res =  1

}


function denom(vect){
var res = 1
for(var i in vect){
res*= factorial(vect[i])
}
return res
}


function factorial (n){
if (n==0 || n==1){
return 1;
}
return factorial(n-1)*n;
}  
走走停停 2024-10-26 07:29:59

有点晚了,但仅供参考...您可以直接使用此 C# 代码。

它会起作用,但是......

唯一重要的是,通常,您应该以独特的值作为起始集。否则你就没有n!排列。你还有别的东西(少于n!)。当项目可能是重复的时,我有点怀疑是否有任何有用的用途。

using System;
using System.Collections.Generic;

namespace WpfPermutations
{
    public class PermutationOuelletLexico3<T>
    {
        // ************************************************************************
        private T[] _sortedValues;

        private bool[] _valueUsed;

        public readonly long MaxIndex; // long to support 20! or less 

        // ************************************************************************
        public PermutationOuelletLexico3(T[] sortedValues)
        {
            if (sortedValues.Length <= 0)
            {
                throw new ArgumentException("sortedValues.Lenght should be greater than 0");
            }

            _sortedValues = sortedValues;
            Result = new T[_sortedValues.Length];
            _valueUsed = new bool[_sortedValues.Length];

            MaxIndex = Factorial.GetFactorial(_sortedValues.Length);
        }

        // ************************************************************************
        public T[] Result { get; private set; }

        // ************************************************************************
        /// <summary>
        /// Return the permutation relative to the index received, according to 
        /// _sortedValues.
        /// Sort Index is 0 based and should be less than MaxIndex. Otherwise you get an exception.
        /// </summary>
        /// <param name="sortIndex"></param>
        /// <returns>The result is written in property: Result</returns>
        public void GetValuesForIndex(long sortIndex)
        {
            int size = _sortedValues.Length;

            if (sortIndex < 0)
            {
                throw new ArgumentException("sortIndex should be greater or equal to 0.");
            }

            if (sortIndex >= MaxIndex)
            {
                throw new ArgumentException("sortIndex should be less than factorial(the lenght of items)");
            }

            for (int n = 0; n < _valueUsed.Length; n++)
            {
                _valueUsed[n] = false;
            }

            long factorielLower = MaxIndex;

            for (int index = 0; index < size; index++)
            {
                long factorielBigger = factorielLower;
                factorielLower = Factorial.GetFactorial(size - index - 1);  //  factorielBigger / inverseIndex;

                int resultItemIndex = (int)(sortIndex % factorielBigger / factorielLower);

                int correctedResultItemIndex = 0;
                for(;;)
                {
                    if (! _valueUsed[correctedResultItemIndex])
                    {
                        resultItemIndex--;
                        if (resultItemIndex < 0)
                        {
                            break;
                        }
                    }
                    correctedResultItemIndex++;
                }

                Result[index] = _sortedValues[correctedResultItemIndex];
                _valueUsed[correctedResultItemIndex] = true;
            }
        }

        // ************************************************************************
        /// <summary>
        /// Calc the index, relative to _sortedValues, of the permutation received
        /// as argument. Returned index is 0 based.
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        public long GetIndexOfValues(T[] values)
        {
            int size = _sortedValues.Length;
            long valuesIndex = 0;

            List<T> valuesLeft = new List<T>(_sortedValues);

            for (int index = 0; index < size; index++)
            {
                long indexFactorial = Factorial.GetFactorial(size - 1 - index);

                T value = values[index];
                int indexCorrected = valuesLeft.IndexOf(value);
                valuesIndex = valuesIndex + (indexCorrected * indexFactorial);
                valuesLeft.Remove(value);
            }
            return valuesIndex;
        }

        // ************************************************************************
    }
}

A bit too late but just as reference... You can use this C# code directly.

It will work but...

The only important thing is that usually, you should have unique values as your starting set. Otherwise you don't have n! permutations. You have something else (less than n!). I have a little doubt of any useful usage when item could be duplicate ones.

using System;
using System.Collections.Generic;

namespace WpfPermutations
{
    public class PermutationOuelletLexico3<T>
    {
        // ************************************************************************
        private T[] _sortedValues;

        private bool[] _valueUsed;

        public readonly long MaxIndex; // long to support 20! or less 

        // ************************************************************************
        public PermutationOuelletLexico3(T[] sortedValues)
        {
            if (sortedValues.Length <= 0)
            {
                throw new ArgumentException("sortedValues.Lenght should be greater than 0");
            }

            _sortedValues = sortedValues;
            Result = new T[_sortedValues.Length];
            _valueUsed = new bool[_sortedValues.Length];

            MaxIndex = Factorial.GetFactorial(_sortedValues.Length);
        }

        // ************************************************************************
        public T[] Result { get; private set; }

        // ************************************************************************
        /// <summary>
        /// Return the permutation relative to the index received, according to 
        /// _sortedValues.
        /// Sort Index is 0 based and should be less than MaxIndex. Otherwise you get an exception.
        /// </summary>
        /// <param name="sortIndex"></param>
        /// <returns>The result is written in property: Result</returns>
        public void GetValuesForIndex(long sortIndex)
        {
            int size = _sortedValues.Length;

            if (sortIndex < 0)
            {
                throw new ArgumentException("sortIndex should be greater or equal to 0.");
            }

            if (sortIndex >= MaxIndex)
            {
                throw new ArgumentException("sortIndex should be less than factorial(the lenght of items)");
            }

            for (int n = 0; n < _valueUsed.Length; n++)
            {
                _valueUsed[n] = false;
            }

            long factorielLower = MaxIndex;

            for (int index = 0; index < size; index++)
            {
                long factorielBigger = factorielLower;
                factorielLower = Factorial.GetFactorial(size - index - 1);  //  factorielBigger / inverseIndex;

                int resultItemIndex = (int)(sortIndex % factorielBigger / factorielLower);

                int correctedResultItemIndex = 0;
                for(;;)
                {
                    if (! _valueUsed[correctedResultItemIndex])
                    {
                        resultItemIndex--;
                        if (resultItemIndex < 0)
                        {
                            break;
                        }
                    }
                    correctedResultItemIndex++;
                }

                Result[index] = _sortedValues[correctedResultItemIndex];
                _valueUsed[correctedResultItemIndex] = true;
            }
        }

        // ************************************************************************
        /// <summary>
        /// Calc the index, relative to _sortedValues, of the permutation received
        /// as argument. Returned index is 0 based.
        /// </summary>
        /// <param name="values"></param>
        /// <returns></returns>
        public long GetIndexOfValues(T[] values)
        {
            int size = _sortedValues.Length;
            long valuesIndex = 0;

            List<T> valuesLeft = new List<T>(_sortedValues);

            for (int index = 0; index < size; index++)
            {
                long indexFactorial = Factorial.GetFactorial(size - 1 - index);

                T value = values[index];
                int indexCorrected = valuesLeft.IndexOf(value);
                valuesIndex = valuesIndex + (indexCorrected * indexFactorial);
                valuesLeft.Remove(value);
            }
            return valuesIndex;
        }

        // ************************************************************************
    }
}
往昔成烟 2024-10-26 07:29:59

我解决这个问题的方法是对给定的排列进行排序。
字符串中字符的交换次数将为我们提供排列在排列排序列表中的位置。

My approach to the problem is sort the given permutation.
Number of swappings of the characters in the string will give us the position of the pemutation in the sorted list of permutations.

我很坚强 2024-10-26 07:29:59

一个低效的解决方案是连续查找先前的排列,直到到达无法再排列的字符串。达到此状态所需的排列数就是原始字符串的位置。

但是,如果您使用组合数学,您可以更快地获得解决方案。如果字符串长度超过 12,前面的解决方案将产生非常慢的输出。

An inefficient solution would be to successively find the previous permutations until you reach a string that cannot be permuted anymore. The number of permutations it takes to reach this state is the position of the original string.

However, if you use combinatorics you can achieve the solution faster. The previous solution will produce a very slow output if string length exceeds 12.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文