면접 에서 흔히 볼 수 있 는 링크 문제 집합

링크 는 우리 가 프로 그래 밍 에서 자주 사용 하 는 데이터 구조 이 고 구조 가 간단 하기 때문에 면접 에서 링크 를 고찰 하 는 문제 가 자주 발생 한다. 다음은 면접 에서 흔히 볼 수 있 는 링크 에 관 한 문 제 를 살 펴 보 자.먼저 링크 의 데이터 구 조 를 알 아 보 겠 습 니 다. 주의: 코드 를 작성 할 때 경계 조건 에 대한 판단 을 기억 해 야 사고방식 의 엄밀 성 을 나 타 낼 수 있 습 니 다.
typedef struct ListNode
{
	int data;
	ListNode* next;
}ListNode;

1. 단일 체인 표 의 노드 의 개 수 를 계산한다.
int GetListLength(ListNode* pHead)
{
 	if(NULL==pHead)
	{
		return 0;
	 }

	 unsigned int nLength=0;
	ListNode* p=pHead;

	 while(p)
	{
		++nLength;

		 p=p->next;
	 }

	 return nLength;
}

2. 싱글 체인 시트 의 반전
하나의 노드 나 링크 만 비어 있 는 상황 을 판단 하고 인접 한 노드 의 next 지침 을 순환 적 으로 옮 겨 다 니 며 교환 하면 됩 니 다. 시간 복잡 도 는 O (n) 입 니 다.
ListNode* ListReverse(ListNode* pHead)
{
	if(NULL==pHead||NULL==pHead->next)
	{
		 return pHead;
	}

	ListNode* p=pHead;
	ListNode* q=p->next;
	ListNode* r;
	while(q)
	{
		r=p->next;
		q->next=p;
		p=q;
		q=r;
	}
	pHead->next=NULL;
	pHead=p;

	return pHead;
}

3. 단일 체인 테이블 의 마지막 k 번 째 노드 찾기
이 문 제 는 먼저 링크 를 옮 겨 다 니 며 링크 의 길이 n 을 계산 한 다음 에 n - k 의 결점 을 찾 을 수 있 습 니 다.
우 리 는 또 거꾸로 생각 할 수 있다. 두 개의 지침, p, q 를 통 해.p 와 q 는 동시에 머리 결점 을 가리 키 고 p 지침 은 먼저 k 보 를 간 다음 에 p 와 q 가 함께 간다. 이렇게 p 는 n - k 보 를 걸 어서 링크 의 끝 에 도착 하고 q 는 n - k 의 결점, 즉 마지막 k 의 결점, 시간 복잡 도 는 O (n) 보다 작다. 주의: 임계 상황 의 판단.
ListNode* GetRkNode(ListNode* pHead,unsigned int k)
{
	 if(k==0||NULL==pHead)
	{
		 return NULL;
	}
	
	ListNode* p=pHead;
	ListNode* q=pHead;

	 unsigned int i;
	 while (q)
	{
		++i;

		 if(i==k)
		 {
			break;
		}

		q=q->next;
	 }

	 if(inext;
		q=q->next;
 	}

	 return p;
}

4. 단일 체인 테이블 의 중간 지점 찾기
이 문 제 는 두 개의 지침 을 사용 하 는 방식 이다. 첫 번 째 지침 은 매번 2 보 를 걷 고 두 번 째 지침 은 매번 1 보 를 걷는다. 첫 번 째 지침 이 링크 의 끝 에 도착 하면 두 번 째 지침 은 중간 노드 에 딱 도착한다.
ListNode* GetMidNode(ListNode* pHead)
{

	if(NULL==pHead||NULL==pHead->next)
	{
		return pHead;
	}

	ListNode* p=pHead;
	ListNode* q=pHead;

	while (p)
	{
		p=p->next->next;
		q=q->next;
	}

	return q;
}

