[Sword Finger Offer]-Adjust the position of odd and even numbers in the array

1. The adjustment position does not need to change relative position

Topic requirements

Enter an array of integers and implement a function to adjust the order of the numbers in the array so that all odd numbers are in the first half of the array and all even numbers are in the second half of the array.

Topic analysis

1. Version one
First of all, when we get this question, we will immediately pop up an idea to scan the array from scratch. Whenever an even number is encountered, take out this number, and move all the digits behind this number one bit forward, then the end position of the array is vacated, and then insert the even number to the end of the array. But this line of thinking is still insufficient. Because the time complexity of this operation is O (n ^ 2).
2. Version 2
We can adopt the exchange strategy to solve the problem. Let's take a concrete example to describe this method in detail. Let's take the array {1,2,3,4,5} to explain in detail.
We first maintain two pointers p1 and p2. When p1 is initialized, it points to the first number of the array. When p2 is initialized, it points to the last number of the array, as shown in the following figure:
Insert picture description here
To make p1 point to an even number, p2 points to an odd number Point to the position of the number. Therefore, p2 is an odd number 5 points without moving, moving forward when p1 p1 point number 2, two digital switching
Insert picture description here
moved backward pointer p1, until he points even number 4, the pointer p2 move forward until he points odd integer
Insert picture description here
which At this time, since p2 has moved to the front of p1, it indicates that all the odd numbers are in front of the even numbers, and the program ends.
The key to summing up the above process is that when p1 points to an even number, and p1 points to an odd number, the number exchange position pointed by the two pointers; the condition for the end of the program is that the p2 pointer is in front of the p1 pointer.

Based on the above analysis, we can write our code as follows:

void ReorderOddEvent(int* pData, unsigned int length)
{
	if (pData == nullptr || length <= 0)
		return;

	int* p1 = pData;
	int* p2 = pData + length - 1;

	while (p1 < p2)
	{
		//向后移动p1,直至他指向偶数
		while (p1 < p2 && (*p1 & 0x1) != 0)
			p1++;
		
		//向前移动p2,直至他指向奇数
		while (p1 < p2 && (*p2 & 0x1) == 0)
			p2--;

		if (p1 < p2)
		{
			int temp = *p1;
			*p1 = *p2;
			*p2 = temp;
		}
	}
}

3. Version three
The method of version two above has solved the problem required in the problem. So if you want you to realize that all negative numbers in the array are in front of non-negative numbers, what should you do when the number that can be divided by 3 is in front of the number that cannot be divided by 3? If you just want to change the two while conditions in the above code, it's a bit wrong.
In fact, the above code is not extensible. We can give a model in which we can easily extend existing solutions to problems of the same type. Therefore, we can keep the large frame of the above code intact and decouple the entire function into two parts: one is to determine whether the number should be in the first half or the second half of the array, and the second is to split the array. Implement the judgment criteria with function pointers.

void Reorder(int* pData, unsigned int length,bool (*func)(int))
{
	if (pData == nullptr || length <= 0)
		return;

	int* p1 = pData;
	int* p2 = pData + length - 1;

	while (p1 < p2)
	{
		//向后移动p1,直至他指向偶数
		while (p1 < p2 && !func(*p1))
			p1++;

		//向前移动p2,直至他指向奇数
		while (p1 < p2 && func(*p2))
			p2--;

		if (p1 < p2)
		{
			int temp = *p1;
			*p1 = *p2;
			*p2 = temp;
		}
	}
}
bool isEven(int n)
{
	return (n & 0x01) == 0;
}
void ReorderOddEven(int* pData, unsigned int length)
{
	Reorder(pData, length, isEven);
}

The benefit of decoupling is improved code reuse.

2. Adjusting the position requires the relative position to remain unchanged

Topic requirements

Enter an array of integers and implement a function to adjust the order of the numbers in the array so that all odd numbers are in the first half of the array, all even numbers are in the second half of the array, and the odd and odd numbers are guaranteed to be relative The location is unchanged.

Topic analysis

Different from the previous question, the relative position of the changed array is required to be unchanged, that is to say, the array {1,2,3,4,5} is {1,3,5,2,4} after moving Instead of just {1, 5, 3, 4, 2}.

At this time, we can consider another space, create a new array, first put the odd push in the original array and then even push in, and then overwrite the original array with the new array data. We use a vector container to achieve, it will be more convenient. Such time complexity is O (n).
The code is implemented as follows:

void reOrderArray(vector<int> &array) {
         vector<int> res;
    for (int i = 0; i < array.size(); i++)
    {
        if (array[i] % 2 == 1)
        {
            res.push_back(array[i]);
        }
    }
    for (int i = 0; i < array.size(); i++)
    {
        if (array[i] % 2 == 0)
        {
            res.push_back(array[i]);
        }
    }
    array = res;
        
    }
Published 98 original articles · won praise 9 · views 3644

Guess you like

Origin blog.csdn.net/qq_43412060/article/details/105448917