DS_2019_5_8(链表面试题)

钟表,可以回到起点,却已不是昨天; 日历,撕下一页简单,把我一天很难.
若是美好,叫做精彩;若是槽糕,叫做经历. 缘分万千,顺其自然;以心换心,才能永远!

链表面试题(C版本)

#include <stdio.h>
#include <stdlib.h>
#pragma once
在这里插入图片描述

1. 删除链表中等于给定值 val 的所有结点。
示例 :
输入 : 1->2->6->3->4->5->6, val = 6
输出 : 1->2->3->4->5

解题思路

  • (1)遍历链表中的所有结点
  • (2)如果结点的val不是要删除的val,就把这个结点尾插到新的链表上

解法一

struct ListNode* removeElements(struct ListNode* head, int val){
	struct ListNode* result = NULL;
	struct ListNode* last = NULL;        //记录result的最后一个结点
	struct ListNode* node = head;
	while (node != NULL){
		struct ListNode* next = node->next;
		if (node->val != val){
			//尾插到result这个链表上

			//结果链表为空链表
			if (result == NULL){
				result = node;
				last = node;
			}
			else{
				last->next = node;
				//更新下最后一个结点
				last = node;
			}
		}
		else{
			//删除节点,先不考虑

		}
		node = next;
	}
	if (last != NULL){
		last->next = NULL;
	}
	return result;
}

解法二

输入 : 2->2->3->1->2->1->2->NULL, val = 2
输出 : 3->1->1->NULL

typedef struct ListNode Node;
struct ListNode* removeElements(struct ListNode* head, int val){
    if (NULL==head){
	return NULL;
    }
    Node* pPre = NULL;
    Node* pCur = head;
    while (pCur){
	    if (val == pCur->val){
		    if (NULL == pPre){
			    //删除第一个结点
			    head = pCur->next;
                free(pCur);
                pCur = head;
		    }
		    else{
			    pPre->next = pCur->next;
			    free(pCur);
			    pCur = pPre->next;
			    //非第一个结点
		    }
	    }
	    else{
		    pPre = pCur;
		    pCur = pCur->next;
	    }
    }
    return head;
}
2.反转一个单链表。 空间复杂度为o(1)
示例:
输入 : 1->2->3->4->5->Null
输出 : 5->4->3->2->1->Null

解法一:(建立三个指针)

typedef struct ListNode Node;
struct ListNode* reverseList(struct ListNode* head){
	Node* pPre = NULL;
	Node* pCur = head;   //放在链表中第一个位置
	Node* pNext = NULL;
	while (pCur){
		pNext = pCur->next;
		pCur->next = pPre;           //指向逆置后的前一个
		pPre = pCur;
		pCur = pNext;
	}
	return pPre;
}

解法二:(头插思想)

typedef struct ListNode Node;
struct ListNode* reverseList(struct ListNode* head){
	Node* pCur = head;   
	Node* pNewHead = NULL;
	while (pCur){
		head = pCur->next;
		pCur->next = pNewHead;       //pNewHead新链表的头结点
		pNewHead = pCur;
		pCur = head;
	}
	return pNewHead;
}
3.给定一个带有头结点head的非空单链表,返回链表的中间节点,如果有两个中间节点,则返回第二个中间节点.

//输入 : 1->2->3->4->5->Null 输出 : 3
//输入 : 1->2->3->4->Null 输出 : 3

typedef struct ListNode Node;
ListNode* ListNode* middleNode(struct ListNode* pHead){
	ListNode* pFast = head;
	ListNode* pSlow = head;
	while (pFast && pFast->next){
		pFast = pFast->next->next;           //一次走两步
		pSlow = pSlow->next;                 //一次走一步
	}
	return pSlow;
}
4.输入一个链表,输出该链表中倒数第k个结点.

输入 : 1->2->3->4->5->Null k=2

解法一

(快指针先走k步, 然后两个指针同时往后移动, 直到快指针走到链表的末尾;)
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k){
	if (NULL == pListHead || 0 == k){
		return NULL;
	}
	ListNode* pFast = pListHead;
	ListNode* pSlow = pListHead;
	//让快指针先走k步
	while (k--){
		if (NULL==pFast){
			return NULL;
		}
		pFast = pFast->next;
	}
	//让两个指针同时向后移动
	while (pFast){
		pFast = pFast->next;
		pSlow = pSlow->next;
	}
	return pSlow;
}

解法二

