1030.距离顺序排列矩阵单元格

题目描述

给出R行C列的矩阵,其中的单元格的整数坐标为(r,c),满足0 <= r < R且0 <= c < C。
另外,我们在该矩阵中给出了一个坐标为(r0,c0)的单元格。
返回矩阵中的所有单元格的坐标,并按到(r0,c0)的距离从最小到最大的顺序排序,其中,返回两单元格(r1,c1)和(r2,c2)之间的距离时曼哈顿距离,| r1 - r2 | + | c1 - c2 |。(你可以按任何满足此条件的顺序返回答案)

示例1

  • 输入:R = 1,C = 2,r0 = 0,c0 = 0
  • 输出:[ [0,0] , [0,1] ]
  • 解释:从(r0,c0)到其他单元格的距离为:[0,1]

示例2

  • 输入:R = 2,C = 2,r0 = 0,c0 = 1
  • 输出:[ [0,1] ,[0,0],[1,1],[1,0] ]
  • 解释:从(r0,c0)到其他单元格的距离为:[0,1,1,2]
    [ [0,1],[1,1],[0,0],[1,0] ]也会被视作正确答案

示例3

  • 输入:R = 2,C = 3,r0 = 1,c0 = 2
  • 输出:[ [1,2] ,[0,2],[1,1],[0,1],[1,0],[0,0] ]
  • 解释:从(r0,c0)到其他单元格的距离为:[0,1,1,2,2,3]
    其他满足题目要求的答案也会被视为正确,例如[ [1,2],[1,1],[0,2],[1,0],[0,1],[0,0] ]。

提示

  1. 1 <= R <= 100
  2. 1 <= C <= 100
  3. 0 <= r0 < R
  4. 0 <= c0 < C

题解

先将所有的单元格的坐标放入向量v,再声明一个整形数组len用来保存每个单元格到(r0,c0)的距离,len和v的下标是一一对应的。将所有元素都放入数组后,再进行升序排序,这里要把数组len和向量v同时排序。这里我用的是快速排序方法。

代码如下

class Solution {
public:
    void sort(vector< vector > &v, int len[], int low, int high)
    {
        if(high > 100) //单元格数量大于100,用快速排序
            Qsort(v, len, low, high);
        else //否则用插入排序
            Insertsort(v, len, high);
    }
    void Qsort(vector< vector > &v, int len[], int low, int high) //快速排序
    {
        int pivot; 
        if(low < high)
        {
            pivot = Part(v, len, low, high); //将v和len一分为二
            Qsort(v, len, low, pivot-1); //对低子表递归排序
            Qsort(v, len, pivot+1, high); //对高子表递归排序
        }
    }
    int Part(vector< vector > &v, int len[], int low, int high) //先选取当中的一个关键字(pivot),然后想办法将它放到一个位置,
   使得它左边的值都比它小,右边的值都比它大
    {
        vector temp(2);
        int pivotkey = len[low]; //用子表的第一个元素作关键字
        int tmp;
        while(low < high) //从表的两端交替向中间扫描
        {
            while(low < high && len[high] >= pivotkey)
            {
                high--;
            }
            //将比pivotkey小的元素换到低位
            temp = v[low];
            v[low] = v[high];
            v[high] = temp;
            tmp = len[low];
            len[low] = len[high];
            len[high] = tmp;
            while(low < high && len[low] <= pivotkey)
            {
                low++;
            }
            //将比pivotkey大的元素换到高位
            temp = v[low];
            v[low] = v[high];
            v[high] = temp;
            tmp = len[low];
            len[low] = len[high];
            len[high] = tmp;
        }
        return low; //返回pivotkey所在的位置
    }
    void Insertsort(vector< vector > &v, int len[], int high) //直接插入排序
    {
        int i,j;
        int t;
        vector temp(2);
        for(i = 1; i <= high; i++)
        {
            if(len[i-1] > len[i]) //需要把len[i]插入数组
            {
                t = len[i]; //设置哨兵
                temp = v[i];
                for(j = i-1; j>=0 && len[j] >= t; j--) //记录后移
                {
                    len[j+1] = len[j];
                    v[j+1] = v[j];
                }
                len[j+1] = t;  //插入到正确位置
                v[j+1] = temp;
            }
        }
    }
    vector> allCellsDistOrder(int R, int C, int r0, int c0) {
        vector> v;
        vector temp(2);
        int len[R*C] = {0};
        int i, j, templen,k;
        for(i = 0; i < R; i++)
        {
            temp[0] = i;
            for(j = 0; j < C; j++)
            {
                temp[1] = j;
                v.push_back(temp);
                len[j+i*C] = abs(temp[0]-r0) + abs(temp[1]-c0);
            }
        }
        sort(v,len,0,C*R-1);
        return v;
    }
};

结果

这道题我提交了n多次,主要问题有两个:下标越界和超时。

  • 下标越界

下标越界问题出在插入排序的循环条件判断中【没错,又是这个for循环】
最初的代码

for(k = i - 1; len[k] >= templen && k >= 0; k--)

错误提示

runtime error: index -1 out of bounds for type 'int [*]' (solution.cpp)

这个提示说明k会减小到-1,进行条件判断时会判断 len[-1] >=templen,而len[-1]是不存在的元素,于是下标越界就发生了。

改进代码

              for(k = i - 1; k >= 0; k--)
              {
                  if(len[k] >= templen)
                  {
                      len[k+1] = len[k];
                      v[k+1] = v[k];
                  }
                  else
                      break;
              }

这段代码将一部分条件判断放入了循环内,这样就避免了下标越界。

  • 超时
    最初的代码用的是直接插入排序【时间复杂度为O(n^2)】。因为显示超时,我就加入了快速排序【时间复杂度为O(nlogn)】。当单元格的数量大于100时,采用快速排序,否则就用直接插入排序。

最后po一下结果吧,其实挺慢的【苦笑


1030.距离顺序排列矩阵单元格_第1张图片
通过结果

你可能感兴趣的:(1030.距离顺序排列矩阵单元格)