5. 끝 에서 끝까지 단일 체인 시트 인쇄
끝 에서 앞으로 단일 체인 표를 인쇄 하면 우 리 는 스 택 의 특성 을 빠르게 생각 할 수 있 습 니 다. 먼저 스 택 에 들 어가 서 마지막 으로 꺼 내 서 인쇄 할 수 있 습 니 다.
void RPrintfNode(ListNode* pHead)
{
	if(NULL==pHead)
	{
		return;
	}
	std::stack stackNode;

	while (pHead)
	{
		stackNode.push(pHead->data);
 		pHead=pHead->next;
	}

	 while(!stackNode.empty())
	{
		 int data=stackNode.top();

		 printf("%d",data);
		
		stackNode.pop();
	 }
}

6. 이미 알 고 있 는 두 개의 단일 체인 표 는 어 릴 때 부터 큰 순서 로 그들 을 합병 한 후에 도 질서 가 있다 (체인 표 의 병합 정렬).
먼저 임계 조건 의 판단 에 주의해 야 한다. 하나의 링크 가 끝 에 도착 할 때 까지 비교 링크 를 옮 겨 다 니 고 남 은 빈 노드 를 새로운 링크 꼬리 에 추가 하면 된다. 원시 적 인 공간 을 이용 해 야 한다.
ListNode* MergeList(ListNode* pHead1,ListNode* pHead2)
{
	if(NULL==pHead1)
	{
		return pHead2;
	}
	if(NULL==pHead2)
	{
		return pHead1;
	}
	if(NULL==pHead1&&NULL==pHead2)
	{
		return NULL;
	}

	ListNode* p=pHead1;
	ListNode* q=pHead2;
	ListNode* pNewNode=NULL;
	ListNode* pHead;

	while(p!=NULL&&q!=NULL)
	{
		if(p->data>q->data)
		{

			if(pNewNode==NULL)
			{
				pNewNode=q;
				pHead=q;
				q=q->next;
			}
			else
			{
				pNewNode->next=q;
				pNewNode=q;
				q=q->next;
			}
		}
		else 
		{
			if(pNewNode==NULL)
			{
				pNewNode=p;
				pHead=p;
				p=p->next;
			}
			else
			{
				pNewNode->next=p;
				pNewNode=p;
				p=p->next;
			}
		}
	}

	if(p!=NULL)
	{
		pNewNode->next=p;
	}
	if(q!=NULL)
	{
		pNewNode->next=q;
	}

	return pHead;
}

7. 하나의 링크 에 고리 가 있 는 지 판단 합 니 다.
만약 에 링크 에 고리 가 존재 한다 면 두 개의 지침 을 사용 하여 첫 번 째 로 1 번 을 걸 을 수 있 고 두 번 째 는 2 걸음 을 걸 을 수 있 으 며 두 개의 지침 이 만나면 고리 가 존재 할 것 이다.
bool IsExitLoop(ListNode* pHead)
{
	if(NULL==pHead)
	{
		return false;
	}

	ListNode* p=pHead;
	ListNode* q=pHead;

	while(p!=NULL&&q->next!=NULL)
	{
		p=p->next;
		q=q->next->next;

		if(p==q)
		{
			return true;
		}
	}

	return false;
}

8. 두 개의 단일 체인 표 가 교차 하 는 지 판단 한다.
주의: 만약 에 두 개의 링크 가 교차 하면 두 개의 링크 의 꼬리 노드 가 똑 같 을 것 이 므 로 두 개의 링크 의 꼬리 노드 가 똑 같은 지 판단 하면 됩 니 다.
bool IsIntersect(ListNode* pHead1,ListNode* pHead2)
{
	if(NULL==pHead1||NULL==pHead2)
	{
		return false;
	}

	while (pHead1->next!=NULL)
	{
		pHead1=pHead1->next;
	}

	while(pHead2->next!=NULL)
	{
		pHead2=pHead2->next;
	}

	if(pHead1==pHead2)
	{
		return true;
	}

	return false;
}

