面试中LeetCode常见算法整理——链表

面试中LeetCode常见算法整理——链表

1. 找出两个链表的交点

160. Intersection of Two Linked Lists

设链表A的长度为 a + c,B的长度为 b + c,其中 c 为尾部公共部分长度,可知 a + c + b = b + c + a。

当访问 A 链表的指针访问到链表尾部时,令它从链表 B 的头部开始访问链表 B;同样地,当访问 B 链表的指针访问到链表尾部时,令它从链表 A 的头部开始访问链表 A。这样就能控制访问 A 和 B 两个链表的指针能同时访问到交点。

class Solution {
public:
	ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
		ListNode* l1 = headA;
		ListNode* l2 = headB;
		while (l1 != l2)
		{
			l1 = (l1 == nullptr) ? headB : l1->next;
			l2 = (l2 == nullptr) ? headA : l2->next;
		}
		return l1;
	}
};

2. 链表反转

206. Reverse Linked List

递归实现

class Solution {
public:
	ListNode* reverseList(ListNode* head) {
		if (!head || !head->next) //注意条件一定要有第二个
			return head;
		ListNode* next = head->next;
		ListNode* newHead = reverseList(next);
		head->next = nullptr;
		next->next = head;
		return newHead;
	}
};

头插法

class Solution {
public:
	ListNode* reverseList(ListNode* head) {
		if (!head || !head->next)
			return head;
		ListNode* pre = nullptr; //前一个节点
		ListNode* cur = head; //当前节点
		while (cur)
		{
			ListNode* next = cur->next;
			cur->next = pre;
			pre = cur;
			cur = next;
		}
		return pre;
	}
};

3. 归并两个有序链表

21. Merge Two Sorted Lists

class Solution {
public:
	ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
		if (!l1)
			return l2;
		if (!l2)
			return l1;
		if (l1->val < l2->val)
		{
			l1->next = mergeTwoLists(l1->next, l2);
			return l1;
		}
		else
		{
			l2->next = mergeTwoLists(l1, l2->next);
			return l2;
		}
	}
};

4. 从有序链表中删除重复节点

递归实现删除链表的重复节点,重复节点只保留一个。

83. Remove Duplicates from Sorted List

class Solution {
public:
	ListNode* deleteDuplicates(ListNode* head) {
		if (!head || !head->next)
			return head;
		head->next = deleteDuplicates(head->next);
		return head->val == head->next->val ? head->next : head;
	}
};

递归实现删除链表的重复节点,不保留重复节点。

82. Remove Duplicates from Sorted List II

class Solution {
public:
	ListNode* deleteDuplicates(ListNode* head) {
		if (!head || !head->next)
			return head;
		ListNode* next = head->next;
		if (head->val == next->val)
		{
			while (next && head->val == next->val)
				next = next->next;
			return deleteDuplicates(next);
		}
		else
		{
			head->next = deleteDuplicates(next);
			return head;
		}
	}
};

5. 删除链表的倒数第n个节点

19. Remove Nth Node From End of List

class Solution {
public:
	ListNode* removeNthFromEnd(ListNode* head, int n) {
		if (!head || n <= 0)
			return head;
		ListNode* p = head;
		while (p&&n--)
			p = p->next;
		if (p == nullptr && n == 0) //链表长度恰好为n
			return head->next;
		else if (p == nullptr) //链表长度不足n
			return head;
		else
		{
			//注意这里的步长关系最好画图确认一下
			ListNode* pSlow = head;
			ListNode* pFast = p->next;
			while (pFast)
			{
				pSlow = pSlow->next;
				pFast = pFast->next;
			}
			pSlow->next = pSlow->next->next;
			return head;
		}

	}
};

6. 交换链表中的相邻节点

24. Swap Nodes in Pairs

class Solution {
public:
	ListNode* swapPairs(ListNode* head) {
		if (!head || !head->next)
			return head;
		ListNode* xuniNode = new ListNode(0);
		xuniNode->next = head;
		ListNode*pre = xuniNode;
		ListNode* cur = head;
		while (cur && cur->next)
		{
			//这个地方如果实在是操作不过来可以多定义几个节点
			ListNode* next = cur->next;
			ListNode* nextnext = next->next;
			pre->next = next;
			next->next = cur;
			cur->next = nextnext;
			pre = cur;
			cur = nextnext;
		}
		ListNode* res = xuniNode->next;
		delete xuniNode;
		return res;
	}
};

7. 链表求和

445. Add Two Numbers II

class Solution {
public:
	ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
		if (!l1 || !l2)
			return nullptr;
		stack s1;
		stack s2;
		stack sres;
		ListNode* p1 = l1;
		ListNode* p2 = l2;
		while (p1)
		{
			s1.push(p1->val);
			p1 = p1->next;
		}

		while (p2)
		{
			s2.push(p2->val);
			p2 = p2->next;
		}

		p1 = l1;
		p2 = l2;
		int sum = 0;
		int carry = 0;
		while (!s1.empty() || !s2.empty())
		{
			if (!s1.empty() && !s2.empty())
			{
				sum = (s1.top() + s2.top() + carry) % 10;
				carry = (s1.top() + s2.top() + carry) / 10;
				sres.push(sum);
				s1.pop();
				s2.pop();
			}
			else if (!s1.empty())
			{
				sum = (s1.top() + carry) % 10;
				carry = (s1.top() + carry) / 10;
				sres.push(sum);
				s1.pop();
			}

			else if (!s2.empty())
			{
				sum = (s2.top() + carry) % 10;
				carry = (s2.top() + carry) / 10;
				sres.push(sum);
				s2.pop();
			}
			//处理最后一位进位的情况
			if (s1.empty() && s2.empty() && carry)
				sres.push(carry);
		}
		ListNode* res = new ListNode(sres.top());
		sres.pop();
		ListNode* pres = res;
		while (!sres.empty())
		{
			pres->next = new ListNode(sres.top());
			sres.pop();
			pres = pres->next;
		}
		return res;
	}
};

8. 回文链表

234. Palindrome Linked List

class Solution {
public:
	bool isPalindrome(ListNode* head) {
		if (!head || !head->next)
			return true;
		ListNode* pSlow = head;
		ListNode* pFast = head->next;
		while (pFast && pFast->next)
		{
			pSlow = pSlow->next;
			pFast = pFast->next->next;
		}
		ListNode* p1 = pSlow->next;
		pSlow->next = nullptr;
		ListNode* p2 = head;
		p1 = reverse(p1);
		while (p1 && p2)
		{
			if (p1->val != p2->val)
				return false;
			p1 = p1->next;
			p2 = p2->next;
		}
		return true;
	}
private:
	ListNode* reverse(ListNode* head)
	{
		if (!head || !head->next)
			return head;
		ListNode* next = head->next;
		ListNode* newHead = reverse(next);
		head->next = nullptr;
		next->next = head;
		return newHead;
	}
};

9. 链表按照奇偶元素聚集

328. Odd Even Linked List

class Solution {
public:
	ListNode* oddEvenList(ListNode* head) {
		if (!head || !head->next)
			return head;
		ListNode* evenEnd = head; //表示当前奇数节点的结尾,初始值为head
		ListNode* cur = head->next;
		while (cur && cur->next) //每次取一组[偶数,奇数]节点对
		{
			ListNode* next = cur->next->next;
			cur->next->next = evenEnd->next;
			evenEnd->next = cur->next;
			cur->next = next;

			evenEnd = evenEnd->next;
			cur = next;
		}
		return head;
	}
};

 

你可能感兴趣的:(LeetCode刷题之路,算法研讨之路)