📜  Pandigital级联的对数

📅  最后修改于: 2021-04-27 23:15:12             🧑  作者: Mango

如果串联的一对字符串至少由(0-9)的所有数字以任意顺序组成一次,则称它们为“ Pandigital串联”。该任务是给定N个字符串,计算得出的对数。 “ Pandigital级联”。

例子:

Input  : num[] = {"123567", "098234", "14765", "19804"}
Output : 3
The pairs, 1st and 2nd giving 
(123567098234),1st and 4rd giving(12356719804) and 
2nd and 3rd giving (09823414765),
on concatenation result in Pandigital Concatenations. 

Input : num[] =  {"56789", "098345", "1234"}
Output : 0
None of the pairs on concatenation result in Pandigital 
Concatenations.

方法1(蛮力):一种可能的蛮力解决方案是通过在O(n 2)中形成所有对,并使用数字的频率数组(0 – 9)来形成所有可能的级联,我们检查每个数字是否至少存在一次在每对中形成的每个串联中。

C++
// C++ program to find all
// Pandigital concatenations
// of two strings.
#include 
using namespace std;
 
// Checks if a given
// string is Pandigital
bool isPanDigital(string s)
{
    bool digits[10] = {false};
    for (int i = 0; i < s.length(); i++)
        digits[s[i] - '0'] = true;
 
    // digit i is not present
    // thus not pandigital
    for (int i = 0; i <= 9; i++)
        if (digits[i] == false)
            return false;
 
    return true;
}
 
// Returns number of pairs
// of strings resulting in
// Pandigital Concatenations
int countPandigitalPairs(vector &v)
{
    // iterate over all
    // pair of strings
    int pairs = 0;
    for (int i = 0; i < v.size(); i++)
        for (int j = i + 1; j < v.size(); j++)
            if (isPanDigital(v[i] + v[j]))
                pairs++;
    return pairs;
}
 
// Driver code
int main()
{
    vector v = {"123567", "098234",
                        "14765", "19804"};
    cout << countPandigitalPairs(v) << endl;
    return 0;
}


Java
// Java program to find all
// Pandigital concatenations
// of two strings.
import java.io.*;
import java.util.*;
 
class GFG
{
    static ArrayList v =
                  new ArrayList();
                   
    // Checks if a given
    // string is Pandigital
    static int isPanDigital(String s)
    {
        int digits[] = new int[10];
         
        for (int i = 0; i < s.length(); i++)
            digits[s.charAt(i) -
                        (int)'0'] = 1;
     
        // digit i is not present
        // thus not pandigital
        for (int i = 0; i <= 9; i++)
            if (digits[i] == 0)
                return 0;
     
        return 1;
    }
     
    // Returns number of pairs
    // of strings resulting in
    // Pandigital Concatenations
    static int countPandigitalPairs()
    {
        // iterate over all
        // pair of strings
        int pairs = 0;
        for (int i = 0; i < v.size(); i++)
            for (int j = i + 1;
                     j < v.size(); j++)
                if (isPanDigital(v.get(i) +
                                 v.get(j)) == 1)
                    pairs++;
        return pairs;
    }
     
    // Driver code
    public static void main(String args[])
    {
        v.add("123567");
        v.add("098234");
        v.add("14765");
        v.add("19804");
        System.out.print(countPandigitalPairs());
    }
}
 
// This code is contributed
// by Manish Shaw(manishshaw1)


Python3
# Python3 program to find all
# Pandigital concatenations
# of two strings.
 
# Checks if a given
# is Pandigital
def isPanDigital(s) :
 
    digits = [False] * 10;
 
    for i in range(0, len(s)) :
        digits[int(s[i]) -
               int('0')] = True
 
    # digit i is not present
    # thus not pandigital
    for i in range(0, 10) :
        if (digits[i] == False) :
            return False
 
    return True
 
# Returns number of pairs
# of strings resulting in
# Pandigital Concatenations
def countPandigitalPairs(v) :
 
    # iterate over all
    # pair of strings
    pairs = 0
    for i in range(0, len(v)) :
 
        for j in range (i + 1,
                        len(v)) :
         
            if (isPanDigital(v[i] +
                             v[j])) :
                pairs = pairs + 1
    return pairs
 
# Driver code
v = ["123567", "098234",
        "14765", "19804"]
 