(快指针先走k - 1, 然后两个指针同时往后移动, 直到快指针走到最后一个节点)
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k){
	if (NULL == pListHead || 0 == k){
		return NULL;
	}
	ListNode* pFast = pListHead;
	ListNode* pSlow = pListHead;
	//让快指针先走k步
	while (--k){
		if (NULL == pFast){
			return NULL;
		}
		pFast = pFast->next;
	}
	if (NULL==pFast){
		return NULL;
	}
	//让两个指针同时向后移动
	while (pFast->next){
		pFast = pFast->next;
		pSlow = pSlow->next;
	}
	return pSlow;
}
4.扩展(删除链表中倒数第k个结点.)

输入 : 1->2->3->4->5->Null k=2

//找到链表中的倒数第k个结点.
//pFast--->k步
while (pFast){
	pFast = pFast->next;
	pSlow = pSlow;
	pSlow = pSlow->next;
}
//删除
if (pHead == pSlow){
	pHead = pSlow->next;
	free(pSlow);
}
else{
	pPreSlow->next = pSlow->next;
	free(pSlow);
}

5.将两个有序链表合并为一个新的有序链表并返回,新链表是通过拼接给定的两个链表的所有结点组成的.

输入: 2->3->7->9->Null 链表pL1
输出 : 1->2->2->3->4->6->7->8->9->Null 链表pTail
1->2->4->6->8->Null 链表pL2

typedef struct ListNode Node;
struct ListNode* mergeTwoLists(struct ListNode* l1, 
	struct ListNode* l2){
	if (NULL == l1){
		return l2;
	}
	if(NULL == l2){
		return l1;
	}
	Node head;
	Node* pTail = &head;
	Node* pL1 = l1;
	Node* pL2 = l2;
	while (pL1 && pL2){
		if (pL1->val <= pL2->val){
			pTail->next = pL1;
			pL1 = pL1->next;
		}
		else {
			pTail->next = pL2;
			pL2 = pL2->next;
		}
		pTail = pTail->next;
	}
	if (NULL == pL1){
		pTail->next = pL2;
	}
	else{
		pTail->next = pL1;
	}
	return head.next;
}
6.编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点都排在大于或者等于x的结点之前.
typedef struct ListNode ListNode;
ListNode* partition(ListNode* pHead, int x){
	if (NULL == pHead){
		return NULL;
	}
	ListNode lessList(0);
	ListNode greaterList(0);
	ListNode* pTail1 = &lessList;
	ListNode* pTail2 = &greaterList;
	ListNode* pCur = pHead;
	while (pCur){
		if (pCur->val < x){
			pTail1->next = pCur;
			pTail1 = pTail1->next;
		}
		else{
			pTail2->next = pCur;
			pTail2 = pTail2->next;
		}

		pCur = pCur->next;
	}
	pTail1->next = NULL;
	pTail2->next = NULL;
	pTail1->next = greaterList.next;
	return lessList.next;
}
7.在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点

//不保留,返回链表头指针.

8.链表的回文结构.c++

解法一

bool chkpalindrome(ListNode* A){
	if (NULL==A){
		return true;
	}
	int* p = (int*)malloc(sizeof(int)* 900);
	//将链表中所有的结点中的值放到辅助空间中
	ListNode* pCur = A;
	int size = 0;
	while (pCur){
		p[size++] = pCur->val;
		pCur = pCur->next;
	}
	int begin = 0;
	int end = size - 1;
	while (begin < end){
		if (p[begin] != p[end]){
			free(p);
			return false;
		}
		begin++;
		end--;
	}
	free(p);
	return true;
}

解法二:(逆置)

ListNode* ReverseList(ListNode* pHead){
	ListNode* pNewHead = NULL;
	ListNode* pCur = pHead;
	while (pCur){
		pHead = pCur->next;
		pCur->next = NewHead;
		pNewHead = pCur;
		pCur = pHead;
	}
	return pNewHead;
}
bool chkpalindrome(ListNode* A){
	if (NULL == A){
		return true;
	}
	//找链表中间位置
	ListNode* pFast = A;
	ListNode* pSlow = A;
	ListNode* pSlowPre = NULL;
	while (pFast && pFast -> next){
		pFast = pFast->next->next;
		pSlowPre = pSlow;
		pSlow = pSlow->next;
	}
	pSlowPre->next = NULL;
	ListNode* pCur1 = A;
	ListNode* pCur2 = ReverseList(pSlow);
	while (pCur1 && pCur2){
		if (pCur1->val != pCur2->val){
			return false;
		}
		pCur1 = pCur1->next;
		pCur2 = pCur2->next;
	}
	return true;
}
9.输入两个链表,找出他们的第一个公共结点.(链表不带环)

