Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 查找包含查询数组所有元素的输入数组的最小窗口_C#_Algorithm_Data Structures_Collections - Fatal编程技术网

C# 查找包含查询数组所有元素的输入数组的最小窗口

C# 查找包含查询数组所有元素的输入数组的最小窗口,c#,algorithm,data-structures,collections,C#,Algorithm,Data Structures,Collections,问题:给定一个由大小为n的整数组成的输入数组和一个由大小为k的整数组成的查询数组,找到输入数组中包含查询数组所有元素且顺序相同的最小窗口 我试过下面的方法 int[] inputArray = new int[] { 2, 5, 2, 8, 0, 1, 4, 7 }; int[] queryArray = new int[] { 2, 1, 7 }; 将查找inputArray中所有查询数组元素的位置 public static void SmallestWin

问题:给定一个由大小为n的整数组成的输入数组和一个由大小为k的整数组成的查询数组,找到输入数组中包含查询数组所有元素且顺序相同的最小窗口

我试过下面的方法

        int[] inputArray = new int[] { 2, 5, 2, 8, 0, 1, 4, 7 };
        int[] queryArray = new int[] { 2, 1, 7 };
将查找inputArray中所有查询数组元素的位置

public static void SmallestWindow(int[] inputArray, int[] queryArray)
    {
        Dictionary<int, HashSet<int>> dict = new Dictionary<int, HashSet<int>>();

        int index = 0;
        foreach (int i in queryArray)
        {
            HashSet<int> hash = new HashSet<int>();
            foreach (int j in inputArray)
            {
                index++;
                if (i == j)
                    hash.Add(index); 
            }
            dict.Add(i, hash);
            index = 0;
        }
      // Need to perform action in above dictionary.??
    }
