Data Structure --- Rotate the elements of an array to the right by k bits

Recursion is a better solution, because you can think of it this way, finding a circular right shift of n elements by k bits can be decomposed into finding a circular right shift of one element by k bits and the rest

Rotate right by n-1 elements by k bits. So we can think like this, first move the element A1 by k bits to the corresponding position, but we need to use a storage space to store the value of the element at that position, then move the stored element to the corresponding position, and then store it again The value of that position, and so on, is illustrated as follows:


The order of the numbers explains the order of movement, that is, first move 1 to the corresponding position, then move 3 to the corresponding position, then move 5 to the corresponding position, and finally move 4 to the corresponding position.

But there is a special case to consider, that is, if An moves to the position of Am, and Am happens to move to the position of An, then the algorithm will fall into an infinite loop of moving these two elements. This situation should be avoided, assuming the above situation occurs. , then there is mn, which is k (mn is the distance to move to the right, that is, k), which is exactly equal to (arrsize-1)-m+n+1 (the distance that Am needs to move to An), which is as follows:

k = m - n

m-n = arrsize-1-m+n+1

Get k=arrsize/2, (the steps are as follows: m - n = arrsize - m + n ----> 2m - 2n = arrsize ---> 2k = arrsize ---> k = arrsize/2)

That is, when the position shifted to the right is exactly half the length of the array, then the above situation will occur, for example:

1 2 3 4

To shift 2 bits to the right is the situation as described above. At this time, you only need to start from a[0] and go to a[size/2-1] (that is, the position of 2) in turn with the elements of the position shifted to the right. which is:

Swap 1 and 3, 2 and 4, we get:

3 4 1 2

The movement is completed. In addition, it should be reminded that if arrsize is not an even number, k has a fractional part, and the number of steps we move is an integer, so if the length of the array is not the basis, then the above situation ( It means that Am moves to An, An moves Am, the same below) will not happen, in other words, the above will only happen when arrsize is even and half of it is exactly the number of steps to move (k). condition.

And it can be proved that if k!=arrsize/2, the above situation will not occur, and neither element will appear, then we can solve it recursively, the algorithm is as follows:

void MoveKsteps(int arr[], const int size, int curelem, int curloc, int n, int k)
{//arr is the array to be moved, size is the size of the array, and curloc is the element currently to be moved in the array
	//curloc is the current position of the element to be moved
	//n records the number of elements moved, k is the number to be shifted right
	using namespace stdioes;

	if (n == size)//elements have been swapped
	{
		return;
	}

	if (!(size % 2) && k == size / 2)
	{
		for (int i = 0; i <= size / 2 - 1; ++i)
		{
			Swap(arr[i], arr[(i + k) % size]);//Swap elements
		}
		return;//It's okay to omit
	}
	else
	{
		Swap(curelem, arr[(curloc = (curloc + k) % size)]);
		return MoveKsteps(arr, size, curelem, curloc, ++n, k);//The return here is also
	}
}

void Swap(int &a, int &b)
{//Swap the values ​​of elements a and b
	a = a + b;
	b = a - b;
	a = a - b;
}

Algorithm complexity analysis: Analyzing the algorithm, it can be seen that the algorithm mainly has two loops, one is the loop of boundary condition processing, which involves the exchange of elements, the number of loops is n/2, and the second loop is a recursive loop, because this is A one-way recursion (that is, the recursion has no branches and no backtracking), the exit of the recursion is n=size, the main task of the recursion is to exchange the value of the element, the complexity of the algorithm is O(1), so the time of the entire recursive algorithm is complicated The degree is O(n).

Below is the entire program, including the test main function.

 
 
#include<iomanip>//Control the output format
#include<iostream>
#define OVERFLOW -1//Failed to dynamically allocate memory
namespace stdioes //Commonly used identifiers, where ioes is the first letter of several identifiers
{
	using std::cout;
	using std::endl;
	using std::cin;
	using std::setw;
}

void MoveKsteps(int arr[], const int size, int curelem, int curloc, int n, int k);
void Swap(int &a, int &b);
intmain()
{
	// The size of the array, the elements of the array, and the size of the right shift.
	using namespace stdioes;
	int *arr, size, k;
	
	cout << "input the size of array:\n";
	cin >> size;
	cout << "input the k:\n";
	cin >> k;
	cout << "input the elemments of array:\n";
	arr = new int[size];
	if (!arr)
	{
		exit(OVERFLOW);
	}
	
	for (int i = 0; i < size; ++i)
	{
		cin >> arr[i];
	}
	cout << "Before moved:\n";
	for (int i = 0; i < size; ++i)
	{
		cout.setf(std::ios_base::left);
		cout << setw(3) << arr[i];
	}
	cout << endl;

	MoveKsteps(arr, size, arr[0], 0, 0, k);
	cout << "After moved:\n";
	for (int i = 0; i < size; ++i)
	{
		cout.setf(std::ios_base::left);
		cout << setw(3) << arr[i];
	}
	cout << endl;

    return 0;
}

void MoveKsteps(int arr[], const int size, int curelem, int curloc, int n, int k)
{//arr is the array to be moved, size is the size of the array, and curloc is the element currently to be moved in the array
	//curloc is the current position of the element to be moved
	//n records the number of elements moved, k is the number to be shifted right
	using namespace stdioes;

	if (n == size)//elements have been swapped
	{
		return;
	}

	if (!(size % 2) && k == size / 2)
	{
		for (int i = 0; i <= size / 2 - 1; ++i)
		{
			Swap(arr[i], arr[(i + k) % size]);//Swap elements
		}
		return;
	}
	else
	{
		Swap(curelem, arr[(curloc = (curloc + k) % size)]);
		return MoveKsteps(arr, size, curelem, curloc, ++n, k);
	}
}

void Swap(int &a, int &b)
{//Swap the values ​​of elements a and b
	a = a + b;
	b = a - b;
	a = a - b;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324525622&siteId=291194637