解题思路

  • (1)确认链表是否相交

a.找到并检测最后一个节点是否相同;

  • (2)求交点

a.确认哪个链表长;
b.让长的的链表向后走差值步;
c.两个指针同时往后移动,直到相遇.

typedef struct ListNode ListNode;

struct ListNode* getIntersectionNode(struct ListNode* headA, struct
	ListNode* headB){
	if (NULL == headA || NULL == headB){
		return NULL;
	}
	//1.确认两个链表是否为相交
	ListNode* pTailA = headA;
	ListNode* pTailB = headB;
	int sizeA = 1;            //统计结点个数
	int sizeB = 1;
	//找headA链表中的最后一个结点
	while (pTailA->next){
		sizeA++;
		pTailA = pTailA->next;
	}
	//找headB链表中的最后一个结点
	while (pTailB->next){
		sizeB++;
		pTailB = pTailB->next;
	}
	if (pTailA!=pTailB){
		return NULL;
	}
	//两个链表已经相交
	int gap = sizeA - sizeB;
	ListNode* pCurA = headA;
	ListNode* pCurB = headB;
	if (gap>0){
		while (gap--){
			pCurA = pCurA->next;
		}
	}
	else{
		while (gap++){
			pCurB = pCurB->next;
		}
	}
	while (pCurA!=pCurB){
		pCurA = pCurA->next;
		pCurB = pCurB->next;
	}
	return pCurA;
}
9. 扩展.输入两个链表,找出他们的第一个公共结点.(链表可能带环)
10. 给定一个链表,判断链表中是否有环.(链表中的最后一个结点的Next域不指向空)
typedef struct ListNode Node;
bool hasCycle(struct ListNode* head){
	Node* pFast = head;
	Node* pSlow = head;
	while (pFast && pFast->next){
		pFast = pFast->next->next;
		pSlow = pSlow->next;
		if (pFast==pSlow){
			return true;
		}
	}
	return false;
}
11. 给定一个链表,返回链表开始入环的第一个结点,如果链表无环,则返回Null.

解题思路

  • (1)可给定两个指针, 三个结点(头结点, 入口点, 相遇点);
  • (2)指针tail1从头部出发, 指针tail2从相遇点出发, 下次相遇点为入口位置;
typedef struct ListNode Node;
struct ListNode* detecCycle(struct ListNode* head){
	Node* pSlow = head;
	Node* pFast = head;
	while (pFast && pFast->next){
		pFast = pFast->next->next;
		pSlow = pSlow->next;
		if (pFast==pSlow){
			break;
		}
	}
	if (NULL == pFast || NULL == pFast->next){
		return NULL;
	}
	Node* pH = head;
	Node* pM = pFast;
	while (pH!=pM){
		pH = pH->next;
		pM = pM->next;
	}
	return pM;                //return pH;
} 
12. 给定一个链表,每个结点包含一个额外增加的随机指针,该指针可以指向链表中任何结点或者空结点,要求返回这个链表的胜负拷贝.(复杂链表的复制)

解题思路

  • (1)在原链表每个结点后插入相同的新结点;
  • (2)给新插入结点的随机指针域赋值;
  • (3)将新插入结点从原链表中拆出来
Node* BuyNode(int data){
	Node* pNewNode = (Node*)malloc(sizeof(Node));
	if (NULL == pNewNode){
		assert(0);
		return NULL;
	}
	pNewNode->val = data;
	pNewNode->next = NULL;
	pNewNode->random = NULL;
	return pNewNode;
}

class solution{
public:
	Node* copyRandomList(Node* head){
		if (NULL == head){
			return NULL;
		}
		//在原链表中每个结点后插入值相同的新结点
		Node* pCur = head;
		while (pCur){
			Node* pNewNode = BuyNode(pCur->next);
			pNewNode->next = pCur->next;
			pCur->next = pNewNode;
			pCur = pNewNode->next;
		}
		//给新插入结点的随机指针域赋值
		pCur = head;
		while (pCur){
			pNewNode = pCur->next;
			if (pCur->random){
				pNewNode->random = pCur->random->next;
			}
			pCur = pNewNode->next;		
		}
		//将新插入的结点从原链表中拆下来
		pCur = head;
		Node* pNewNode = pCur -> next;
		while (pCur->next){
			pNewNode = pCur->next;
			pCur -> next = pNewNode -> next;
			pCur = pNewNode;
		}
		return pNewHead;
	}
};

