Sword는 질문 21- 홀수 책이 짝수 앞에 오도록 배열 순서를 조정합니다.

홀수 책이 짝수 앞에 오도록 배열 순서를 조정하십시오.

이야기

정수 배열을 입력하고 배열의 숫자 순서를 조정하는 함수를 구현하여 모든 개수가 배열의 전반부에 있고 모든 짝수는 배열의 후반부에 있도록합니다.

초기 분석

가장 쉬운 방법은 물론 처음부터 배열을 스캔하는 것이며, 짝수를 만날 때마다 숫자가 끝에 배치됩니다. 즉, 숫자 뒤의 숫자는 앞으로 이동해야합니다.
짝수를 만날 때마다 O (n) 숫자가 이동되기 때문에 총 시간 복잡도는 O (n ^ 2)입니다.

더 좋은 방법

배열에는 홀수 또는 짝수의 두 가지 유형의 숫자 ​​만 있기 때문입니다. 따라서 홀수 앞에 짝수가 나타날 때마다 순서를 바꿔도 괜찮습니까?

따라서 두 개의 포인터를 유지해야합니다.
초기화 될 때 첫 번째 숫자를 가리키는 첫 번째 포인터는 뒤로 만 이동할 수 있습니다.
두 번째 포인터는 초기화 될 때 마지막 숫자를 가리키며 앞으로 만 이동할 수 있습니다.

두 포인터가 만나기 전에 첫 번째 포인터가 짝수이고 두 번째 포인터가 홀수이면 위치를 바꿉니다.

예를 들면

입력 배열 : {1, 2, 3, 4, 5}

프로세스 :
1. 처음에 첫 번째 포인터는 1을 가리키고 두 번째 포인터는 5를 가리 킵니다
. 2. 1은 홀수이므로 첫 번째 포인터는 짝수 2를 가리킬 때까지 뒤로 이동합니다.
3. 이때 두 번째 포인터가 5를 가리키고 있기 때문에 서로 바꾼다.
4. 그런 다음 두 사람이 만날 때까지 계속

그림 :
여기에 사진 설명 삽입
따라서 다음 코드를 얻을 수 있습니다.

void ReorderOddEven(int* pData,unsigned int length)
{
    
    
	if(pData==nullptr || length==0)
		return;
	int* pBegin=pData;
	int* pEnd=pData+length+1;
	
	while(pBegin<pEnd)
	{
    
    
		//向后移动pBegin 直到它指向偶数
		while(pBegin<pEnd && (*pBegin & 0x1)!=0)
			pBegin++;
		//向前移动pEnd 直到指向奇数
		while(pBegin<pEnd && (*pEnd & 0x1)==0)
			pEnd--;
		if(pBegin<pEnd)
		{
    
    
			int temp=*pBegin;
			*pBegin=*pEnd;
			*pEnd=tmp;
		}
	}
}

확장 모듈 식 처리

위의 문제는 해결되고 완벽 해 보이지만 비슷한 문제가 있으면 어떨까요?

질문 : 배열이 양수와 음수 두 부분으로 나뉘고 음수가 음수가 아닌 수 앞에있는 경우 처리 방법은 무엇입니까?
A : 새 기능을 재정의하려면 다음의 판단 조건 만 변경하면됩니다. 두 번째 및 세 번째 while 루프.

다른 질문을합니다. 두 부분으로 나뉘면 한 부분은 3으로 나눌 수 있고 앞 부분은 3으로 나눌 수없고 뒷 부분은 어떻게 되나요?
다시 대답하십시오. 또는 새 기능을 재정의하고 다시 변경하십시오 ... 인터럽트 : 중지하고 중지하십시오. 더 좋은 방법이 없습니까?

위의 질문을 보면 답이 틀리지 않으니 조건 만 바꾸면됩니다.
그러나 위이다, 잘못 만을

변경해야 할 판단 조건 일 뿐인데 왜 매번 같은 코드를 반복해야하나요?
나머지 코드를 재사용 할 수 없도록 판단해야하는 조건을 캡슐화하지 않는 이유는 무엇입니까?
맞습니다, 정식 질문자가 원했던 답입니다!

따라서 함수 포인터를 도입하고 위 코드를 논리와 연산의 두 부분으로 나누면됩니다. 이런 식으로 많은 계산을 반복하는 대신 매번 논리 함수를 다시 작성하면되고 재사용 성이 크게 향상됩니다.

void ReorderOddEven(int* pData,unsigned int length,bool (*func)(int))
{
    
    
	if(pData==nullptr || length==0)
		return;
	int* pBegin=pData;
	int* pEnd=pData+length+1;
	
	while(pBegin<pEnd)
	{
    
    
		//向后移动pBegin 直到它指向偶数
		while(pBegin<pEnd && !func(*pBegin))
			pBegin++;
		//向前移动pEnd 直到指向奇数
		while(pBegin<pEnd && func(*pEnd) )
			pEnd--;
		if(pBegin<pEnd)
		{
    
    
			int temp=*pBegin;
			*pBegin=*pEnd;
			*pEnd=tmp;
		}
	}
}

bool IsEven(int n)
{
    
    
	return (n&0x1)==0;
}

——————————————————————————————————————————— ————
참고서 : "Sword Finger Offer"

추천

출처blog.csdn.net/rjszz1314/article/details/104286378