print (countPandigitalPairs(v))
 
# This code is contributed by
# Manish Shaw(manishshaw1)


C#
// C# program to find all Pandigital
// concatenations of two strings.
using System;
using System.Collections.Generic;
 
class GFG
{
    // Checks if a given
    // string is Pandigital
    static int isPanDigital(string s)
    {
        int []digits = new int[10];
        Array.Clear(digits, 0, 10);
        for (int i = 0; i < s.Length; i++)
            digits[s[i] - (int)'0'] = 1;
     
        // digit i is not present
        // thus not pandigital
        for (int i = 0; i <= 9; i++)
            if (digits[i] == 0)
                return 0;
     
        return 1;
    }
     
    // Returns number of pairs
    // of strings resulting in
    // Pandigital Concatenations
    static int countPandigitalPairs(ref List v)
    {
        // iterate over all
        // pair of strings
        int pairs = 0;
        for (int i = 0; i < v.Count; i++)
            for (int j = i + 1; j < v.Count; j++)
                if (isPanDigital(v[i] + v[j]) == 1)
                    pairs++;
        return pairs;
    }
     
    // Driver code
    static void Main()
    {
        List v = new List{"123567", "098234",
                                          "14765", "19804"};
        Console.WriteLine(countPandigitalPairs(ref v));
    }
}
 
// This code is contributed
// by Manish Shaw(manishshaw1)


PHP


C++
// C++ program to count PanDigital pairs
#include 
using namespace std;
 
const int pandigitalMask = ((1 << 10) - 1);
 
void computeMaskFrequencies(vector v, map& freq)
{
    for (int i = 0; i < v.size(); i++) {
        int mask = 0;
 
        // Stores digits present in string v[i]
        // atleast once. We use a set as we only
        // need digits which exist only once
        // (irrespective of reputation)
        unordered_set digits;
        for (int j = 0; j < v[i].size(); j++)
            digits.insert(v[i][j] - '0');
 
        // Calculate the mask by considering all digits
        // existing atleast once
        for (auto it = digits.begin(); it != digits.end(); it++) {
            int digit = (*it);
            mask += (1 << digit);
        }
 
        // Increment the frequency of this mask
        freq[mask]++;
    }
}
 
// Returns number of pairs of strings resulting
// in Pandigital Concatenations
int pandigitalConcatenations(map freq)
{
    int ans = 0;
 
    // All possible strings lie between 1 and 1023
    // so we iterate over every possible mask
    for (int i = 1; i <= 1023; i++) {
        for (int j = 1; j <= 1023; j++) {
 
            // if the concatenation results in mask of
            // Pandigital Concatenation, calculate all
            // pairs formed with Masks i and j
            if ((i | j) == pandigitalMask) {
                if (i == j)
                    ans += (freq[i] * (freq[i] - 1));            
                else
                    ans += (freq[i] * freq[j]);            
            }
        }
    }
 
    // since every pair is considers twice,
    // we get rid of half of these
    return ans/2;
}
 
int countPandigitalPairs(vector v)
{
    // Find frequencies of all masks in
    // given vector of strings
    map freq;
    computeMaskFrequencies(v, freq);
     
    // Return all possiblg concatenations.
    return pandigitalConcatenations(freq);
}
 
// Driver code
int main()
{
    vector v = {"123567", "098234", "14765", "19804"};
    cout << countPandigitalPairs(v) << endl;
    return 0;
}


Java
// Java program to count PanDigital pairs
import java.util.*;
 
