{"id":15383,"date":"2010-01-06T07:00:00","date_gmt":"2010-01-06T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2010\/01\/06\/can-you-get-rotating-an-array-to-run-faster-than-on\/"},"modified":"2010-01-06T07:00:00","modified_gmt":"2010-01-06T07:00:00","slug":"can-you-get-rotating-an-array-to-run-faster-than-on","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20100106-00\/?p=15383","title":{"rendered":"Can you get rotating an array to run faster than O(n&#178;)?"},"content":{"rendered":"<p>\nSome follow-up remarks to my old posting on\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2008\/09\/02\/8918130.aspx\">\nrotating a two-dimensional array<\/a>:\n<\/p>\n<p>\nSome people noticed that the article I linked to purporting to rotate\nthe array actually transposes it.\nI was wondering how many people would pick up on that.\n<\/p>\n<p>\nI was surprised that people confused\nrotating an array (or matrix) with creating a rotation matrix.\nThey are unrelated operations;\nthe only thing they have in common are the letters r-o-t-a-t-i.\nA matrix is a representation of a linear transformation,\nand\na rotation matrix is a linear transformation which rotates <i>vectors<\/i>.\nIn other words, applying the rotation matrix to a vector produces\na new vector which is a rotated version of the original vector.\nThe linear transformation is a <i>function<\/i> of one parameter:\nIt takes a vector and produces a new vector.\nA rotation matrix is a matrix which <i>rotates other things<\/i>.\nWhereas rotating an array is something you do <i>to the array<\/i>.\nThe array is the thing being rotated, not the thing doing the rotating.\nIt didn&#8217;t even occur to me that people would confuse the two.\nIt&#8217;s the difference a phone dial and dialing a phone.\n<\/p>\n<p>\nShowing that you cannot rotate an array via matrix multiplication\nis straightforward.\nSuppose there were a matrix <i>R<\/i> which rotated an array (laid\nout in the form of a matrix) clockwise.\nThe result of rotating the identity matrix would be a\na matrix with 1&#8217;s along the diagonal\nfrom upper right to lower left, let&#8217;s call that matrix&nbsp;<i>J<\/i>.\nThen we have <i>RI&nbsp;=&nbsp;J<\/i>, and therefore <i>R&nbsp;=&nbsp;J<\/i>.\nNow apply&nbsp;<i>R<\/i> to both sides:\n<i>RRI&nbsp;=&nbsp;RJ&nbsp;=&nbsp;I<\/i>\nand therefore <i>R&sup2;&nbsp;=&nbsp;I<\/i>.\nBut clearly rotating clockwise twice is not the identity\nfor&nbsp;<i>n<\/i>&nbsp;&ge;&nbsp;2.\n(Rotating clockwise twice is turning upside-down.)\n<\/p>\n<p>\nA more mechanical way to see this is to take the equation\n<i>R&nbsp;=&nbsp;J<\/i> and show that <i>J<\/i>\ndoes not perform the desired operation;\njust try it on the matrix with 1 in the upper left entry and 0&#8217;s everywhere\nelse.\n<\/p>\n<p>\nAnd since it&#8217;s one of those geeky math pastimes to see\n<a HREF=\"http:\/\/blogs.msdn.com\/matthew_van_eerde\/archive\/2008\/09\/12\/rotating-a-matrix-redux.aspx\">\nhow many differents proofs you can come up with for a single result<\/a>,\nthe third way to show that rotation cannot be effected by\nmatrix multiplication is to observe that the transformation is not linear.\n(That&#8217;s the magical algebra-theoretical way of showing it,\nwhich is either <i>so obvious you can tell just by looking at it<\/i>\nor\n<i>so obscure it defies comprehension<\/i>.)\n[The transformation viewed as a transformation on matrices rather\nthan a transformation on column vectors is indeed linear,\nbut the matrix for that would be an <i>n&sup2;&nbsp;&times;&nbsp;n&sup2;<\/i>\nmatrix, and the operation wouldn&#8217;t be matrix multiplication,\nso that doesn&#8217;t help us here.]\n<\/p>\n<p>The last question raised by this exercise was\n<a HREF=\"http:\/\/beta.stackoverflow.com\/questions\/42519\/how-do-you-rotate-a-two-dimensional-array\">\nwhether you could do better than <i>O<\/i>(<i>n<\/i>&sup2;)<\/a>.\nComputer science students spend so much time trying to push the\ncomplexity of an algorithm down\nthat they neglect to learn how to tell that you can&#8217;t go any lower.\nIn this case, you obviously can&#8217;t do better than <i>O<\/i>(<i>n<\/i>&sup2;)\nbecause every single one of the <i>n<\/i>&sup2; entries in the array\nneeds to move (except of course the center element if <i>n<\/i>&nbsp;is odd).\nIf you did less than <i>O<\/i>(<i>n<\/i>&sup2;) of work,\nthen for sufficiently large&nbsp;<i>n<\/i>,\nyou will end up not moving some array elements, which would be a failure\nto complete the required operation.\n<\/p>\n<p>\n<b>Bonus chatter<\/b>:\nMind you, you can do better than\n<i>O<\/i>(<i>n<\/i>&sup2;) if you change the rules of the problem.\nFor example, if you allow <i>pretending<\/i> to move the elements,\nsay by overloading the <code>[]<\/code> operator,\nthen you can perform the rotation in\n<i>O<\/i>(1) time by just writing a wrapper:\n<\/p>\n<pre>\nstruct IArray\n{\n  virtual int&amp; Element(int x, int y) = 0;\n  virtual ~IArray() = 0;\n};\nclass RotatedArray : public IArray {\npublic:\n RotatedArray(IArray *p) : m_p(p) { }\n ~RotatedArray() { delete m_p; }\n int&amp; Element(int x, int y) {\n  return m_p-&gt;Element(y, x);\n }\nprivate:\n IArray *m_p;\n};\nvoid RotateInPlace(IArray *&amp; p, int N)\n{\n p = new RotatedArray(p);\n}\n<\/pre>\n<p>\nThis pseudo-rotates the elements by changing the accessor.\nCute but doesn&#8217;t actually address the original problem,\nwhich said that you were passed an array, not an interface\nthat simulates an array.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Some follow-up remarks to my old posting on rotating a two-dimensional array: Some people noticed that the article I linked to purporting to rotate the array actually transposes it. I was wondering how many people would pick up on that. I was surprised that people confused rotating an array (or matrix) with creating a rotation [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[26],"class_list":["post-15383","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>Some follow-up remarks to my old posting on rotating a two-dimensional array: Some people noticed that the article I linked to purporting to rotate the array actually transposes it. I was wondering how many people would pick up on that. I was surprised that people confused rotating an array (or matrix) with creating a rotation [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/15383","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=15383"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/15383\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=15383"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=15383"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=15383"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}