删除链表
//使用虚拟结点
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
//头部添加虚拟结点
ListNode *resHead = new ListNode(-1,head);
ListNode *p= resHead;
while(p->next)
{
if(p->next->val == val)
{
p->next = p -> next ->next;
}
else
{
p = p ->next;
}
}
return resHead->next;
}
};
返回链表中间结点
给定一个头结点为 head 的非空单链表,返回链表的中间结点。
如果有两个中间结点,则返回第二个中间结点。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* middleNode(ListNode* head) {
//第一种解法 将链表遍历,放入vector数组中,取中间结点
vector<ListNode*> A = {head};
while(A.back()->next)
{
A.push_back(A.back()->next);
}
return A[A.size()/2];
//第二种解法 遍历两次,第一次为获得结点数,第二次为取中间结点
int num = 0;
ListNode *cur = head;
while(cur)
{
num++;
cur = cur->next;
}
int k = 0;
ListNode *cur2 = head;
while(k<num/2)
{
++k;
cur2 = cur2 -> next;
}
return cur2;
//第三种解法 快慢指针 遍历,快一些的走两步,慢一些的走一步
ListNode* slow = head;
ListNode *fast = head;
while(fast && fast->next)
{
slow = slow -> next;
fast = fast -> next -> next;
}
return slow;
}
};
反转链表
反转一个单链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
//利用一个新空间,遍历取出当前结点,利用头插法,接续到新链表head之后
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *res = new ListNode();
ListNode *cur = head;
while(cur)
{
ListNode *temp = cur;
cur = cur -> next;
temp->next = res->next;
res->next = temp;
}
return res->next;
}
};
//迭代解法
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* curr = head;
while (curr) {
ListNode* next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}
};
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/reverse-linked-list/solution/fan-zhuan-lian-biao-by-leetcode-solution-d1k2/
删除排序链表中的重复元素
存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除所有重复的元素,使每个元素 只出现一次 。
返回同样按升序排列的结果链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if(!head) return head;
ListNode *l1 = head;
while(l1->next)
{
if (l1->val != l1->next-> val)
{
l1= l1->next;
}
else
{
l1->next = l1->next->next;
}
}
return head;
}
};
移除未排序链表中的重复元素
移除未排序链表中的重复节点,保留最开始出现的结点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* removeDuplicateNodes(ListNode* head) {
//第一种解法 :利用两次循环 , 时间复杂度 O(N)
ListNode *p = head;
while(p){
ListNode *q = p;
while(q->next)
{
if(p->val == q->next->val)
{
q->next = q->next->next;
}
else
{
q = q->next;
}
}
p = p->next;
}
return head;
//第二种解法 利用哈希表,unordered_set ,时间复杂度O(N2)
if(head == nullptr) return head;
unordered_set<int> occured = {head->val};
ListNode* pos = head;
//枚举前驱结点
while(pos->next)
{
//当前待删除结点
ListNode *cur = pos->next;
if(!occured.count(cur->val))
{
occured.insert(cur->val);
pos = pos -> next;
}
else
{
pos->next = cur -> next;
}
}
//pos -> next = nullptr;
return head;
}
};
合并两个有序链表
将两个升序链表合并为一个新的升序链表并返回,新链表是通过拼接给定的两个链表的所有节点组成的
迭代解法
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode *head = new ListNode();
ListNode *tail = head;
while(l1 != nullptr && l2!= nullptr)
{
if (l1->val > l2->val)
{
tail->next = l2;
l2 = l2->next;
}
else
{
tail->next = l1;
l1 = l1->next;
}
tail = tail -> next;
}
if(l1 !=nullptr) tail->next = l1;
if(l2 !=nullptr) tail->next =l2;
return head->next;
}
};
递归解法
class solution{
public:
ListNode* mergeTwoLists(ListNode *l1, ListNode *l2){
if(l1 == nullptr)
{
return l2;
}
else if(l2 == nullptr){
return l1;
}
else if(l1->val < l2->val){
l1->next = mergeTwoLists(l1->next,l2);
return l1;
}
else
{
l2->next = mergeTwoLists(l2->next,l1);
return l2;
}
}
}
两链表对应位置相加
//参考官方解法,个人写的思路
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode *pre = new ListNode();
ListNode *p =pre;
int m = 0;
int val;
while(l1 || l2) //遍历完两个链表
{
ListNode *cur = new ListNode();
int n1 = l1 ? l1->val : 0; //l1非空,取值l1->val ,否则取值为 0
int n2 = l2 ? l2->val : 0;
val = n1 + n2 + m;
if(m ==1 ) m = 0;
if (val > 9)
{
m = 1;
val = val -10;
}
cur->val = val ;
pre->next = cur;
pre = cur;
if(l1)l1 = l1->next;
if(l2)l2 = l2->next;
}
if(m==1) //当l1,l2均到链表末尾时,仍有进位产生即m==1,此时再新建结点接续
{
ListNode *q = new ListNode(1);
pre->next = q ;
}
return p->next;
}
};
//官方解法
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
ListNode *head = nullptr, *tail = nullptr;
int carry = 0;
while (l1 || l2) {
int n1 = l1 ? l1->val: 0;
int n2 = l2 ? l2->val: 0;
int sum = n1 + n2 + carry;
if (!head) {
head = tail = new ListNode(sum % 10);
} else {
tail->next = new ListNode(sum % 10);
tail = tail->next;
}
carry = sum / 10;
if (l1) {
l1 = l1->next;
}
if (l2) {
l2 = l2->next;
}
}
if (carry > 0) {
tail->next = new ListNode(carry);
}
return head;
}
};
链接:https://leetcode-cn.com/problems/add-two-numbers/solution/liang-shu-xiang-jia-by-leetcode-solution/
回文链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
//利用栈 后进先出 的特性来存储结点,并比较原链表与栈内链表结点val值是否相等
class Solution {
public:
bool isPalindrome(ListNode* head) {
ListNode *p = head;
stack<ListNode > *s = new stack<ListNode>;
int elem;
while(p!= nullptr)
{
s->push(*p);
p = p->next;
}
while(head!=nullptr)
{
elem = s->top().val; //取栈顶元素,取val值
s->pop(); //出栈
if (head->val != elem)
return false;
head = head ->next;
}
return true;
}
};
** 力扣官方解答**
1.取值复制到数组中,比较前后是否相等
class Solution {
public:
bool isPalindrome(ListNode* head) {
vector<int> vals;
while (head != nullptr) {
vals.emplace_back(head->val);
head = head->next;
}
for (int i = 0, j = (int)vals.size() - 1; i < j; ++i, --j) {
if (vals[i] != vals[j]) {
return false;
}
}
return true;
}
};
总的时间复杂度:O(2n) = O(n)O(2n)=O(n)。
2.整个流程可以分为以下五个步骤:
找到前半部分链表的尾节点。
反转后半部分链表。
判断是否回文。
恢复链表。
返回结果。