Selection algorithms on sorted matrix

后端 未结 8 1750
野性不改
野性不改 2020-11-28 22:51

this is a google interview question :

Given a N*N Matrix. All rows are sorted, and all columns are sorted. Find the Kth Largest element of the matrix.

doing

相关标签:
8条回答
  • 2020-11-28 23:25

    My code below is an O(k) algorithm. It does not work on a certain edge case (probably one in each direction: x and y). I listed the edge case so someone can fix it. I'm not going to fix it because it's bed time for me.

    Summary of algorithm: you only need to keep track of two candidate #s that might be the smallest, one while proceeding in the x-direction and one while proceeding in the y-direction. Think about it and it might make sense to you.

    enum Direction {
      X,
      Y
    };
    
    struct Index
    {
      Index(int unsigned x, int unsigned y)
        : x(x),
          y(y)
      {}
    
      void operator = (Index const & rhs)
      {
        x = rhs.x;
        y = rhs.y;
      }
    
      int unsigned x;
      int unsigned y;
    };
    
    int unsigned solve(int unsigned i_k, int unsigned ** i_data, int unsigned i_n)
    {
      if (1 == i_k) {
        return i_data[0][0];
      }
    
      Direction dir = X;
      Index smaller(0,0);
      Index larger(0,0);
    
      if (i_data[1][0] < i_data[0][1]) {
        dir = X;
        smaller = Index(1,0);
        larger = Index(0,1); }
      else {
        dir = Y;
        smaller = Index(0,1);
        larger = Index(1,0);
      }
    
      for (int unsigned i = 0; i < (i_k - 2); ++i) {
        int unsigned const x = smaller.x;
        int unsigned const y = smaller.y;
        if (X == dir) {
          if ((x + 1) == i_n) {
            // End of row
            smaller = larger;
            larger.x += 1;
            dir = Y; }
          else if (i_data[x + 1][y] < i_data[larger.x][larger.y]) {
            smaller.x += 1; }
          else {
            smaller = larger;
            larger = Index(x + 1, y);
            dir = Y;
          } }
        else {
          if ((y + 1) == i_n) {
            // End of col
            smaller = larger;
            larger.y += 1;
            dir = X; }
          else if (i_data[x][y + 1] < i_data[larger.x][larger.y]) {
            smaller.y += 1; }
          else {
            smaller = larger;
            larger = Index(x, y + 1);
            dir = X;
          }
        }
      }
      return i_data[smaller.x][smaller.y];
    }
    

    doesn't work on the following edge case (where we hit the end of a row). I'm going to bed, feel free to fix this case:

      size = 4;
      data = createMatrix(size);
      data[0][0] = 1; data[1][0] = 6; data[2][0] = 10; data[3][0] = 11;
      data[0][1] = 3; data[1][1] = 7; data[2][1] = 12; data[3][1] = 14;
      data[0][2] = 4; data[1][2] = 8; data[2][2] = 13; data[3][2] = 15;
      data[0][3] = 5; data[1][3] = 9; data[2][3] = 19; data[3][3] = 20;
      answer = solve(14, data, size);
      assertAnswer(answer, 15, ++testNum);
      deleteMatrix(data, size);
    
    0 讨论(0)
  • 2020-11-28 23:26

    Yes, there is an O(K) algorithm due to Frederickson and Johnson.

    Greg N. Frederickson and Donald B. Johnson. Generalized Selection and Ranking: Sorted Matrices. SIAM J. Comput. 13, pp. 14-30. http://epubs.siam.org/sicomp/resource/1/smjcat/v13/i1/p14_s1?isAuthorized=no

    0 讨论(0)
提交回复
热议问题