链表面试题(C++版本)

#include <iostream>
using namespace std;

#if 0
// 如果想要通过形参改变外部的实参,必须传递实参的地址
// 如果实参是值,比如 int a; 传递a的地址----一级指针
// 如果实参是指针, 比如: int* pa = &a; 传递pa的地址-->二级指针
void Swap(int** left, int** right)
{
	//cout << &left << " " << &right << endl;
	int* temp = *left;
	*left = *right;
	*right = temp;
}

int main()
{
	int a = 10;
	int b = 20;
	//Swap(a, b);
	//Swap(&a, &b);

	int* pa = &a;
	int* pb = &b;
	//Swap(pa, pb);
	Swap(&pa, &pb);
	return 0;
}
#endif


// 不带头结点的单链表
struct ListNode
{
	ListNode(int data)
	: _pNext(nullptr)
	, _data(data)
	{}

	ListNode* _pNext;
	int _data;
};


void PushBack(ListNode*& pHead, int data)
{
	if (nullptr == pHead)
	{
		pHead = new ListNode(data);
		return;
	}

	// 找到链表中最后一个节点
	ListNode* pCur = pHead;
	while (pCur->_pNext)
		pCur = pCur->_pNext;

	pCur->_pNext = new ListNode(data);
}

void PrintList(ListNode* pHead)
{
	ListNode* pCur = pHead;
	while (pCur)
	{
		cout << pCur->_data << "--->";
		pCur = pCur->_pNext;
	}
	cout << "NULL" << endl;
}

/
//
#if 0
// 时间复杂度:O(N)   空间复杂度:O(N)
#include <stack>
void ReverseList(ListNode*& pHead)
{
	if (nullptr == pHead)
		return;

	stack<ListNode*> s;
	ListNode* pCur = pHead;
	while (pCur)
	{
		s.push(pCur);
		pCur = pCur->_pNext;
	}

	pHead = s.top();
	s.pop();
	ListNode* pPre = pHead;
	while (!s.empty())
	{
		pCur = s.top();
		pPre->_pNext = pCur;
		pPre = pCur;
		s.pop();
	}

	pCur->_pNext = nullptr;
}


#endif
#if 0
void ReverseList(ListNode*& pHead)
{
	ListNode* pPre = nullptr;
	ListNode* pCur = pHead;
	ListNode* pNext = nullptr;

	while (pCur)
	{
		pNext = pCur->_pNext;
		pCur->_pNext = pPre;
		pPre = pCur;
		pCur = pNext;
	}

	pHead = pPre;
}
#endif


// 采用头插法
void ReverseList(ListNode*& pHead)
{
	ListNode* pNewHead = nullptr;
	ListNode* pCur = pHead;

	while (pCur)
	{
		// 将pCur从原链表中移除
		pHead = pCur->_pNext;

		// 将pCur头插到新链表中
		pCur->_pNext = pNewHead;
		pNewHead = pCur;

		// 让pCur取原链表中的下一个节点
		pCur = pHead;
	}

	pHead = pNewHead;
}


ListNode* FindMiddleNode(ListNode* pHead)
{
	if (nullptr == pHead)
		return nullptr;

	ListNode* pSlow = pHead;
	ListNode* pFast = pHead;

	while (pFast && pFast->_pNext)
	{
		pFast = pFast->_pNext->_pNext;
		pSlow = pSlow->_pNext;
	}

	return pSlow;
}

#if 0
ListNode* FindLastKNode(ListNode* pHead, size_t K)
{
	if (nullptr == pHead || 0 == K)
		return nullptr;

	ListNode* pFast = pHead;
	// 后置--,pFast先走K步
	while (K--)
	{
		// 检测:K大于链表长度的情况
		if (nullptr == pFast)
			return nullptr;

		pFast = pFast->_pNext;
	}

	ListNode* pSlow = pHead;
	while (pFast)
	{
		pFast = pFast->_pNext;
		pSlow = pSlow->_pNext;
	}

	return pSlow;
}
#endif