9. 단일 체인 표 가 교차 하 는 첫 번 째 교점 을 구한다.
단일 체인 표 가 교차 하 는 교점 을 구 합 니 다. 우 리 는 주로 두 개의 체인 표 의 길 이 를 모 릅 니 다. 체인 표 1 의 길 이 는 length 1 이 고 체인 표 2 의 길 이 는 length 2 라 고 가정 합 니 다. 만약 에 length 1 > length 2 라면 체인 표 1 을 먼저 length 1 - length 2 단계 로 가게 하고 체인 표 2 를 처음부터 함께 걷 게 하면 그들 이 같 으 면 만 나 는 노드 입 니 다.
ListNode* GetFirstIntersect(ListNode* pHead1,ListNode* pHead2)
{
	if(pHead1==NULL||pHead2==NULL)
	{
		return NULL;
	}

	unsigned int length1=0,length2=0;

	ListNode* p=pHead1;
	ListNode* q=pHead2;

	while(p->next!=NULL)
	{
		p=p->next;
		++length1;
	}

	while(q->next!=NULL)
	{
		q=q->next;
		++length2;
	}

	if(p!=q)
	{
		return NULL;
	}
	p=pHead1;
	q=pHead2;

	if(length1>length2)
	{
		p=pHead1;

		unsigned int k=length1-length2;

		while(k)
		{
			p=p->next;
			k--;
		}
	}
	else
	{
		q=pHead2;

		unsigned int k=length2-length1;

		while(k)
		{
			q=q->next;
			k--;
		}
	}

	while(p==q)
	{
		p=p->next;
		q=q->next;

		return p;
	}

	return NULL;
}

10. 이미 알 고 있 는 단일 체인 표 에 링 이 존재 하 므 로 링 의 첫 번 째 노드 에 들 어가 야 합 니 다.
단일 체인 테이블 에 존재 하 는 고 리 는 위 에서 소개 한 방법 을 통 해 판단 할 수 있 습 니 다. 두 개의 바늘, 하나의 느 린 바늘 p, 하나의 빠 른 바늘 q, p 는 매번 한 걸음 씩 걷 고 q 는 매번 두 걸음 씩 걷 습 니 다. p 와 q 가 만 났 을 때 체인 테이블 에 고리 가 존재 한 다 는 것 을 설명 합 니 다.
만 나 는 노드 pNode 를 기록 한 다음 에 체인 헤드 포인터 와 pNode 에서 한 걸음 씩 걸 을 때마다 두 포인터 가 만 날 때 바로 링 의 입구 점 입 니 다.
4. 567913. 10 번 문제 의 증명 은 다음 과 같다.
pfast 가 pslow 와 만 났 을 때 pslow 는 링크 를 다 훑 어보 지 않 았 을 것 입 니 다. pfast 는 링 안에서 n 링 (1 < = n) 을 순환 하 였 습 니 다.pslow 가 s 보 를 걸 었 다 고 가정 하면 pfast 는 2s 보 (pfast 보 수 는 s 와 링 에 많이 돌아 가 는 n 권) 를 걸 었 고 링 의 길 이 를 r 로 설정 하면:
2s = s + nr s = nr 는 전체 링크 길이 L 을 설정 하고 입구 고리 와 만 남 점 거 리 는 x 이 며 출발점 에서 링 입구 점 까지 의 거 리 는 a 이다.  
 a + x = nr 는 a + x = (n – 1) r + r = (n - 1) r + L - a = (n - 1) r + (L – a – x)
(L – a – x) 는 만 남 점 에서 링 입구 점 까지 의 거 리 를 알 수 있 습 니 다. 이 를 통 해 알 수 있 듯 이 링크 헤드 에서 링 입구 점 까지 는 (n - 1) 순환 내부 고리 + 만 남 점 에서 링 입구 점 까지 입 니 다. 그래서 우 리 는 체인 헤드, 만 남 점 에서 각각 지침 을 설정 하고 한 걸음 씩 걸 을 때마다 두 개의 지침 이 반드시 만 나 고 만 남 의 첫 번 째 점 은 링 입구 점 입 니 다.
요약: 링크 는 면접 에서 자주 등장 하 는 면접 문제 로 기초 지식의 육성 을 중시 하고 흔히 볼 수 있 는 문 제 를 잘 알 면 능숙 해 질 것 이다.시간 관계 로 인해 상기 코드 는 테스트 사례 를 하지 않 았 습 니 다. 만약 에 오류 가 있 으 면 독자 의 지적 을 바 랍 니 다. 그리고 많이 포함 되 어 있 습 니 다.

좋은 웹페이지 즐겨찾기