class GFG{
 
static int pandigitalMask = ((1 << 10) - 1);
 
static void computeMaskFrequencies(Vector v,
                         HashMap freq)
{
    for(int i = 0; i < v.size(); i++)
    {
        int mask = 0;
 
        // Stores digits present in String v[i]
        // atleast once. We use a set as we only
        // need digits which exist only once
        // (irrespective of reputation)
        HashSet digits = new HashSet<>();
        for(int j = 0; j < v.get(i).length(); j++)
            digits.add(v.get(i).charAt(j) - '0');
 
        // Calculate the mask by considering
        // all digits existing atleast once
        for(int it :digits)
        {
            int digit = (it);
            mask += (1 << digit);
        }
 
        // Increment the frequency of
        // this mask
        if (freq.containsKey(mask))
        {
            freq.put(mask, freq.get(mask) + 1);
        }
        else
        {
            freq.put(mask, 1);
        }
    }
}
 
// Returns number of pairs of Strings
// resulting in Pandigital Concatenations
static int pandigitalConcatenations(
    HashMap freq)
{
    int ans = 0;
 
    // All possible Strings lie between
    // 1 and 1023 so we iterate over every
    // possible mask
    for(int i = 1; i <= 1023; i++)
    {
        for(int j = 1; j <= 1023; j++)
        {
             
            // If the concatenation results in mask of
            // Pandigital Concatenation, calculate all
            // pairs formed with Masks i and j
            if ((i | j) == pandigitalMask &&
                      freq.containsKey(j) &&
                      freq.containsKey(i))
            {
                if (i == j)
                    ans += (freq.get(i) *
                           (freq.get(i) - 1));            
                else
                    ans += (freq.get(i) *
                            freq.get(j));            
            }
        }
    }
     
    // Since every pair is considers twice,
    // we get rid of half of these
    return ans / 2;
}
 
static int countPandigitalPairs(Vector v)
{
     
    // Find frequencies of all masks in
    // given vector of Strings
    HashMap freq = new HashMap<>();
    computeMaskFrequencies(v, freq);
     
    // Return all possiblg concatenations.
    return pandigitalConcatenations(freq);
}
 
// Driver code
public static void main(String[] args)
{
    Vector v  = new Vector<>();
    v.add("123567");
    v.add("098234");
    v.add("14765");
    v.add("19804");
     
    System.out.print(countPandigitalPairs(v) + "\n");
}
}
 
// This code is contributed by Amit Katiyar


C#
// C# program to count
// PanDigital pairs
using System;
using System.Collections.Generic;
class GFG{
 
static int pandigitalMask =
           ((1 << 10) - 1);
 
static void computeMaskFrequencies(List v,
                                   Dictionary freq)
{
  for(int i = 0; i < v.Count; i++)
  {
    int mask = 0;
 
    // Stores digits present in String v[i]
    // atleast once. We use a set as we only
    // need digits which exist only once
    // (irrespective of reputation)
    HashSet digits = new HashSet();
     
    for(int j = 0; j < v[i].Length; j++)
      digits.Add(v[i][j] - '0');
 
    // Calculate the mask by considering
    // all digits existing atleast once
    foreach(int it in digits)
    {
      int digit = (it);
      mask += (1 << digit);
    }
 
    // Increment the frequency of
    // this mask
    if (freq.ContainsKey(mask))
    {
      freq[mask]++;
    }
    else
    {
      freq.Add(mask, 1);
    }
  }
}
 
// Returns number of pairs of
// Strings resulting in Pandigital
// Concatenations
static int pandigitalConcatenations(Dictionary freq)
{
  int ans = 0;
 
  // All possible Strings lie between
  // 1 and 1023 so we iterate over every
  // possible mask
  for(int i = 1; i <= 1023; i++)
  {
    for(int j = 1; j <= 1023; j++)
    {
      // If the concatenation results in
      // mask of Pandigital Concatenation,
      // calculate all pairs formed with
      // Masks i and j
      if ((i | j) == pandigitalMask &&
          freq.ContainsKey(j) &&
          freq.ContainsKey(i))
      {
        if (i == j)
          ans += (freq[i] *
                  (freq[i] - 1));            
        else
          ans += (freq[i] *
                  freq[j]);            
      }
    }
  }
 
  // Since every pair is considers
  // twice, we get rid of half of
  // these
  return ans / 2;
}
 
static int countPandigitalPairs(List v)
{   
  // Find frequencies of all masks in
  // given vector of Strings
  Dictionary freq = new Dictionary();
  computeMaskFrequencies(v, freq);
 
  // Return all possiblg concatenations.
  return pandigitalConcatenations(freq);
}
 
// Driver code
public static void Main(String[] args)
{
  List v  = new List();
  v.Add("123567");
  v.Add("098234");
  v.Add("14765");
  v.Add("19804");
  Console.Write(countPandigitalPairs(v) + "\n");
}
}
 
// This code is contributed by 29AjayKumar


输出:

3



