2016-04-03 123 views
0

我在这里看到了几个问题,并不完全回答我的问题。我试图做一些经常在面试问题中使用的经典矩阵旋转问题的翻译。我没有关注方矩阵,而是对M×N矩阵感兴趣。如何将M×N矩阵180度旋转到位?

对于输入矩阵

1 2 3 
4 5 6 
7 8 9 
1 2 3 

我想矩阵变换成

3 2 1 
9 8 7 
6 5 4 
3 2 1 

这里是我写的代码:

#include <iostream> 
#include <vector> 
#include <algorithm> 

void do_swaps(int& a, int& b, int& c, int& d) { 
    std::swap(a, b); 
    std::swap(c, d); 
} 

void rotate(std::vector<std::vector<int>>& v) { 
    size_t m = v.size(); 
    size_t n = v[0].size(); 

    for(size_t i = 0; i < m/2; ++i) { 
    for(size_t j = 0; j <= n/2; ++j) { 
     do_swaps(v[i][j], v[m-i-1][n-j-1], v[m-j-1][i], v[j][n-i-1]); 
    } 
    } 
} 

void print(const std::vector<std::vector<int>>& v) { 
    size_t m = v.size(); 
    size_t n = v[0].size(); 

    for(size_t i = 0; i < m; ++i) { 
    for(size_t j = 0; j < n; ++j) { 
     std::cout << v[i][j] << ' '; 
    } 
    std::cout << '\n'; 
    } 
} 


int main() { 
    std::vector<std::vector<int>> m{{1,2,3}, {4,5,6}, {7,8,9}, {1, 2, 3}}; 
    std::cout << "Before: \n"; 
    print(m); 
    rotate(m); 
    std::cout << "\nAfter: \n"; 
    print(m); 
} 

这是我的输出:

Before: 
1 2 3 
4 5 6 
7 8 9 
1 2 3 

After: 
3 2 1 
9 5 7 
6 8 4 
3 2 1 

我的代码适用于3 x 3矩阵(尚未测试更高维矩阵),但我似乎在代码中出现了一处错误,导致最内层元素保持未修剪状态。

在行for(size_t j = 0; j <= n/2; ++j) {,我试着将停止条件调整为几件事情,包括j < (n+1)/2;j < (n-1)/2;,但它仍然是一样的。

有人可以解释我的算法出错了吗?

回答

2

当行数为奇数时,您不会照顾中线。

此外,您交换位于中间列(当列号为奇数时)的元素两次。您可以检查是否m是奇数与位按 - 与1.

以下是一个更简单的方法来项目交换值是上面介绍,你甚至不必关心在这种情况下的中间列。

void rotate(std::vector<std::vector<int>>& v) { 
    size_t m = v.size(); 
    size_t n = v[0].size(); 

    for (size_t i = 0; i < m/2; ++i) 
    { 
     for (size_t j = 0; j < n; ++j) 
      std::swap(v[i][j], v[m - i - 1][n - j - 1]); 
    } 
    if (m&1) 
    for (size_t i = 0; i< n/2; ++i) 
     std::swap(v[m/2][i], v[m/2][n-i-1]); 
} 
+1

这似乎并不一般。小心解释一下? – erip

+1

1.你没有在中间翻转行 2.你在中间列上交换元素两次 – hedgie

+0

它似乎对我的输入有效,但我仍然不完全理解代码的情况。如果你添加更多的解释,我会接受它。 – erip

1

我会使用镜X然后镜ý或反之亦然。它适用于任何分辨率(偶数/奇数)并且安全。所以先交换所有行,然后交换所有列(反之亦然)。这里有一些代码。

void rotate(std::vector<std::vector<int>>& v) { 
    size_t m= v.size(); 
    size_t n=v[0].size(); 

    for(size_t i=0;i<m;i++) { 
    for(size_t j=0,k=n-1;j<k;j++,k--) { 
     std::swap(v[i][j],v[i][k]); 
    } 
    } 

    for(size_t j=0;j<n;j++) { 
    for(size_t i=0, k=m-1; i<k; i++, k--) { 
     std::swap(v[i][j],v[k][j]);  
    } 
    } 
} 
+0

这很直观。这实际上是我的第一个解决方案的基础,但我认为它可以很容易地通过“m”和“n”的“单程”轻松完成。 – erip

1

一个pythonish方式(不到位):

d = (1, 2, 3), (4, 5, 6), (7, 8, 9), (1, 2, 3) 

[r[::-1] for r in d[::-1]] 
+0

伟大的解决方案! – erip