2016-04-03 14 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次元マトリックス(高次元のマトリックスはテストしていません)でも動作しますが、コード内で1つのエラーが発生しているため、最も内側のエレメントがスワップしないままです。

for(size_t j = 0; j <= n/2; ++j) {の行では、j < (n+1)/2;j < (n-1)/2;などのいくつかの条件で停止条件を調整しようとしましたが、同じままです。

誰かが自分のアルゴリズムでどこが間違っているのか説明できますか?

答えて

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.中間の列の要素を2回スワップします – hedgie

+0

入力にはうまくいくようですが、コードで何が起こっているのかはまだ分かりません。あなたがそれ以上の説明を加えると、私はそれを受け入れるでしょう。 – erip

1

IはミラーX、次いでミラーYまたはその逆を使用します。任意の解像度(偶数/奇数)で、その場で安全です。したがって、最初にすべての行を交換し、次にすべての列を交換します(またはその逆)。ここにいくつかのコードがあります。

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

関連する問題