方法2(高效):
现在,我们正在寻找比上面讨论的蛮力更好的东西。仔细的分析表明,对于出现的每个数字0-9,我们都有一个掩码1111111111(即,所有数字0-9都存在于数字数组中)

Digits -  0  1  2  3  4  5  6  7  8  9
          |  |  |  |  |  |  |  |  |  |
Mask   -  1  1  1  1  1  1  1  1  1  1 

Here 1 denotes that the corresponding digits
exists at-least once thus for all such Pandigital 
Concatenations, this relationship should hold.
So we can represent 11...11 as a valid mask for
pandigital concatenations.



所以,现在的做法是表示每一个字符串的地方,如果在字符串中存在第i位的第i位为10位掩码。

E.g., "11405" can be represented as
Digits -           0  1  2  3  4  5  6  7  8  9
                   |  |  |  |  |  |  |  |  |  |
Mask for 11405 -   1  1  0  0  1  1  0  0  0  0



该方法虽然看起来很完整,但仍然无效,因为我们仍然必须遍历所有对,并检查这两个字符串的OR是否会导致有效的Pandigital级联的掩码。

如果我们分析所有可能的字符串的可能掩码,我们可以理解,每个单个字符串将仅由数字0 – 9组成,因此每个数字最多最多可以包含0到9的所有数字,因此该数字的掩码将是1111111111(十进制为1023)。因此,在十进制系统中,所有掩码都以(0 – 1023]的形式退出。

现在我们只需要维护一个频率数组来存储掩码在字符串数组中存在的次数。

C++

// C++ program to count PanDigital pairs
#include 
using namespace std;
 
const int pandigitalMask = ((1 << 10) - 1);
 
void computeMaskFrequencies(vector v, map& freq)
{
    for (int i = 0; i < v.size(); i++) {
        int mask = 0;
 
        // Stores digits present in string v[i]
        // atleast once. We use a set as we only
        // need digits which exist only once
        // (irrespective of reputation)
        unordered_set digits;
        for (int j = 0; j < v[i].size(); j++)
            digits.insert(v[i][j] - '0');
 
        // Calculate the mask by considering all digits
        // existing atleast once
        for (auto it = digits.begin(); it != digits.end(); it++) {
            int digit = (*it);
            mask += (1 << digit);
        }
 
        // Increment the frequency of this mask
        freq[mask]++;
    }
}
 
// Returns number of pairs of strings resulting
// in Pandigital Concatenations
int pandigitalConcatenations(map freq)
{
    int ans = 0;
 
    // All possible strings lie between 1 and 1023
    // so we iterate over every possible mask
    for (int i = 1; i <= 1023; i++) {
        for (int j = 1; j <= 1023; j++) {
 
            // if the concatenation results in mask of
            // Pandigital Concatenation, calculate all
            // pairs formed with Masks i and j
            if ((i | j) == pandigitalMask) {
                if (i == j)
                    ans += (freq[i] * (freq[i] - 1));            
                else
                    ans += (freq[i] * freq[j]);            
            }
        }
    }
 
    // since every pair is considers twice,
    // we get rid of half of these
    return ans/2;
}
 
int countPandigitalPairs(vector v)
{
    // Find frequencies of all masks in
    // given vector of strings
    map freq;
    computeMaskFrequencies(v, freq);
     
    // Return all possiblg concatenations.
    return pandigitalConcatenations(freq);
}
 
// Driver code
int main()
{
    vector v = {"123567", "098234", "14765", "19804"};
    cout << countPandigitalPairs(v) << endl;
    return 0;
}

Java

// Java program to count PanDigital pairs
import java.util.*;
 