ListNode* FindLastKNode(ListNode* pHead, size_t K)
{
	if (nullptr == pHead || 0 == K)
		return nullptr;

	ListNode* pFast = pHead;
	// 前置--,pFast先走K-1步
	while (--K)
	{
		// 检测:K大于链表长度的情况
		if (nullptr == pFast)
			return nullptr;

		pFast = pFast->_pNext;
	}

	if (nullptr == pFast)
		return nullptr;

	ListNode* pSlow = pHead;
	while (pFast->_pNext)
	{
		pFast = pFast->_pNext;
		pSlow = pSlow->_pNext;
	}

	return pSlow;
}

ListNode* DeleteLastKNode(ListNode*& pHead, size_t K)
{
	// 1. 找倒数第K个节点
	if (nullptr == pHead || 0 == K)
		return nullptr;

	ListNode* pFast = pHead;
	// 后置--,pFast先走K步
	while (K--)
	{
		// 检测:K大于链表长度的情况
		if (nullptr == pFast)
			return nullptr;

		pFast = pFast->_pNext;
	}

	ListNode* pSlow = pHead;
	ListNode* pPre = nullptr;
	while (pFast)
	{
		pFast = pFast->_pNext;
		pPre = pSlow;
		pSlow = pSlow->_pNext;
	}

	// 2. 删除节点
	if (pSlow == pHead)
	{
		pHead = pSlow->_pNext;
	}
	else
	{
		pPre->_pNext = pSlow->_pNext;
	}

	delete pSlow;
}

ListNode* MergeList(ListNode* pHead1, ListNode* pHead2)
{
	if (nullptr == pHead1)
		return pHead2;

	if (nullptr == pHead2)
		return pHead1;

	// 合并之后新链表的头结点
	ListNode NewHead(0);
	ListNode* pTail = &NewHead;
	ListNode* pCur1 = pHead1;
	ListNode* pCur2 = pHead2;

	while (pCur1 && pCur2)
	{
		if (pCur1->_data <= pCur2->_data)
		{
			pTail->_pNext = pCur1;
			pCur1 = pCur1->_pNext;
		}
		else
		{
			pTail->_pNext = pCur2;
			pCur2 = pCur2->_pNext;
		}

		pTail = pTail->_pNext;
	}

	if (nullptr == pCur1)
		pTail->_pNext = pCur2;
	else
		pTail->_pNext = pCur1;

	return NewHead._pNext;
}

int GetListSize(ListNode* pHead)
{
	int count = 0;
	ListNode* pCur = pHead;
	while (pCur)
	{
		count++;
		pCur = pCur->_pNext;
	}

	return count;
}

ListNode* GetCrossNode(ListNode* pHead1, ListNode* pHead2)
{
	// 0. 参数检测
	if (nullptr == pHead1 || nullptr == pHead2)
		return nullptr;

	// 1. 检测两个链表是否相交
	// 检测两个链表中最后一个节点是否相同
	ListNode* pTail1 = pHead1;
	while (pTail1->_pNext)
		pTail1 = pTail1->_pNext;

	ListNode* pTail2 = pHead2;
	while (pTail2->_pNext)
		pTail2 = pTail2->_pNext;

	// 两个链表不想交
	if (pTail1 != pTail2)
		return nullptr;

	// 2. 求交点
	int size1 = GetListSize(pHead1);
	int size2 = GetListSize(pHead2);

	// 先让较长的链表往后移动两个链表差值步
	int gap = size1 - size2;
	ListNode* pCur1 = pHead1;
	ListNode* pCur2 = pHead2;
	if (gap > 0)
	{
		// 让pCur1往后移动gap
		while (gap--)
			pCur1 = pCur1->_pNext;
	}
	else
	{
		while (gap++)
			pCur2 = pCur2->_pNext;
	}

	// 让两个指针同时往后移动
	while (pCur1 != pCur2)
	{
		pCur1 = pCur1->_pNext;
		pCur2 = pCur2->_pNext;
	}

	return pCur1;
}

int main()
{
	ListNode* pHead1 = nullptr;
	PushBack(pHead1, 2);
	PushBack(pHead1, 4);
	PushBack(pHead1, 7);
	PrintList(pHead1);

	ListNode* pHead2 = nullptr;
	PushBack(pHead2, 1);
	PushBack(pHead2, 3);
	PushBack(pHead2, 8);
	PushBack(pHead2, 9);
	PrintList(pHead2);

	ListNode* pHead = MergeList(pHead1, pHead2);
	PrintList(pHead);
	return 0;
}
#include <iostream>
using namespace std;