publicstaticvoidsmallestwindow(int[]inputArray,int[]queryArray)
{
Dictionary dict=新字典();
int指数=0;
foreach(queryArray中的int i)
{
HashSet hash=新HashSet();
foreach(输入阵列中的int j)
{
索引++;
如果(i==j)
hash.Add(索引);
}
dict.Add(i,散列);
指数=0;
}
//需要执行上述字典中的操作。??
}
我找到了下面的字典

  • int 2-->位置{1,3}
  • int 1-->位置{6}
  • int 7-->位置{8}
  • 现在我想执行以下步骤来查找最小窗口

  • 比较int 2位置和int 1位置。因为(6-3)<(6-1)…所以我将在hashmap中存储3,6

  • 将像上面一样比较int 1和int 7的位置


  • 我无法理解如何比较字典的两个连续值。请帮助。

    我看不出使用
    HashSet
    Dictionary
    在这方面有什么帮助。如果我面对这个问题,我会采取完全不同的做法

    一种方法(不是最有效的方法)如下所示。此代码假定
    queryArray
    至少包含两项

    int FindInArray(int[] a, int start, int value)
    {
        for (int i = start; i < a.Length; ++i)
        {
            if (a[i] == value)
                return i;
        }
        return -1;
    }
    
    struct Pair
    {
        int first;
        int last;
    }
    
    List<Pair> foundPairs = new List<Pair>();
    
    int startPos = 0;
    bool found = true;
    while (found)
    {
        found = false;
        // find next occurrence of queryArray[0] in inputArray
        startPos = FindInArray(inputArray, startPos, queryArray[0]);
        if (startPos == -1)
        {
            // no more occurrences of the first item
            break;
        }
        Pair p = new Pair();
        p.first = startPos;
        ++startPos;
        int nextPos = startPos;
        // now find occurrences of remaining items
        for (int i = 1; i < queryArray.Length; ++i)
        {
            nextPos = FindInArray(inputArray, nextPos, queryArray[i]);
            if (nextPos == -1)
            {
                break;  // didn't find it
            }
            else
            {
                p.last = nextPos++;
                found = (i == queryArray.Length-1);
            }
        }
        if (found)
        {
            foundPairs.Add(p);
        }
    }
    
    // At this point, the foundPairs list contains the (start, end) of all
    // sublists that contain the items in order.
    // You can then iterate through that list, subtract (last-first), and take
    // the item that has the smallest value.  That will be the shortest sublist
    // that matches the criteria.
    
    int FindInArray(int[]a,int start,int value)
    {
    对于(int i=开始;i

    通过一些工作,可以提高效率。例如,如果“queryArray”包含
    [1,2,3]
    inputArray
    包含
    [1,7,4,9,1,3,6,4,1,8,2,3]
    ,则上述代码将找到三个匹配项(从位置0,4和8开始)。稍微聪明一点的代码可以确定,当在位置4处发现
    1
    时,由于在此之前未发现
    2
    ,从第一个位置开始的任何序列都会比从位置4开始的序列长,因此会短路第一个序列并从新位置重新开始。不过,这使代码有点复杂。

    算法:
    对于查询数组中的每个元素,存储在映射M(V)中→ (I,P)),V是元素,I是输入数组的索引,P是查询数组中的位置。(输入数组中某些P的索引最大,因此查询[0..P]是输入[I..curr]的子序列)

    遍历数组。
    如果该值是查询数组中的第一项:将当前索引存储为I。
    否则:存储查询数组中上一个元素的索引值,例如
    M[currVal].I=M[query[M[currVal].P-1].I

    如果该值是最后一项:检查[I..curr]是否为新的最佳值

    复杂性
    其复杂性为O(N),其中N是输入数组的大小

    N.B.
    这段代码要求查询数组中没有重复的元素。为此,我们可以使用地图M(V→ ((I,P))的列表。这是O(NhC(Q)),其中hC(Q)是查询数组的模式计数。
    使用M(V)更好→ listOf((linkedList(I),P)))。当查询数组中连续出现重复元素时,我们使用链表。然后更新这些值成为O(1)。然后,复杂度为O(NhC(D(Q)),其中D(Q)是具有合并的连续项的Q

    实施

    示例java实现可用。这不适用于查询数组中的重复元素,也不适用于错误检查等。

    您希望字典中的值不是哈希集,而是(排序的)树或数组;字典包含从输入数组中找到的值到该值出现的(排序)索引列表的映射

    然后你做下面的事情

    • 查找查询中的第一个条目。选择它出现的最低索引
    • 查找第二个条目;选择大于第一个索引的最低条目
    • 查第三个;选择大于第二个的最小值。(等等)
    • 当您到达查询中的最后一个条目时,(1+最后一个索引-第一个索引)是最小匹配的大小
    • 现在选择第一个查询的第二个索引,重复,等等
    • 2 --> position {0,2}   // note: I change them to 0-based array
      1 --> position {5,6}  // I suppose it's {5,6} to make it more complex, in your code it's only {5}
      7 --> position {7}
      
       struct Pair
       {
           public int Number;  // the number in queryArray
           public int[] Indexes;  // the positions of the number
       }
       static List<int[]> results = new List<int[]>(); //store all possible paths
       static Stack<int> currResult = new Stack<int>(); // the container of current path
       static int[] inputArray, queryArray; 
       static Pair[] pairs;
      
      inputArray = new int[] { 2, 7, 1, 5, 2, 8, 0, 1, 4, 7 }; //my test case
      queryArray = new int[] { 2, 1, 7 };
      pairs = (from n in queryArray
            select new Pair { Number = n, Indexes = inputArray.FindAllIndexes(i => i == n) }).ToArray();
      Go(0);
      
      public static int[] FindAllIndexes<T>(this IEnumerable<T> source, Func<T,bool> predicate)
      {
           //do necessary check here, then
           Queue<int> indexes = new Queue<int>();
           for (int i = 0;i<source.Count();i++)
                 if (predicate(source.ElementAt(i))) indexes.Enqueue(i);
           return indexes.ToArray();
      }
      
      static void Go(int depth)
      {
          if (depth == pairs.Length)
          {
              results.Add(currResult.Reverse().ToArray());
          }
          else
          {
              var indexes = pairs[depth].Indexes;
              for (int i = 0; i < indexes.Length; i++)
              {
                  if (depth == 0 || indexes[i] > currResult.Last())
                  {
                      currResult.Push(indexes[i]);
                      Go(depth + 1);
                      currResult.Pop();
                  }
              }
          }
      }
      
      public static int[] SmallestWindow(int[] inputArray, int[] queryArray)
      {
          var indexed = queryArray
              .SelectMany(x => inputArray
                                   .Select((y, i) => new
                                       {
                                           Value = y,
                                           Index = i
                                       })
                                   .Where(y => y.Value == x))
              .OrderBy(x => x.Index)
              .ToList();
      
          var segments = indexed
              .Select(x =>
                  {
                      var unique = new HashSet<int>();
                      return new
                          {
                              Item = x,
                              Followers = indexed
                                  .Where(y => y.Index >= x.Index)
                                  .TakeWhile(y => unique.Count != queryArray.Length)
                                  .Select(y =>
                                      {
                                          unique.Add(y.Value);
                                          return y;
                                      })
                                  .ToList(),
                              IsComplete = unique.Count == queryArray.Length
                          };
                  })
              .Where(x => x.IsComplete);
      
          var queryIndexed = segments
              .Select(x => x.Followers.Select(y => new
                  {
                      QIndex = Array.IndexOf(queryArray, y.Value),
                      y.Index,
                      y.Value
                  }).ToArray());
      
          var queryOrdered = queryIndexed
              .Where(item =>
                  {
                      var qindex = item.Select(x => x.QIndex).ToList();
                      bool changed;
                      do
                      {
                          changed = false;
                          for (int i = 1; i < qindex.Count; i++)
                          {
                              if (qindex[i] <= qindex[i - 1])
                              {
                                  qindex.RemoveAt(i);
                                  changed = true;
                              }
                          }
                      } while (changed);
                      return qindex.Count == queryArray.Length;
                  });
      
          var result = queryOrdered
              .Select(x => new[]
                  {
                      x.First().Index,
                      x.Last().Index
                  })
              .OrderBy(x => x[1] - x[0]);
      
          var best = result.FirstOrDefault();
          return best;
      }
      
      public void Test()
      {
          var inputArray = new[] { 2, 1, 5, 6, 8, 1, 8, 6, 2, 9, 2, 9, 1, 2 };
          var queryArray = new[] { 6, 1, 2 };
      
          var result = SmallestWindow(inputArray, queryArray);
      
          if (result == null)
          {
              Console.WriteLine("no matching window");
          }
          else
          {
              Console.WriteLine("Smallest window is indexes " + result[0] + " to " + result[1]);
          }
      }
      
      Smallest window is indexes 3 to 8
      
          public class Pair
          {
          public int Number;
          public List<int> Position;
          }
      
           public static Pair[]  GetIndex(int[] inputArray, int[] query)
            {
              Pair[] pairList = new Pair[query.Length]; 
              int pairIndex = 0;
              foreach (int i in query)
              {
                  Pair pair = new Pair();
                  int index = 0;
                  pair.Position = new List<int>();
                  foreach (int j in inputArray)
                  {                    
                      if (i == j)
                      {
                          pair.Position.Add(index);
                      }
                      index++;
                  }
                  pair.Number = i;
                  pairList[pairIndex] = pair;
                  pairIndex++;
              }
              return pairList;
          }
      
              Pair[] pairs = NewCollection.GetIndex(array, intQuery);
      
              List<int> minWindow = new List<int>();
              for (int i = 0; i <pairs.Length - 1; i++)
              {
                  List<int> first = pairs[i].Position;
                  List<int> second = pairs[i + 1].Position;
                  int? temp = null;
                  int? temp1 = null;
                  foreach(int m in first)
                  {
                      foreach (int n in second)
                      {
                          if (n > m)
                          {
                              temp = m;
                              temp1 = n;
                          }                        
                      }                    
                  }
                  if (temp.HasValue && temp1.HasValue)
                  {
                      if (!minWindow.Contains((int)temp))
                          minWindow.Add((int)temp);
                      if (!minWindow.Contains((int)temp1))
                          minWindow.Add((int)temp1);
                  }
                  else
                  {
                      Console.WriteLine(" Bad Query array");
                      minWindow.Clear();
                      break;                    
                  }
              }
      
              if(minWindow.Count > 0)
              {
               Console.WriteLine("Minimum Window is :");
               foreach(int i in minWindow)
               {
                   Console.WriteLine(i + " ");
               }
              }
      
          void findMinWindow(const vector<int>& input, const vector<int>& query) {
               map<int, int> qtree;
               for(vector<int>::const_iterator itr=query.begin(); itr!=query.end(); itr++) {
                  qtree[*itr] = 0;
               }
      
               int first_ptr=0;
               int begin_ptr=0;
      
               int index1 = 0;
               int queptr = 0;
      
               int flip = 0;
      
               while(true) {
                   //check if value is in query
                   if(qtree.find(input[index1]) != qtree.end()) {
                      int x = qtree[input[index1]];
                      if(0 == x) {
                        flip++;
                      }
                      qtree[input[index1]] = ++x;
                    }
      
                    //remove all nodes that are not required and
                    //yet satisfy the all query condition.
                    while(query.size() == flip) {
                      //done nothing more
                      if(queptr == input.size()) {
                        break;
                      }
      
                      //check if queptr is pointing to node in the query
                      if(qtree.find(input[queptr]) != qtree.end()) {
                        int y = qtree[input[queptr]];
                        //more nodes and the queue is pointing to deleteable node
                        //condense the nodes
                        if(y > 1) {
                          qtree[input[queptr]] = --y;
                          queptr++;
                        } else {
                          //cant condense more just keep that memory
                          if((!first_ptr && !begin_ptr) ||
                              ((first_ptr-begin_ptr)>(index1-queptr))) {
                            first_ptr=index1;
                            begin_ptr=queptr;
                          }
                          break;
                        }
                      } else {
                        queptr++;
                      }
                    }
      
                   index1++;
      
                   if(index1==input.size()) {
                      break;
                   }
               }
               cout<<"["<<begin_ptr<<" - "<<first_ptr<<"]"<<endl;
          }
      
          #include <iostream>
          #include <vector>
          #include <map>
      
          using namespace std;
      
          int main() {
              vector<int> input;
              input.push_back(2);
              input.push_back(5);
              input.push_back(2);
              input.push_back(8);
              input.push_back(0);
              input.push_back(1);
              input.push_back(4);
              input.push_back(7);
      
              vector<int> query1;
              query1.push_back(2);
              query1.push_back(8);
              query1.push_back(0);
      
              vector<int> query2;
              query2.push_back(2);
              query2.push_back(1);
              query2.push_back(7);
      
              vector<int> query3;
              query3.push_back(1);
              query3.push_back(4);
      
              findMinWindow(input, query1);
              findMinWindow(input, query2);
              findMinWindow(input, query3);
          }