|
||||
Title: CS: ARRAY ROTATION Post by srowen on Aug 1st, 2002, 9:05am How about this solution? First, reverse the order of the elements in the whole list: {xn, xn-1, ..., x1} Then reverse the sublist containing the last k-1 elements, and then also the sublist containing the other n-k+1 elements: {xk, xk+1, ..., xn, x1, ..., xk-1} To illustrate rotating a list of n=5 elements so that k=4 is first: 1 2 3 4 5 reverse list: 5 4 3 2 1 break into sublists and reverse: 5 4 3 2 1 4 5 1 2 3 Each reversal is clearly O(n) and the swapping requires some small constant amount of storage. |
||||
Title: Re: CS: ARRAY ROTATION Post by -D- on Aug 1st, 2002, 10:59am Grrr... I was banging my head against the wall with mods and elements hopping around. This is like your string reversal answer... hrm... -D- |
||||
Title: Re: CS: ARRAY ROTATION Post by yosenl on Aug 2nd, 2002, 3:19am This problem can also be found in the book by 'Programming Pearls' by Jon Bentley, column 2. It is an excellent book about various facets of computer programming. |
||||
Title: Re: CS: ARRAY ROTATION Post by zameericle on Aug 5th, 2002, 3:23am how about: array: 0123456789 k: 5 you need a swap(i,k) function that can be done in O(1) memory as follows: i = i XOR k k = k XOR i i = i XOR k so to do the rotation the following code: int i=0; while( k < n ) { swap( a[i++], a[k++] ); } |
||||
Title: Re: CS: ARRAY ROTATION Post by srowen on Aug 5th, 2002, 5:48am This happens to work in the case where k = n/2, but try this for, say, k=6 here and you will not get the desired result. |
||||
Title: Re: CS: ARRAY ROTATION Post by zameericle on Aug 6th, 2002, 1:29am oops.. what happens if you change the beginning offset to k = n - k + 1; that should fix the problem. |
||||
Title: Re: CS: ARRAY ROTATION Post by S. Owen on Aug 6th, 2002, 5:30am Try k=4: 7 8 9 3 4 5 6 0 1 2 or k=8: 3 4 5 6 7 8 0 1 2 9 I don't believe that you can get the desired result along these lines. |
||||
Title: Re: CS: ARRAY ROTATION Post by zameericle on Aug 6th, 2002, 8:24am gah.. I give up!!! It's tough to get off a current train of thought once you're on it... |
||||
Title: Re: CS: ARRAY ROTATION Post by Paul Hsieh on Aug 6th, 2002, 10:00pm Hint: How long does it take to find the minimum element in this rotated list? |
||||
Title: Re: CS: ARRAY ROTATION Post by Paul Hsieh on Aug 6th, 2002, 10:46pm Whoops! Answering the wrong question! You have to differentiate the subjects a bit more I think. Anyhow, the solution to this is: Step 1: Compute S = gcd (k, n) (Euclid's algorithm, or Knuth's improvement -- whatever.) Step 2: Code:
Step 3: Code:
The idea is that you are just pushing the array entries to their correct position in the disjoint contiguous rings { x, f(x), f2(x), f3(x), f4(x), ... } and realizing that there are gcd(n,k) such rings for any given (n,k). There may be a faster way, but this is the way that occurs to me. Now of course, you can argue that Step 1 alone is slower than O(n) (I don't know/remember if it is or not) by itself. So to work around that, you can modify Step 3, to sort of compute the gcd() on the fly by noting it, then when i==1, the lowest value of j not equal to i within the inner most loop, will be equal to the gcd itself. Hmmm ... if gcd() were slower than O(n), then the above described algorithm would be a faster way of computing it ... which is not bloody likely. So just ignore that comment ... I assert that the Knuth algorithm for figuring out gcd(n, k) is at worst O(n) ;D. |
||||
Title: Re: CS: ARRAY ROTATION Post by NoNamePlease on Nov 24th, 2003, 4:27pm I think Paul Hsieh gave a similar solution, but this seems easier (Perl): Code:
|
||||
Title: Re: CS: ARRAY ROTATION Post by grimbal on May 25th, 2004, 4:51pm on 08/06/02 at 05:30:18, S. Owen wrote:
What about this: void rot(int a[], int n, int k){ int i; k = n-k; for( i = n-1 ; k<n ; i-- ){ int tmp = a[i]; a[i] = a[i-k]; a[i-k] = tmp; if( i==k ){ k = k - n%k; n = i; } } } [corrected BAD code] |
||||
Title: Re: CS: ARRAY ROTATION Post by Leonid Broukhis on May 26th, 2004, 4:21pm on 05/25/04 at 16:51:51, grimbal wrote:
This is BAD. There are two assignments to a[ i ] without a sequence point which means the result is undefined. |
||||
Title: Re: CS: ARRAY ROTATION Post by grimbal on May 26th, 2004, 7:34pm Well, it could have been worse: Code:
;D Regarding the x ^= y ^= x ^= y, I know it is bad. I just wanted to make the code as succint as possible. Every serious C programmer will recognize a swap. :) It is bad because it does unnecessary operations. It is also undefined for C, because there are no sequence points to guarantee the order of the assignations. But I read somewhere that this might be changed in a coming revision of the C Standard. It would show that it is not the program that is wrong, but the C language. ;) |
||||
Title: Re: CS: ARRAY ROTATION Post by grimbal on May 28th, 2004, 7:52am Same idea, a little simpler Code:
|
||||
Title: Re: CS: ARRAY ROTATION Post by Aryabhatta on Sep 8th, 2004, 8:22am This is similar to Paul Hsieh's solution without the need for computing the gcd of (n,k). Basically the permutation is f(i) = i + k (mod n) The permutation is composed of rings. Each ring has a min element called the seed. One property of this set of seeds is: Start following the ring for each seed in ascending order of their values. If we just completed the ring of the seed of value i and not all elements of the array have been touched, then i+1 is the next seed. I don't remember where I read this. I guess the proof of this should not be very difficult. |
||||
Powered by YaBB 1 Gold - SP 1.4! Forum software copyright © 2000-2004 Yet another Bulletin Board |