链表_数据结构
Linked List
目录
- [环形链表知识点补充2019.2.25](#circle linklist)
- [000.链表数据结构的实现](#linklist implement)
- [876.链表的中点问题](#876.Middle of the Linked List)
- [2.两个链表的反向数学相加](#2.Add Two Numbers)
- [445.两个链表数学相加](#445.Add Two Numbers II)
- [24.交换链表相邻的点](#24.Swap Nodes in Pairs)
- [83.删除有序列表中的重复点](#83.remove the duplication in sorted linked-list)
- [86.分离数组](#86.partition list)
- [203.链表结点的删除](#203.Remove Linked List Elements)
- [328.奇偶链表](#328.Odd Even Linked List)
- [817.链表中元素的分部](#817.Linked List Components)
- [23.合并k个有序链表](#23.Merge k Sorted Lists)
- [725.将链表按要求进行分块](#725.Split Linked List in Parts)
- [148.链表排序,这道题很重要](#148.Sort List)
- [430.多维度的双向链表变成一维度的双向链表](#430.Flatten a multilevel Doubly Linked List)
- [109.将有序链表转换成平衡二叉查找树](#109.convert the sort list to heigh balanced BST)
- [25.一次反转k个链表](#25.reverse linklist node in k-group)
环形链表实现
// 使用环形链表的数据结构来实现
// 首尾结点的链接很机智,可以学习
#include <list>
#include <iostream>
int lastRemaining(unsigned int n,unsigned int m)
{
if(n<1 || m<1)
return -1;
unsigned int i=0;
list<int> numbers;
for(int i=0;i<n;++i) // construct the circle list
numbers.push_back(i);
list<int>::iterator current=numbers.begin();
while(numbers.size()>1){
for(int i=1;i<m;++i){
current++;
if(current==numbers.end()) // implement the circle list end concat the begin
current=numbers.begin()
}
list<int>::iterator next=++current;
if(next==numbers.end())
next=numbers.begin();
--current;
numbers.erase(current);
current=next; // next instead of the start counting point
}
return *(current); // get iterator elements,directed use reference
}
在写数据结构代码是犯了一个非常低级的错误,就是没能在循环中和列表中index 的相对应的关系,区分我们口中的“第几个”。
千万不要尝试去排序链表
链表在寻找其中的元素时要重开始的指针开始进行。
linklist new =l->next; //新建指针new 指向链表l的第一个结点
linklist new=*l //相当于新建一个指针new 指向链表头结点。
头结点,这是一个很重要的知识点。
头结点中包含头指针
头结点放在第一个元素结点之前
头结点是为了操作的方便统一,有了这个头结点对元素的插入和删除就可以和其他元素相同处理
还有一个注意点就是,链表的查找是从第一个结点开始的,不是头结点
链表数据结构的实现
链表数据结构的实现:
1. linklist.h 头文件(linklist.hpp)
2. linklist.cpp 实现
3. main.cpp 测试实现
- 头文件的实现
#ifndef LinkList_hpp
#define LinkList_hpp
#include<stdio.h>
typedef struct node{
int data;
struct node *next;
}NODE;
class LinkList{
private:
NODE *head;
public:
LinkList() {head=NULL;}
~LinkList();
bool clearSqList();
bool isEmpty() {return head=NULL;}
int Length();
bool GetElem(int i,int *e);
int localElem(int e);
bool PriorElem(int cur_e, int *pre_e);
bool NextElem(int cur_e, int *next_e);
bool Insert(int i, int e);
bool Delete(int i, int *e);
NODE * Reverse();
};
#endif /* LinkList_hpp */
- 具体实现的实现 linklist.cpp
// LinkList.cpp
// DataStructure
//
// Created by 邓烁邓烁 on 2018/9/30.
// Copyright © 2018年 邓烁. All rights reserved.
//
// implement the operation
#include "LinkList.hpp"
#include<iostream>
LinkList::~LinkList(){
NODE *p=head;
while(head){
p=head;
head=head->next;
delete(p);
}
}
bool LinkList::clearSqList(){
NODE *p=head;
while(head){
p=head;
head=head->next;
delete(p);
}
return true;
}
int LinkList::Length(){
NODE*p=head;
int j=0;
while(p){
j++;
p=p->next;
}
return j;
}
/*
need the return value ,define a void function
*/
bool LinkList::GetElem(int i, int *e){
NODE *p=head;
p=head;
int j=0;
while(p &&j<i){
p=p->next;
j++;
}
if(!p)
return false;
*e=p->data;
return true;
}
int LinkList::localElem(int e){
NODE *p=head;
p=head;
int index=0;
while(p){
if(p->data==e)
return index;
else p=p->next;
index ++;
}
std::cout<<"元素不存在列表中"<< std::endl;
exit(1);
}
bool LinkList::PriorElem(int cur_e, int *pre_e)
{
NODE *p = head;
if (p->data == cur_e) return false;//是头结点,不存在上一个元素
while (p->next != NULL)
{
if (p->next->data == cur_e)
{
*pre_e = p->data;
return true;
}
else
p = p->next;
}
return false;//遍历完不存在或者只有一个头结点
}
bool LinkList::NextElem(int cur_e, int *next_e)
{
NODE *p = head;
if (head == NULL || head->next == NULL) return false;
while (p->next != NULL)
{
if (p->data == cur_e)
{
*next_e = p->next->data;
return true;
}
else
p = p->next;
}
return false;
}
/*
insert elements in position e
*/
bool LinkList::Insert(int i, int e)
{
NODE *p = head,*s;
int j = 0;
if (i == 0)
{
s = (NODE *)new NODE[1]; //new a node from the memory
s->data = e;
s->next = p;
head = s;
return true;
}
while (p&&j < i - 1)
{
p = p->next;
j++;
}
if (p == NULL)
return false;//到队尾了
s= (NODE *)new NODE[1];
// this three statement is core code
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
bool LinkList::Delete(int i, int *e)
{
NODE *p = head, *s;
if (p == NULL) return false;
int j = 0;
if (i == 0)
{
head = head->next;
*e = p->data;
delete p;
p = NULL;
return true;
}
while (p&&j < i - 1)
{
j++;
p = p->next;
}
if (p == NULL)
return false;
s = p->next;
p->next = p->next->next;
*e = s->data;
delete s; // it's mean free s from memory
s = NULL;
return true;
}
NODE* LinkList::Reverse()
{
if (head == NULL || head->next == NULL) return head;
NODE *p = head,*q=head->next,*r;
head->next = NULL;
while (q)
{
r = q->next;
q->next = p;
p = q;
q = r;
}
head = p;
return head;
}
- 编写用例代码来实现 main.cpp
// main.cpp
// DataStructure
//
// Created by 邓烁邓烁 on 2018/9/30.
// Copyright © 2018年 邓烁. All rights reserved.
//
// 编写测试用例来检测代码的正确性
#include <iostream>
#include"LinkList.hpp"
using namespace std;
int main()
{
int a = 0;
int *p = &a;
LinkList li;
li.Insert(0, 5);
li.Insert(1, 4);
li.Insert(2, 12);
li.Insert(3, 5);
li.Insert(3, 6);
li.Insert(1, 7);
cout <<"链表长度"<< li.Length()<<endl;
cout << "各个元素的值是:";
for (int i = 0;i < li.Length();i++)//遍历该链表
{
if (li.GetElem(i, p))
cout << *p<<" ";
}
cout << endl;
cout << "反转后各个元素的值是:";
NODE* re_li=li.Reverse();
while (re_li)
{
cout << re_li->data << " ";
re_li = re_li->next;
}
cout << endl;
}
链表中结点
- 未实现版本,要再考虑一下
/**
* 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<int> list_array;
int num=0;
while(head!=NULL){
head=head->next;
num++;
}
int middle=num/2;
int j=0;
while(head!=NULL && j<middle){
head=head->next;
j++;
}
return head;
}
};
- 双指针版本 AC
lass Solution {
public:
ListNode* middleNode(ListNode* head) {
struct ListNode *start=head;
struct ListNode *end=head;
if(head==NULL){
return head;
}else if(!start->next){ //only one node
return start;
}else if(!end->next->next){ //only two node
return start->next;
}
while(start!=NULL && end!=NULL && end->next!=NULL){
start=start->next;
end=end->next->next;
if(!end->next){
return start;
}
if(start->next && !end->next->next){
return start->next;
}
}
return start; // 我认为这一句完全不用加
}
};
2.Add Two Numbers
两个链表的反向数学运算
// 解法缺少一个0 结点
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
stack<int> s1;
stack<int> s2;
ListNode *helper=new ListNode(0);
ListNode *cur=helper;
cur->next=NULL;
while(l1){
s1.push(l1->val);
l1=l1->next;
}
while(l2){
s2.push(l2->val);
l2=l2->next;
}
int flag=0;
while(!s1.empty() || !s2.empty()){
int num_l1=0;
if(!s1.empty()){
num_l1=s1.top();
s1.pop();
}
int num_l2=0;
if(!s2.empty()){
num_l2=s2.top();
s2.pop();
}
ListNode *temp=new ListNode((num_l1+num_l2+flag)%10);
cur->next=temp;
cur=temp;
flag=num_l1+num_l2+flag>=10;
}
return helper;
}
};
另外一种直接进行链表的直接推进
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
// 题意可以认为是实现高精度加法
ListNode *head = new ListNode(0);
ListNode *ptr = head;
int carry = 0;
while (true) {
if (l1 != NULL) {
carry += l1->val;
l1 = l1->next;
}
if (l2 != NULL) {
carry += l2->val;
l2 = l2->next;
}
ptr->val = carry % 10;
carry /= 10;
// 当两个表非空或者仍有进位时需要继续运算,否则退出循环
if (l1 != NULL || l2 != NULL || carry != 0) {
ptr = (ptr->next = new ListNode(0));
} else break;
}
return head;
}
};
两个链表的数学运算
445.Add Two Numbers II
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int num1=list2number(l1);
int num2=list2number(l2);
struct ListNode list_node;
list_node=number2list(num1+num2);
return list_node;
}
int list2number(ListNode *head){
if(head==NULL) return 0;
int value=0;
while(!head){
value=10*value;
value+=head->val;
head=head->next;
}
return value;
}
# 添加头结点的思路是对的
# 但是好像就是链表的初始化有点问题
ListNode* number2list(int num){
struct ListNode num_list;
int num_node;
while(num>0){
num_node=num%10;
num=int(num/10);
struct ListNode head;
head->val=num_node;
head->next=num_list;
num_list=head;
}
return num_list;
}
};
copy from other author
- 主要是利用两个栈来实现,和进制进1时如何处理。
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
stack<int> s1;
stack<int> s2;
while(l1){
s1.push(l1->val);
l1=l1->next;
}
while(l2){
s2.push(l2->val);
l2=l2->next;
}
ListNode* cur=NULL;
int c=0; //define a flag ,if value big than 10
while(!s1.empty() || !s2.empty()){
int value1=0;
if(!s1.empty()){
value1=s1.top();
s1.pop();
}
int value2=0;
if(!s2.empty()){
value2=s2.top();
s2.pop();
}
ListNode* temp=new ListNode((value1+value2+c)%10);
temp->next=cur;
cur=temp;
c=(value1+value2+c)>=10; // a true or false statement
}
if(c==1){
ListNode*temp=new ListNode(1);
temp->next=cur;
cur=temp;
}
return cur;
}
};
24.Swap Nodes in Pairs
链表相邻结点的交换
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
# 我自己的思路实现判定结点是否存在,直接在原地进行指针的交换,实现元素顺序的交换,在编程实现中成功的将自己给绕晕
# 下面解题方法的重点和启发点在于/;新建了一个辅助用的头结点来进行添加操作 new listnode (0);这在交换过程中非常有用,直接利用next指针进行添加元素即可。
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(head==NULL || head->next==NULL){
return head;
}
ListNode *ret=head;
ListNode *helper=new ListNode(0);
ListNode *cur=helper;
while(ret && ret->next){
ListNode *next=ret->next->next;
cur->next=ret->next;
cur=cur->next;
cur->next=ret;
cur=cur->next;
cur->next=NULL;
ret=next;
}
if(ret) cur->next=ret; # 单剩一个结点时 !ret->next 添加最后一个结点
return helper->next;
}
};
83.remove the duplication in sorted linked-list
// 这里面又一个非常重要的知识点就是
// 链表进行修改的时候,要把头结点进行备份复制
// 对 复制的结点进行修改操作,最后直接返回头结点就可以
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if(head==NULL|| head->next==NULL)
return head;
ListNode *temp=head;
while(temp->next){
if((temp->next)->val==temp->val)
{
ListNode *delNode=temp->next;
temp->next=temp->next->next;
delete(delNode); //内存结点的释放
//temp=prev->next;
}
else{
temp=temp->next;
}
}
return head;
}
};
// 较慢的版本,可能是 且语句
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode* cur = head;
while (cur) {
while (cur->next && cur->val == cur->next->val)
cur->next = cur->next->next;
cur = cur->next;
}
return head;
}
};
// 这个是删除重复点(两个结点都删除),比较鲁棒的代码
struct ListNode
{
int val;
ListNode next;
};
void DeleteDuplication(ListNode **PHead){
if(PHead==nullptr || *PHead==nullptr)
return;
ListNode *preNode=nullptr;
ListNode *pNode=*PHead;
while(pNode !=nullptr){
ListNode *pNext=pNode->next;
bool NeedDelete=false;
if(pNext!=nullptr && pNext->val==pNode->val)
NeedDelete=true;
if(!NeedDelete){
preNode=pNode; // 保留要删除结点的前一个结点
pNode=pNode->next;
}
// 需要删除
else{
int value=pNode->val;
ListNode *nodeToBeDel=pNode;
while(nodeToBeDel!=nullptr && nodeToBeDel->val==value){
pNext=nodeToBeDel->next;
delete nodeToBeDel;
nodeToBeDel=nullptr;
nodeToBeDel=pNext; // 删除第二个结点
}
if(preNode==nullptr)
*PHead=pNext;
else
preNode->next=pNext;
pNode=pNext;
}
}
}
86.partition list
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
// 这个版本的结果是运行时间超过了限制
// time limited exceed
// 都是一些基础问题,空结点如何定义
// 怎么实现链表之间的链接
class Solution {
public:
ListNode* partition(ListNode* head, int x) {
ListNode *cur=head;
ListNode *tmp1=head;
ListNode *tmp2=head;
while(cur){
if(cur->val<x){
tmp1->next=cur;
tmp1=head;
}
else{
tmp2->next=cur;
tmp2=cur;
}
cur=cur->next;
}
tmp1->next=tmp2;
return head->next;
}
};
// 可以AC,但是时间效率太差
// 这个也就是我的解题思路
ListNode *partition(ListNode *head, int x) {
ListNode node1(0), node2(0); // 学会如何定义一个空结点???
ListNode *p1 = &node1, *p2 = &node2;
while (head) {
if (head->val < x)
p1 = p1->next = head;
else
p2 = p2->next = head;
head = head->next;
}
p2->next = NULL;
p1->next = node2.next; //注意结点这只能.next 不能->next;
return node1.next;
}
203.Remove Linked List Elements
// 链表中结点的删除
/*
* 注意多种情况的讨论
* 1.链表只有一个结点,删除后,头结点要指向null
* 2.删除的结点是 尾结点
* 3.正常结点进行删除
*/
// 结构化定义结点
struct ListNode
{
int m_value;
ListNode *next;
};
void deleteLinkListNode(ListNode ** pListHead,ListNode *pToBeDeleted){
if(pListHead==NULL)
return;
// 借用下一个结点,来覆盖删除本结点,非常好用的方法。
if(pToBeDeleted->next!=NULL){
ListNode p_next=pToBeDeleted->next;
pToBeDeleted->m_value=p_next->m_value;
pToBeDeleted->next=p_next->next;
// 释放空结点
delete p_next;
p_next=NULL
}
// 如果只有一个结点
else if(*pListHead==pToBeDeleted){
delete pToBeDeleted;
pToBeDeleted=NULL;
*pListHead=NULL;
}
// 删除尾结点
else{
ListNode cur_node=*pListHead;
// 一个一个传递找到尾结点
while(cur_node->next!=pToBeDeleted){
cur_node=cur_ndoe->next;
}
cur_node->next=NULL;
// 删除释放结点
delete pToBeDeleted;
pToBeDeleted=NULL;
}
}
ListNode *removeElements(ListNode *head, int val)
{
ListNode **list = &head;
while (*list != nullptr)
{
if ((*list)->val == val)
{
*list = (*list)->next;
}
else
{
list = &(*list)->next;
}
}
return head;
}
//class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* pre = NULL;
ListNode* loop = head;
while(loop) {
if (loop->val == val) {
if (pre == NULL) {
head = loop->next;
delete loop;
loop = head;
} else {
pre->next = loop->next;
delete loop;
loop = pre->next;
}
} else {
pre = loop;
loop = loop->next;
}
}
return head;
}
};
// 还有一个递归的思路
// 这个估计不能应用于循环链表,必须有一个结束递归的条件(尾指针为NULL)
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
if (head == NULL) return NULL;
head->next = removeElements(head->next, val);
return head->val == val ? head->next : head;
}
};
// 新建一个 dummy伪结点,将头结点放在伪结点后面,修改伪结点以后的元素
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
// more easy
ListNode *dummy=new ListNode(0);
dummy->next=head; //伪结点连接上头结点
head=dummy; // 伪结点作为头结点,只修改伪结点以后的结点,伪结点是不改变的,最后进行返回即可
while(head->next!=NULL){
if(head->next->val==val){
head->next=head->next->next;
}
else{
head=head->next;
}
}
return dummy->next;
}
};
328.Odd Even Linked List
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
// 这个需要记忆,就是方法的纯记忆
class Solution {
public:
ListNode* oddEvenList(ListNode* head) {
if(head==NULL)
return head;
else{
ListNode *odd=head,*even=head->next,*dummy_even=even; //保留原始的偶结点初结点
while(even && even->next){
odd->next=odd->next->next;
even->next=even->next->next;
odd=odd->next;
even=even->next;
}
odd->next=dummy_even;
}
return head;
}
};
817.Linked List Components
// 我的思路:1.先判断两个元素
// 2.判断这个两个元素是否同时在这个G中(我当时想到了循环判断个python中的字典变量)
// 但是没有想到c++中可以利用关联容器来进行实现
class Solution {
public:
int numComponents(ListNode* head, vector<int>& G) {
unordered_set<int> G_set (G.begin(),G.end()); //创建一个关联容器 set,并且使用哈希函数组织的set
int result=0;
while(head){
if(G_set.count(head->val) && (head->next==NULL || !G_set.count(head->next->val))) // .count()函数返回0,1 int值 ,表示key是否存在
result++;
head=head->next;
}
return result;
}
};
23.Merge k Sorted Lists
// 按照自己的想法来写的
// 现将所有的链表值 放入一个vector中
// 排序后,再新建一个链表,将点一个个再添加到链表的tail
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
vector<int> container;
for(int i=0;i<lists.size();i++){
while(lists[i]){
container.push_back(lists[i]->val);
lists[i]=lists[i]->next;
}
}
vector<int> sort (container.begin(),container.end()); //这返回一个iterator而不是一个排好序的vector 就是这一个问题
ListNode *head=new ListNode(0);
ListNode *dummy=head;
for(int i=0;i<sort.size();i++){
ListNode *node=new ListNode(0);
node->val=sort[i];
node->next=NULL;
head->next=node;
head=node;
}
return dummy->next;
}
};
// 还是自己的想法,简单的进行修改
//修改通过版,20ms, faster than 70%
// 还要进行时间和空间复杂度的分析
// O(m x n) m是行数,n是一个链表最多的个数
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
vector<int> con;
for(int i=0;i<lists.size();i++){
while(lists[i]){
con.push_back(lists[i]->val);
lists[i]=lists[i]->next;
}
}
std::sort(con.begin(),con.end()); 直接使用标准库的排序来实现升序排序
ListNode *head=new ListNode(0);
ListNode *dummy=head;
for(int i=0;i<con.size();i++){
ListNode *node=new ListNode(0);
node->val=con[i];
node->next=NULL;
head->next=node;
head=node;
}
return dummy->next;
}
};
// 50ms
// 一个基于 merge two sortd list的解法,很有思想
ListNode *mergeKLists(vector<ListNode *> &lists) {
if(lists.empty()){
return nullptr;
}
while(lists.size() > 1){
lists.push_back(mergeTwoLists(lists[0], lists[1]));
lists.erase(lists.begin());
lists.erase(lists.begin());
}
return lists.front();
}
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;
}
}
725.Split Linked List in Parts
// 自己的想法
class Solution {
public:
vector<ListNode*> splitListToParts(ListNode* root, int k) {
vector<ListNode*>result;
int number=0;
while(root){
root=root->next;
number++;
}
if(number<=k){
for(int i=0;i<k;k++){
if(root!=NULL){
ListNode*tmp=root;
root=root->next;
result.push_back(tmp);
}
// 接入空结点
else{
ListNode *tmp=new ListNode();
result.push_back(tmp);
}
}
}
//问题在于当这个链表中的元素大于要分隔的部分个数时,如何进行 切分链表中的元素
// 是用循环,还是利用指针??
else{
}
}
};
// 参考一下别人的版本
class Solution {
public:
vector<ListNode*> splitListToParts(ListNode* root, int k) {
vector<ListNode*> parts(k, nullptr);
int len = 0;
for (ListNode* node = root; node; node = node->next) // 这个改成while循环就不对,需要深度思考一下
len++;
int n = len / k, r = len % k; // n : minimum guaranteed part size; r : extra nodes spread to the first r parts;
ListNode* node = root, *prev = nullptr;
for (int i = 0; node && i < k; i++, r--) {
parts[i] = node;
for (int j = 0; j < n + (r > 0); j++) {
prev = node;
node = node->next;
}
prev->next = nullptr;
}
return parts;
}
};
148.Sort List
//这道题1.分而治之的思想2.递归的思想3.两个有序链表合并 都需要仔细的去学习理解
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
if(!head || !head->next) return head;
// clac the linked list length
ListNode *cur=head;
int length=0;
while(cur){
cur=cur->next;
length++;
}
ListNode dummy(0);
dummy.next=head;
ListNode *left,*right,*tail;
for(int step=1;step<length;step<<=1){ // step<<=1 loop的含义?
cur=dummy.next;
tail=&dummy;
while(cur){
left=cur;
right=split(left,step);
cur=split(right,step);
tail=merge(left,right,tail);
}
}
return dummy.next;
}
private:
ListNode *split(ListNode *head,int n){
for(int i=1;i<n&&head;i++) head=head->next;
if(!head) return NULL;
ListNode *second=head->next;
head->next=NULL;
return second;
}
ListNode *merge(ListNode *l1,ListNode *l2,ListNode *head){
ListNode *cur=head;
while(l1&&l2){
if(l1->val>l2->val){
cur->next=l2;
cur=l2;
l2=l2->next;
}
else{
cur->next=l1;
cur=l1;
l1=l1->next;
}
}
cur->next=(l1?l1:l2);
while(cur->next)
cur=cur->next;
return cur;
}
};
// 当然合并两个有序链表,还有一种简单容易理解的方法
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;
}
}
430.Flatten a multilevel Doubly Linked List
/*
// Definition for a Node.
class Node {
public:
int val = NULL;
Node* prev = NULL;
Node* next = NULL;
Node* child = NULL;
Node() {}
Node(int _val, Node* _prev, Node* _next, Node* _child) {
val = _val;
prev = _prev;
next = _next;
child = _child;
}
};
*/
// 自己理解深度还是有一点差距的
// 自己可以想清楚这个思路的完成
// 但是一转换到代码的实现,就会出现很多错误和过不去的“坎”
class Solution {
public:
Node* flatten(Node* head) {
Node *cur=head;
Node *cur_next;
while(cur)
{
if(cur->child){
cur_next=cur->next;
cur->next=flatten(cur->child);
cur->child=NULL; // 一维后 all child become null
cur->next->prev=cur; //双向链表的链接
while(cur->next){
cur=cur->next;
}
cur->next=cur_next;
if(cur_next){
cur_next->prev=cur; // 双向链表的链接
}
}
else{
cur=cur->next;
}
}
return head;
}
};
109.convert the sort list to heigh balanced BST
// perfect code
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* sortedListToBST(ListNode* head) {
return RecursionListToBST(head,NULL);
}
TreeNode* RecursionListToBST(ListNode* head,ListNode *tail){
// linklist is empty
if(head==tail)
return NULL;
// only one node in the tree
if(head->next==tail){
TreeNode *root=new TreeNode(head->val);
return root;
}
// search the middle node
// excllent code segment need memorize.
ListNode *mid=head;
ListNode *temp=head;
while(temp!=tail && temp->next!=tail){
mid=mid->next;
temp=temp->next->next;
}
TreeNode *root=new TreeNode(mid->val);
root->left=RecursionListToBST(head,mid);
root->right=RecursionListToBST(mid->next,tail);
return root;
}
};
25.reverse linklist node in k-group
/*
* 分析思路:
* 1.当链表的长度大于k的时候,直接返回原链表,输入的k是小于等于链表的长度
* 2.现将链表分成k个groups,对每个groups中的内容进行反转
* 3.在保留原结点(dummy)的情况下,再将结点进行结合起来
*/
// 主要是虚结点dummy node 的设立
// 还有就是 编写 reverse list
// 用递归的方法来解决感觉好一点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
auto node=head;
for(int i=0;i<k;++i){
if(!node)
return head;
node=node->next;
}
auto new_head=reverse(head,node);
head->next=reverseKGroup(node,k);
return new_head;
}
private:
ListNode *reverse(ListNode *first,ListNode *last){
ListNode *prev=last;
// 交换元素这一块,不是很懂 看的有点懵
while(first!=last){
auto temp=first->next;
first->next=prev;
prev=first;
first=temp;
}
return prev;
}
};
// 这个解法是利用循环iteration 来实现
// 但是效率并没有比递归好很多,只是有一点点改进
class Solution {
public:
ListNode *reverseKGroup(ListNode *head, int k) {
if(head==NULL||k==1) return head;
int num=0;
ListNode *preheader = new ListNode(-1);
preheader->next = head;
ListNode *cur = preheader, *nex, *pre = preheader;
while(cur = cur->next)
num++;
while(num>=k) {
cur = pre->next;
nex = cur->next;
for(int i=1;i<k;++i) {
cur->next=nex->next;
nex->next=pre->next;
pre->next=nex;
nex=cur->next;
}
pre = cur;
num-=k;
}
return preheader->next;
}
};
关于链表的一些问题
1.reverse linklist 注意结点的反转存储的问题
2.partition linklist dummy结点的巧妙运用
3.reverse linklist ii java,C++是两种完全不同的实现方法
不要用狭隘的眼光看待不了解的事物,自己没有涉及到的领域不要急于否定.
每天学习一点,努力过好平凡的生活.