算法与数据结构之链表
一.翻转链表
在翻转专题中提到了,提供地址
文章地址:http://www.cnblogs.com/vhyz/p/7241743.html
二.合并排序链表
21. Merge Two Sorted Lists
Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists、
两个排序链表合并,并且合并后还得是已排序的
利用递归的方式,贴上代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(l1==nullptr )
return l2;
if(l2==nullptr)
return l1;
if(l1->val<l2->val)
{
l1->next = mergeTwoLists(l1->next,l2);
return l1;
}
else{
l2->next = mergeTwoLists(l1,l2->next);
return l2;
}
}
};
该方法特别好,先比较大小,随后将比较好大小的链表与第二个链表继续递归
另一种思路是利用中间临时变量p来循环,思路与递归差不多,贴上代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* head = new ListNode(-1);
ListNode* p = head;
while (l1 != NULL || l2 != NULL)
{
int val1 = l1==NULL ? INT_MAX:l1->val;
int val2 = l2==NULL ? INT_MAX:l2->val;
if (val1 <= val2)
{
p->next = l1;
l1 = l1->next;
}
else
{
p->next = l2;
l2 = l2->next;
}
p = p->next;
}
p = head->next;
delete head;
return p;
}
};
值得注意的一点是,提前用head保存了p的原来位置是很明智的
三.删除排序链表中的重复元素
83. Remove Duplicates from Sorted List
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode* temp = nullptr;
if(head == nullptr)
return nullptr;
ListNode* result = head;
while(head->next)
{
temp = head->next;
if(head->val == temp->val)
{
head->next = temp->next;
}
else
{
head = temp;
}
}
return result;
}
};
四.删除链表中指定值的节点
203. Remove Linked List Elements
Remove all elements from a linked list of integers that have value val.
Example
Given: 1 --> 2 --> 6 --> 3 --> 4 --> 5 --> 6, val = 6
Return: 1 --> 2 --> 3 --> 4 --> 5
递归算法
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
if (head == nullptr) return nullptr;
head->next = removeElements(head->next, val);
return head->val == val ? head->next : head;
}
};
先遍历各个节点直到结尾,然后返回,如果该节点符合要求,那么返回该节点的next指针即下一个节点
循环算法
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode *pseudo_head = new ListNode(0);
pseudo_head->next = head;
ListNode *cur = pseudo_head;
while(cur){
if(cur->next && cur->next->val == val) cur->next = cur->next->next;
else cur = cur->next;
}
return pseudo_head->next;
}
};
创建新节点,该节点指向head,然后再创建节点等于该新节点,将节点cur一直指向下一节点
cur->next = cur->next->next;
注意上面这一行,这一行一直成为我算法的问题,值得学习。
指向节点指针的指针法
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode** list;
list = &head;
while(*list != NULL)
{
if((*list)->val == val)
{
*list = (*list)->next;
}
else
{
list = &((*list) ->next);
}
}
return head;
}
};
五.判断链表是否回文
234. Palindrome Linked List
翻转整个链表再判断
因为链表只有一个,所以要复制链表才能继续,赋值链表要注意空节点
class Solution {
public:
bool isPalindrome(ListNode* head) {
if(head == nullptr)
return true;
ListNode * p = nullptr;
ListNode * q = new ListNode (head->val);
ListNode * t = q;
while(head)
{
ListNode* next = head->next;
head->next = p;
p = head;
head = next;
if(head){
ListNode* temp = new ListNode(head->val);
t->next = temp;
t = t->next;
}
}
while(p)
{
if(p->val != q->val)
return false;
p = p->next;
q = q->next;
}
return true;
}
};
翻转链表与复制链表同时进行
翻转一半链表做判断
class Solution {
public:
bool isPalindrome(ListNode* head) {
if(head == nullptr||head->next == nullptr )
return true;
ListNode * fast = head;
ListNode * slow = head;
while(fast->next !=nullptr && fast->next->next != nullptr)
{
slow = slow->next;
fast = fast->next->next;
}
slow = re(slow->next);
while(slow)
{
if(slow->val != head->val)
return false;
slow = slow->next;
head = head->next;
}
return true;
}
ListNode * re(ListNode * slow)
{
ListNode * p =nullptr;
ListNode * next =nullptr;
while(slow)
{
next = slow->next;
slow->next = p;
p = slow;
slow = next;
}
return p;
}
};
特别注意空节点没有next指针,否则报错!
递归 全局变量法
class Solution {
public:
ListNode * temp;
bool isPalindrome(ListNode* head) {
temp = head;
return check (head);
}
bool check(ListNode * p)
{
if(p == nullptr)
return true;
bool result = check(p->next) && (p->val == temp->val);
temp = temp->next;
return result;
}
};
利用temp的延迟性来打到算法目的
六.给两个已排序的单向链表合成为一个
21. Merge Two Sorted Lists
Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists
递归算法
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if(l1==nullptr )
return l2;
if(l2==nullptr)
return l1;
if(l1->val<l2->val)
{
l1->next = mergeTwoLists(l1->next,l2);
return l1;
}
else{
l2->next = mergeTwoLists(l1,l2->next);
return l2;
}
}
};
循环算法
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode * ans = new ListNode (0);
ListNode * q = ans;
while(l1&&l2)
{
if(l1->val<l2->val)
{
q->next = l1;
l1 = l1->next;
}
else{
q->next = l2;
l2 = l2->next;
}
q=q->next;
}
q->next = l1?l1:l2;
return ans->next;
}
};