class GFG{
 
static int pandigitalMask = ((1 << 10) - 1);
 
static void computeMaskFrequencies(Vector v,
                         HashMap freq)
{
    for(int i = 0; i < v.size(); i++)
    {
        int mask = 0;
 
        // Stores digits present in String v[i]
        // atleast once. We use a set as we only
        // need digits which exist only once
        // (irrespective of reputation)
        HashSet digits = new HashSet<>();
        for(int j = 0; j < v.get(i).length(); j++)
            digits.add(v.get(i).charAt(j) - '0');
 
        // Calculate the mask by considering
        // all digits existing atleast once
        for(int it :digits)
        {
            int digit = (it);
            mask += (1 << digit);
        }
 
        // Increment the frequency of
        // this mask
        if (freq.containsKey(mask))
        {
            freq.put(mask, freq.get(mask) + 1);
        }
        else
        {
            freq.put(mask, 1);
        }
    }
}
 
// Returns number of pairs of Strings
// resulting in Pandigital Concatenations
static int pandigitalConcatenations(
    HashMap freq)
{
    int ans = 0;
 
    // All possible Strings lie between
    // 1 and 1023 so we iterate over every
    // possible mask
    for(int i = 1; i <= 1023; i++)
    {
        for(int j = 1; j <= 1023; j++)
        {
             
            // If the concatenation results in mask of
            // Pandigital Concatenation, calculate all
            // pairs formed with Masks i and j
            if ((i | j) == pandigitalMask &&
                      freq.containsKey(j) &&
                      freq.containsKey(i))
            {
                if (i == j)
                    ans += (freq.get(i) *
                           (freq.get(i) - 1));            
                else
                    ans += (freq.get(i) *
                            freq.get(j));            
            }
        }
    }
     
    // Since every pair is considers twice,
    // we get rid of half of these
    return ans / 2;
}
 
static int countPandigitalPairs(Vector v)
{
     
    // Find frequencies of all masks in
    // given vector of Strings
    HashMap freq = new HashMap<>();
    computeMaskFrequencies(v, freq);
     
    // Return all possiblg concatenations.
    return pandigitalConcatenations(freq);
}
 
// Driver code
public static void main(String[] args)
{
    Vector v  = new Vector<>();
    v.add("123567");
    v.add("098234");
    v.add("14765");
    v.add("19804");
     
    System.out.print(countPandigitalPairs(v) + "\n");
}
}
 
// This code is contributed by Amit Katiyar

C#

// C# program to count
// PanDigital pairs
using System;
using System.Collections.Generic;
class GFG{
 
static int pandigitalMask =
           ((1 << 10) - 1);
 
static void computeMaskFrequencies(List v,
                                   Dictionary freq)
{
  for(int i = 0; i < v.Count; i++)
  {
    int mask = 0;
 
    // Stores digits present in String v[i]
    // atleast once. We use a set as we only
    // need digits which exist only once
    // (irrespective of reputation)
    HashSet digits = new HashSet();
     
    for(int j = 0; j < v[i].Length; j++)
      digits.Add(v[i][j] - '0');
 
    // Calculate the mask by considering
    // all digits existing atleast once
    foreach(int it in digits)
    {
      int digit = (it);
      mask += (1 << digit);
    }
 
    // Increment the frequency of
    // this mask
    if (freq.ContainsKey(mask))
    {
      freq[mask]++;
    }
    else
    {
      freq.Add(mask, 1);
    }
  }
}
 
// Returns number of pairs of
// Strings resulting in Pandigital
// Concatenations
static int pandigitalConcatenations(Dictionary freq)
{
  int ans = 0;
 
  // All possible Strings lie between
  // 1 and 1023 so we iterate over every
  // possible mask
  for(int i = 1; i <= 1023; i++)
  {
    for(int j = 1; j <= 1023; j++)
    {
      // If the concatenation results in
      // mask of Pandigital Concatenation,
      // calculate all pairs formed with
      // Masks i and j
      if ((i | j) == pandigitalMask &&
          freq.ContainsKey(j) &&
          freq.ContainsKey(i))
      {
        if (i == j)
          ans += (freq[i] *
                  (freq[i] - 1));            
        else
          ans += (freq[i] *
                  freq[j]);            
      }
    }
  }
 
  // Since every pair is considers
  // twice, we get rid of half of
  // these
  return ans / 2;
}
 
static int countPandigitalPairs(List v)
{   
  // Find frequencies of all masks in
  // given vector of Strings
  Dictionary freq = new Dictionary();
  computeMaskFrequencies(v, freq);
 
  // Return all possiblg concatenations.
  return pandigitalConcatenations(freq);
}
 
// Driver code
public static void Main(String[] args)
{
  List v  = new List();
  v.Add("123567");
  v.Add("098234");
  v.Add("14765");
  v.Add("19804");
  Console.Write(countPandigitalPairs(v) + "\n");
}
}
 
// This code is contributed by 29AjayKumar

输出:

3



复杂度: O(N * | s | + 1023 * 1023)其中| s |给出数组中字符串的长度