검지 offer 알고리즘 문제
23618 단어 剑指offer
제목 1: 체인 테이블을 처음부터 끝까지 인쇄
제목 설명은 체인 테이블을 입력하고 끝에서 끝까지 체인 테이블의 각 노드의 값을 출력합니다.
사고방식 1: 귀속은head->next==NULL일 때 귀속을 중지하고 상부로 돌아가며 현재 노드 값을vector에 눌러 넣는다.마지막으로vect 전체를 되돌려줍니다.
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> res;
if(head!=NULL){
res = printListFromTailToHead(head->next);
res.push_back(head->val);
}
return res;
}
};
단점: 체인 테이블이 매우 길면 함수 호출의 층수가 깊어져 창고가 넘칠 수 있습니다.
사고방식 2: 비귀속
vector를 사용하면 흐르는 값이vector의 첫 부분에 놓입니다.
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> ret;
while(head != nullptr)
{
ret.insert(ret.begin(),head->val);
head = head->next;
}
return ret;
}
};
단점:vector 머리에 데이터를 삽입할 때마다 함수 실행 효율이 낮음
사고방식 3:vector 정방향 저장소를 사용하고reverse
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> ret;
while(head != nullptr)
{
ret.push_back(head->val);
head = head->next;
}
reverse(ret.begin(),ret.end());
return ret;
}
};
사고방식 4: 창고를 보조로 하고 첫 번째 경험을 통해 값을 창고에 눌러 넣고 전체 체인 테이블을 모두 눌러 넣은 후에 창고 꼭대기에서 노드의 값을 하나씩 출력한다.
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> res;
stack<int> temp;
ListNode* p=head;
while(p){
temp.push(p->val);
p = p->next;
}
while(!temp.empty()){
res.push_back(temp.top());
temp.pop();
}
return res;
}
};
제목 2: 체인 테이블 중 꼴찌 k번째 결점
제목 설명은 체인 테이블을 입력하여 이 체인 테이블의 꼴찌 k번째 결점을 출력합니다.
사고방식1:stack을 사용하여 모든 노드를 저장하고 k-1개를 출력합니다. 이때 창고 꼭대기에 있는 것이 바로 k번째
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(pListHead==NULL||k<=0)
return NULL;
stack temp;
ListNode* p=pListHead;
while(p!=NULL){
temp.push(p);
p=p->next;
}
if(temp.size()return NULL;
for(int i=0; i1; i++){
temp.pop();
}
return temp.top();
}
};
단점: 공간의 복잡도가 너무 높아 창고가 넘칠 수 있다.
사고방식 2: 두 개의 바늘을 먼저 첫 번째 바늘과 두 번째 바늘이 모두 머리 결점을 가리키게 한 다음에 첫 번째 손가락이 바로 (k-1)걸음을 해서 두 번째 k노드에 도달하게 한다.그리고 두 개의 바늘이 동시에 뒤로 이동한다. 첫 번째 결점이 끝에 도착했을 때 두 번째 결점이 있는 위치는 바로 꼴찌 k번째 노드이다.
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
if(pListHead == NULL || k <= 0)
return NULL;
ListNode* p=pListHead;
ListNode* q=pListHead;
for(int i=0;i<k-1;i++){
if(q->next != NULL) // k
q = q->next;
else
return NULL;
}
while(q->next != NULL){
p = p->next;
q = q->next;
}
return p;
}
};
제목 3: 체인 테이블 반전
제목은 체인 테이블을 입력하고 체인 테이블을 반전시킨 후 체인 테이블의 모든 요소를 출력하는 것을 설명합니다.
사고방식 1:stack을 새로 만들고 stack에 따라 창고를 열고 새 체인 테이블을 만듭니다.
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead == NULL || pHead->next == NULL)
return pHead;
ListNode* pNew;
stack temp;
ListNode* p=pHead;
while(p->next!=NULL){
temp.push(p);
p = p->next;
}
pNew = p;
while(!temp.empty()){
p->next = temp.top();
p = p->next;
temp.pop();
}
p->next = NULL;
return pNew;
}
};
방법 2: 세 개의 바늘이 동시에 미끄러진다. 첫 번째는 새로운 서열의 머리이고, 두 번째는 원래의 서열의 머리이며, 세 번째는 원래의 서열 머리의next
A->B->C->D->E->F(1)PB= A P = B PC = C(2) AD->E->F PB= B P = C PA = D(3)AE->F PB= C P = D PA = E...(N)ANULL PB = E P = F PA = NULL 종료 순환 P->next = PB PHead(A)->next = NULL NULL
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if(pHead == NULL || pHead->next == NULL)
return pHead;
ListNode *pBefore = pHead, *p = pHead->next, *pAfter = p->next;
while (pAfter) {
p->next = pBefore;
pBefore = p;
p = pAfter;
pAfter = pAfter->next;
}
p->next = pBefore;
pHead->next = NULL;
return p;
}
};
제목 4: 체인 테이블에서 중복된 결점 삭제
제목은 정렬된 체인 테이블에 중복된 결점이 있음을 설명합니다. 이 체인 테이블에서 중복된 결점을 삭제하십시오. 중복된 결점은 보존되지 않고 체인 헤더 바늘로 돌아갑니다.예를 들어 체인 테이블 1->2->3->3->4->4->5 처리 후 1->2->5
사고방식 1: 귀속
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead)
{
if(pHead==NULL || pHead->next==NULL)
return pHead;
ListNode* current;
if(pHead->val == pHead->next->val){
current = pHead->next->next;
while(pHead->val == current->val && current != NULL)
current = current->next;
return deleteDuplication(current);
}
else{
current = pHead->next;
pHead->next = deleteDuplication(current);
return pHead;
}
}
};
사고방식 2: 비귀속
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead)
{
if(pHead==NULL || pHead->next==NULL)
return pHead;
ListNode* newHead = new ListNode(-1); // , -1
newHead->next = pHead;
ListNode* pre = newHead;
ListNode* p = pHead;
ListNode* pNext = p->next;
while(p!=NULL && p->next!=NULL){
pNext=p->next;
if(p->val == pNext->val){
while(pNext!=NULL && pNext->val==p->val)
pNext = pNext->next;
pre->next = pNext; // ,pre ,
p = pNext;
}
else{ // , pre ,
pre = p;
p = p->next;
}
}
return newHead->next;
}
};
제목 5: 두 개의 정렬된 체인 테이블 병합
제목은 두 개의 단조롭고 점차적으로 증가하는 체인표를 입력하고 두 개의 체인표가 합성된 체인표를 출력하는 것을 묘사한다. 물론 우리는 합성된 체인표가 단조롭고 줄지 않는 규칙을 만족시켜야 한다.
사고방식
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(!pHead1 && !pHead2)
return NULL;
// ,
if(!pHead1 || !pHead2)
return(pHead1 == NULL)? pHead2:pHead1;
ListNode* pNew;
if(pHead1->val <= pHead2->val){
pNew = pHead1;
pNew->next = Merge(pHead1->next,pHead2);
}
else{
pNew = pHead2;
pNew->next = Merge(pHead1,pHead2->next);
}
return pNew;
}
};
사고방식 2: 비귀속
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
if(!pHead1 && !pHead2)
return NULL;
if(!pHead1 || !pHead2)
return(pHead1 == NULL)? pHead2:pHead1;
ListNode* pNew; //
if(pHead1->val<=pHead2->val){
pNew=pHead1;
pHead1=pHead1->next;
}
else{
pNew=pHead2;
pHead2=pHead2->next;
}
ListNode* p = pNew; //
while(pHead1 && pHead2){ //
if(pHead1->val < pHead2->val){
p->next = pHead1;
pHead1 = pHead1->next;
p = p->next;
}
else{
p->next = pHead2;
pHead2 = pHead2->next;
p = p->next;
}
}
if(pHead1 == NULL) // 1
p->next = pHead2;
if(pHead2 == NULL) // 2
p->next = pHead1;
return pNew;
}
};
제목 6: 복잡한 체인 테이블의 복제
제목 설명은 복잡한 체인 테이블 (각 노드에 노드 값과 두 개의 바늘이 있는데, 하나는 다음 노드를 가리키고, 다른 하나는 특수한 바늘이 임의의 노드를 가리킨다) 을 입력하고, 결과는 복사된 복잡한 체인 테이블의head로 되돌아옵니다.(출력 결과에서 매개 변수의 노드 인용을 되돌려 주지 마십시오. 그렇지 않으면 판정 프로그램이 비어 있습니다.)
문제 풀이 사고방식(1) 낡은 체인 테이블(예를 들어 A-B-C-D)에서 새 체인 테이블(A-A'-B'-C'-D')을 만들 때 새 체인 테이블의 특수 지침을 처리하지 않습니다.(2) 낡은 체인 시계의 특수 바늘에 따라 새로운 체인 시계의 특수 바늘을 복제한다.(3) 새 체인 테이블에서 복제 체인 테이블을 분리합니다.
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
RandomListNode* Clone(RandomListNode* pHead)
{
if(!pHead)
return NULL;
// , ,A-A'-B-B'-C-C'-D-D'
RandomListNode *currNode = pHead; //curr = A
while(currNode){
RandomListNode *node = new RandomListNode(currNode->label); // A'
node->next = currNode->next; //A'->B
currNode->next = node; //A->A'
currNode = node->next; //curr = B ...... NULL
}
// , random
currNode = pHead;
while(currNode){
RandomListNode *node = currNode->next;
if(currNode->random){
node->random = currNode->random->next;
}
currNode = node->next;
}
// ,
RandomListNode *pCloneHead = pHead->next;
RandomListNode *tmp;
currNode = pHead;
while(currNode->next){
tmp = currNode->next;
currNode->next = tmp->next;
currNode = tmp;
} // ,A->next = B; ,A'->next = B';
return pCloneHead;
}
};
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
검지 offer 알고리즘 문제제목 설명은 체인 테이블을 입력하고 끝에서 끝까지 체인 테이블의 각 노드의 값을 출력합니다. 사고방식 4: 창고를 보조로 하고 첫 번째 경험을 통해 값을 창고에 눌러 넣고 전체 체인 테이블을 모두 눌러 넣은 후에 창...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.