#if 0
// 如果想要通过形参改变外部的实参,必须传递实参的地址
// 如果实参是值,比如 int a; 传递a的地址----一级指针
// 如果实参是指针,比如: int* pa = &a; 传递pa的地址-->二级指针
void Swap(int** left, int** right)
{
	//cout << &left << " " << &right << endl;
	int* temp = *left;
	*left = *right;
	*right = temp;
}

int main()
{
	int a = 10;
	int b = 20;
	//Swap(a, b);
	//Swap(&a, &b);

	int* pa = &a;
	int* pb = &b;
	//Swap(pa, pb);
	Swap(&pa, &pb);
	return 0;
}
#endif


// 不带头结点的单链表
struct ListNode
{
	ListNode(int data)
	: _pNext(nullptr)
	, _data(data)
	{}

	ListNode* _pNext;
	int _data;
};

*&(在函数体中如果改变饿了pHead的指向, 外部的实参也会发生改变; 如果只是传递指针的话, 外部实参修改了, 指针的指向是不会改变的; C语言中需要传二级指针, C++中只需要传一级指针的引用就可以了)
void PushBack(ListNode*& pHead, int data)
{
	if (nullptr == pHead)
	{
		pHead = new ListNode(data);
		return;
	}

	// 找到链表中最后一个节点
	ListNode* pCur = pHead;
	while (pCur->_pNext)
		pCur = pCur->_pNext;

	pCur->_pNext = new ListNode(data);
}

void PrintList(ListNode* pHead)
{
	ListNode* pCur = pHead;
	while (pCur)
	{
		cout << pCur->_data << "--->";
		pCur = pCur->_pNext;
	}
	cout << "NULL" << endl;
}

/
//单链表的逆置
#if 0
// 时间复杂度:O(N)   空间复杂度:O(N)
#include <stack>
void ReverseList(ListNode*& pHead)
{
	if (nullptr == pHead)
		return;

	stack<ListNode*> s;
	ListNode* pCur = pHead;
	while (pCur)
	{
		s.push(pCur);
		pCur = pCur->_pNext;
	}

	pHead = s.top();
	s.pop();
	ListNode* pPre = pHead;
	while (!s.empty())
	{
		pCur = s.top();
		pPre->_pNext = pCur;
		pPre = pCur;
		s.pop();
	}

	pCur->_pNext = nullptr;
}


#endif
#if 0
void ReverseList(ListNode*& pHead)
{
	ListNode* pPre = nullptr;
	ListNode* pCur = pHead;
	ListNode* pNext = nullptr;

	while (pCur)
	{
		pNext = pCur->_pNext;
		pCur->_pNext = pPre;
		pPre = pCur;
		pCur = pNext;
	}

	pHead = pPre;
}
#endif


// 采用头插法
void ReverseList(ListNode*& pHead)
{
	ListNode* pNewHead = nullptr;
	ListNode* pCur = pHead;

	while (pCur)
	{
		// 将pCur从原链表中移除
		pHead = pCur->_pNext;

		// 将pCur头插到新链表中
		pCur->_pNext = pNewHead;
		pNewHead = pCur;

		// 让pCur取原链表中的下一个节点
		pCur = pHead;
	}

	pHead = pNewHead;
}


ListNode* FindMiddleNode(ListNode* pHead)
{
	if (nullptr == pHead)
		return nullptr;

	ListNode* pSlow = pHead;
	ListNode* pFast = pHead;

	while (pFast && pFast->_pNext)
	{
		pFast = pFast->_pNext->_pNext;
		pSlow = pSlow->_pNext;
	}

	return pSlow;
}

#if 0
ListNode* FindLastKNode(ListNode* pHead, size_t K)
{
	if (nullptr == pHead || 0 == K)
		return nullptr;

	ListNode* pFast = pHead;
	// 后置--,pFast先走K步
	while (K--)
	{
		// 检测:K大于链表长度的情况
		if (nullptr == pFast)
			return nullptr;

		pFast = pFast->_pNext;
	}

	ListNode* pSlow = pHead;
	while (pFast)
	{
		pFast = pFast->_pNext;
		pSlow = pSlow->_pNext;
	}

	return pSlow;
}
#endif

