目录
反转单链表
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
class Solution {
public:
//递归
ListNode *reverseList1(ListNode *head)
{
//递归结束条件肯定是head走到最后了那就是要么是null要么是末尾元素
if (head == NULL || head->next == NULL)
return head;
//局部反转 当前元素的下一位元素的next指向当前元素 当前节点的next指向null
ListNode *p = reverseList1(head->next);
head->next->next = head;
head->next = NULL;
return p;
}
//双指针
ListNode *reverseList2(ListNode *head)
{
/*
双指针法 将当前节点与下一位节点反转
*/
//当只有一个节点或者没有节点的时候
if (head == NULL || head->next == NULL)
return head;
ListNode *cur = head;
ListNode *pre = head->next;
while (pre != NULL)
{
ListNode *tmp = pre->next; //保存pre next
//反转
pre->next = cur;
//cur与pre同时想继续向后走
//由于pre->已经指向cur了 所以我们必须提前保存pre->next
cur = pre;
pre = tmp;
}
return cur;
}
};
合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
ListNode *mergeTwoLists(ListNode *l1, ListNode *l2)
{
if (l1 == NULL)
return l2;
else if(l2==NULL)
return l1;
ListNode *pre = new ListNode(-1);
ListNode* p = pre;
while(l1&&l2)
{
if(l1->val<=l2->val)
{
p->next = l1;
l1 = l1->next;
}
else
{
p->next = l2;
l2 = l2->next;
}
p = p->next;
}
p->next = l1==NULL?l2:l1;
p = pre->next;
delete pre;
return p;
}
};
剑指offer35.复杂链表的复制
给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。要求返回这个链表的 深拷贝
class Node
{
public:
int val;
Node *next;
Node *random;
Node(int _val)
{
val = _val;
next = NULL;
random = NULL;
}
};
Node *copyRandomList(Node *head)
{
if (head == NULL)
return NULL;
//1.将拷贝的节点插入到被拷贝节点的下一个
Node *cur = head;
while (cur != NULL)
{
Node *p = new Node(cur->val);
Node *next = cur->next;
cur->next = p;
p->next = next;
cur = next;
}
//2.将拷贝的节点的rand进行设置
cur = head;
while (cur != NULL)
{
Node *p = cur->next;
if (cur->random != NULL)
p->random = cur->random->next;
else
p->random = NULL;
cur = p->next;
}
//3.偶数位上的就是拷贝的节点
//将拷贝的节点摘下来,进行尾插
Node *copyHead = NULL;
Node *copyTail = NULL;
cur = head;
while (cur != NULL)
{
Node* p = cur->next;
cur->next = p->next;
p->next = NULL;
if (copyTail == NULL)
{
copyTail = copyHead = p;
}
else
{
copyTail->next = p;
copyTail = p;
}
cur = cur->next;
}
return copyHead;
}
返回倒数第K个节点
输入一个链表,输出该链表中倒数第k个结点。
输入 1, {1,2,3,4,5}
返回值 {5}
ListNode *FindKthToTail(ListNode *pListHead, unsigned int k)
{
//快慢指针法
//快指针先走k-1步 然后快慢指针一起走 快指针走到头慢指针就是倒数第5个
if (k == 0 || pListHead == NULL)
return NULL;
ListNode *fast = pListHead;
ListNode *slow = pListHead;
while (k && fast != NULL)
{
fast = fast->next;
k--;
}
if (k == 0)
{
while (fast != NULL)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
return NULL;
}
链表求和
给定两个用链表表示的整数,每个节点包含一个数位。
这些数位是反向存放的,也就是个位排在链表首部。
编写函数对这两个整数求和,并用链表形式返回结果。
示例:
输入:(7 -> 1 -> 6) + (5 -> 9 -> 2),即617 + 295
输出:2 -> 1 -> 9,即912
716 592 1308
ListNode* reverseList(ListNode *head)
{
if (head == nullptr)
return nullptr;
ListNode *cur = head->next;
head->next = nullptr;
while (cur)
{
ListNode *p = cur;
cur = cur->next;
p->next = head;
head = p;
}
return head;
}
ListNode *addInList(ListNode *head1, ListNode *head2)
{
// write code here
/*
3 6
7 3 9
0 0 0 1
*/
head1 = reverseList(head1);
head2 = reverseList(head2);
ListNode *p1 = head1;
ListNode *p2 = head2;
ListNode *pre = nullptr;
int flag = 0;
while (p1 && p2)
{
int sum = p1->val + p2->val + flag;
flag = 0;
if (sum > 9)
{
flag = 1;
sum -= 10;
}
p1->val = sum;
pre = p1;
p1 = p1->next;
p2 = p2->next;
}
if (p2)
{
pre->next = p2;
p1 = p2;
}
while (p1)
{
int sum = p1->val + flag;
flag = 0;
if (sum > 9)
{
flag = 1;
sum -= 10;
}
p1->val = sum;
pre = p1;
p1 = p1->next;
}
if (flag)
pre->next = new ListNode(1);
return reverseList(head1);
}
两个链表的第一个公共节点
//双指针分别指向两个链表 求出两个链表的长度 他们长度的差值就是长链表指针先走的长度 然后一起走直到相遇
//两个指针同时走 当一个走到头就让他指向另一个头结点继续走
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB)
{
if (headB==nullptr||headA==nullptr)
return nullptr;
ListNode *pa = headA, *pb = headB;
while(pa!=pb)
{
pa = pa!=nullptr?pa->next:headB;
pb = pb!=nullptr?pb->next:headA;
}
return pa;
}
合并K个升序链表
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
class Solution
{
public:
ListNode *twoMergeLists(ListNode *l1, ListNode *l2)
{
if (l1 == nullptr && l2 == nullptr)
return nullptr;
if (l1 == nullptr)
return l2;
if (l2 == nullptr)
return l1;
ListNode *pre = new ListNode(-1);
ListNode *p = pre;
while (l1 && l2)
{
if (l1->val < l2->val)
{
p->next = l1;
l1 = l1->next;
}
else
{
p->next = l2;
l2 = l2->next;
}
p = p->next;
}
p->next = l1 == nullptr ? l2 : l1;
p = pre->next;
delete pre;
return p;
}
ListNode *mergeList(vector<ListNode *> &lists,int left,int right)
{
if(left==right)return lists[left];
if(left>right)return nullptr;
int mid = (left+right)>>1;
return twoMergeLists(mergeList(lists,left,mid),mergeList(lists,mid+1,right));
}
ListNode *mergeKLists(vector<ListNode *> &lists)
{
return mergeList(lists, 0, lists.size()-1);
}
};
回文链表
给你一个单链表的头节点
head
,请你判断该链表是否为回文链表。如果是,返回true
;否则,返回false
class Solution
{
public:
bool isPalindrome(ListNode *head)
{
if(head==NULL||head->next==NULL)
return true;
stack<int> s;
ListNode* cur = head;
while(cur!=NULL)
{
s.push(cur->val);
cur = cur->next;
}
while(!s.empty())
{
if(head->val==s.top())
{
head = head->next;
s.pop();
}
else
{
return false;
}
}
return true;
}
};
先写这么多吧,眼睛有点酸后面在写然后在更新吧!
------------------------------------------------------------------------------------------------------
继续肝!!!
删除链表的倒数第 n 个结点
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点
示例 1:
输入:head = [1,2,3,4,5], n = 5
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
示例 3:
输入:head = [1,2], n = 2
输出:[2]
class Solution
{
public:
ListNode *removeNthFromEnd(ListNode *head, int n)
{
if (head == NULL || n <= 0)
return head;
ListNode *fast = head;
ListNode *slow = head;
while (fast && n + 1 > 0)
{
fast = fast->next;
n--;
}
while (fast)
{
fast = fast->next;
slow = slow->next;
}
if (head == slow)
{
if (n == 0)
{
head = head->next;
}
else
{
head->next = head->next->next;
}
}
else
{
slow->next = slow->next->next;
}
return head;
}
};
剑指 Offer 18. 删除链表的节点
// 给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。
// 返回删除后的链表的头节点。
// 示例 1:
// 输入: head = [4,5,1,9], val = 5
// 输出: [4,1,9]
// 解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9.
// 示例 2:
// 输入: head = [4,5,1,9], val = 1
// 输出: [4,5,9]
// 解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9.
class Solution
{
public:
ListNode *deleteNode(ListNode *head, int val)
{
if (head == NULL)
return head;
ListNode *cur = head;
ListNode *pre = NULL;
while (cur != NULL && cur->val != val)
{
pre = cur;
cur = cur->next;
}
if (pre == NULL)
head = head->next;
else
pre->next = cur->next;
return head;
}
void deleteNode(ListNode *node)
{
ListNode *del = node->next;
node->val = del->val;
node->next = del->next;
}
};
删除中间节点
实现一种算法,删除单向链表中间的某个节点(即不是第一个或最后一个节点),假定你只能访问该节点。
示例:
输入:单向链表a->b->c->d->e->f中的节点c
结果:不返回任何数据,但该链表变为a->b->d->e->f
class Solution
{
public:
void deleteNode(ListNode *node)
{
if(node==nullptr||node->next==nullptr)
return;
node->val = node->next->val;
node->next = node->next->next;
}
};
移除重复节点
移除未排序链表中的重复节点。保留最开始出现的节点。
// 示例1:
// 输入:[1, 2, 3, 3, 2, 1]
// 输出:[1, 2, 3]
// 示例2:
// 输入:[1, 1, 1, 1, 2]
// 输出:[1, 2]
class Solution
{
public:
ListNode *removeDuplicateNodes(ListNode *head)
{
if (head == nullptr || head->next == nullptr)
return head;
ListNode *pi = head;
while (pi != nullptr)
{
ListNode *pj = pi;
while (pj->next != nullptr)
{
if (pi->val != pj->next->val)
{
pj = pj->next;
}
else
{
pj->next = pj->next->next;
}
}
pi = pi->next;
}
return head;
}
};
删除排序链表中的重复元素
// 存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除所有重复的元素,使每个元素 只出现一次 。
// 返回同样按升序排列的结果链表。
//输入:head = [1,1,1,1,1,1,2,3,3]
//输出:[1,2,3]
class Solution
{
public:
ListNode *deleteDuplicates(ListNode *head)
{
if (head == nullptr || head->next == nullptr)
return head;
ListNode *pa = head;
ListNode *pb = head->next;
while (pb)
{
if (pa->val == pb->val)
{
pa->next = pb->next;
pb = pa->next;
}
else
{
pa = pa->next;
pb = pb->next;
}
}
return head;
}
};
从尾到头打印单链表
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
// 输入:head = [1,3,2]
// 输出:[2,3,1]
class Solution {
public:
vector<int> reversePrint(ListNode* head)
{
vector<int>vec;
ListNode*cur = head;
while(cur!=NULL)
{
vec.push_back(cur->val);
//s.push(cur->val);
cur = cur->next;
}
reverse(vec.begin(),vec.end());
return vec;
}
};
两数相加
给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
输入:l1 = [0], l2 = [0]
输出:[0]
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
class Solution
{
public:
ListNode *addTwoNumbers(ListNode *l1, ListNode *l2)
{
int len1 = 0;
int len2 = 0;
ListNode *p = l1;
ListNode *q = l2;
while (p != nullptr)
{
len1++;
p = p->next;
}
p = l2;
while (p != nullptr)
{
len2++;
p = p->next;
}
if (len1 > len2)
{
p = l1;
q = l2;
}
else
{
p = l2;
q = l1;
}
int carry = 0;
while (p && q)
{
int num = p->val + l2->val + carry;
carry = 0;
if (num > 10)
{
num /= 10;
carry = 1;
}
p->val = num;
p = p->next;
l2 = l2->next;
}
while (p)
{
int num = p->val + carry;
carry = 0;
if (num > 10)
{
num /= 10;
carry = 1;
}
p->val = num;
p = p->next;
}
if (carry == 1)
p->next = new ListNode(1);
return l1;
}
};
环形链表
给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。
class Solution {
public:
bool hasCycle(ListNode *head)
{
if (head == NULL)
return false;
//快慢指针
ListNode *fast = head;
ListNode *slow = head;
while (fast && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
return true;
}
return false;
}
};
环形链表 II
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。
输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点。
输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。
class Solution {
public:
ListNode *detectCycle(ListNode *head)
{
if(head==nullptr)
return nullptr;
ListNode *fast = head;
ListNode *slow = head;
while(fast&&fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(fast==slow)
{
fast = head;
while(fast!=slow)
{
fast = fast->next;
slow = slow->next;
}
return slow;
}
}
return nullptr;
}
};
对链表进行插入排序
ListNode *insertionSortList(ListNode *head)
{
if (head == NULL || head->next == NULL)
return head;
ListNode *p = head;
ListNode *q = p->next;
//断开链表
head->next = NULL;
//插入数据
while (q != NULL)
{
p = q;
q = q->next;
ListNode *s = head;
ListNode *pre = NULL;
//找位置
while (s != NULL && p->val > s->val)
{
pre = s;
s = s->next;
}
//插入位置在头部
if (pre == NULL)
{
p->next = head;
head = p;
}
else
{
p->next = pre->next;
pre->next = p;
}
}
return head;
}