ListNode* FindLastKNode(ListNode* pHead, size_t K)
{
	if (nullptr == pHead || 0 == K)
		return nullptr;

	ListNode* pFast = pHead;
	// 前置--,pFast先走K-1步
	while (--K)
	{
		// 检测:K大于链表长度的情况
		if (nullptr == pFast)
			return nullptr;

		pFast = pFast->_pNext;
	}

	if (nullptr == pFast)
		return nullptr;

	ListNode* pSlow = pHead;
	while (pFast->_pNext)
	{
		pFast = pFast->_pNext;
		pSlow = pSlow->_pNext;
	}

	return pSlow;
}

//删除链表中第K个结点
ListNode* DeleteLastKNode(ListNode*& pHead, size_t K)
{
	// 1. 找倒数第K个节点
	if (nullptr == pHead || 0 == K)
		return nullptr;

	ListNode* pFast = pHead;
	// 后置--,pFast先走K步
	while (K--)
	{
		// 检测:K大于链表长度的情况
		if (nullptr == pFast)
			return nullptr;

		pFast = pFast->_pNext;
	}

	ListNode* pSlow = pHead;
	ListNode* pPre = nullptr;
	while (pFast)
	{
		pFast = pFast->_pNext;
		pPre = pSlow;
		pSlow = pSlow->_pNext;
	}

	// 2. 删除节点
	if (pSlow == pHead)
	{
		pHead = pSlow->_pNext;
	}
	else
	{
		pPre->_pNext = pSlow->_pNext;
	}

	delete pSlow;
}

//合并链表
ListNode* MergeList(ListNode* pHead1, ListNode* pHead2)
{
	if (nullptr == pHead1)
		return pHead2;

	if (nullptr == pHead2)
		return pHead1;

	// 合并之后新链表的头结点
	ListNode NewHead(0);
	ListNode* pTail = &NewHead;
	ListNode* pCur1 = pHead1;
	ListNode* pCur2 = pHead2;

	while (pCur1 && pCur2)
	{
		if (pCur1->_data <= pCur2->_data)
		{
			pTail->_pNext = pCur1;
			pCur1 = pCur1->_pNext;
		}
		else
		{
			pTail->_pNext = pCur2;
			pCur2 = pCur2->_pNext;
		}

		pTail = pTail->_pNext;
	}

	if (nullptr == pCur1)
		pTail->_pNext = pCur2;
	else
		pTail->_pNext = pCur1;

	return NewHead._pNext;
}

//获取链表的结点个数
int GetListSize(ListNode* pHead)
{
	int count = 0;
	ListNode* pCur = pHead;
	while (pCur)
	{
		count++;
		pCur = pCur->_pNext;
	}

	return count;
}

//
ListNode* GetCrossNode(ListNode* pHead1, ListNode* pHead2)
{
	// 0. 参数检测
	if (nullptr == pHead1 || nullptr == pHead2)
		return nullptr;

	// 1. 检测两个链表是否相交
	// 检测两个链表中最后一个节点是否相同
	ListNode* pTail1 = pHead1;
	while (pTail1->_pNext)
		pTail1 = pTail1->_pNext;

	ListNode* pTail2 = pHead2;
	while (pTail2->_pNext)
		pTail2 = pTail2->_pNext;

	// 两个链表不想交
	if (pTail1 != pTail2)
		return nullptr;

	// 2. 求交点
	int size1 = GetListSize(pHead1);
	int size2 = GetListSize(pHead2);

	// 先让较长的链表往后移动两个链表差值步
	int gap = size1 - size2;
	ListNode* pCur1 = pHead1;
	ListNode* pCur2 = pHead2;
	if (gap > 0)
	{
		// 让pCur1往后移动gap
		while (gap--)
			pCur1 = pCur1->_pNext;
	}
	else
	{
		while (gap++)
			pCur2 = pCur2->_pNext;
	}

	// 让两个指针同时往后移动
	while (pCur1 != pCur2)
	{
		pCur1 = pCur1->_pNext;
		pCur2 = pCur2->_pNext;
	}

	return pCur1;
}

int main()
{
	ListNode* pHead1 = nullptr;
	PushBack(pHead1, 2);
	PushBack(pHead1, 4);
	PushBack(pHead1, 7);
	PrintList(pHead1);

	ListNode* pHead2 = nullptr;
	PushBack(pHead2, 1);
	PushBack(pHead2, 3);
	PushBack(pHead2, 8);
	PushBack(pHead2, 9);
	PrintList(pHead2);

	ListNode* pHead = MergeList(pHead1, pHead2);
	PrintList(pHead);
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值