牛客编程2:输入一个链表,按链表值从尾到头的顺序返回一个ArrayList

10 篇文章 0 订阅
6 篇文章 0 订阅

题目描述

输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) { 
*        }
*  };
*/

5种思路

(1)头插法(改变了链表的方向,即是重新定义了一个方向相反的链表)

(2)利用栈先入后出的特性完成

(3)存下来然后进行数组翻转。

(4)递归

(5)链表就地反转(更改链表的结构,实现链表的逆序,相比数组逆序复杂)

基础知识:

https://www.cnblogs.com/mark2018/p/9374403.html

struct ListNode {
       int val;    //定义val变量值,存储节点值
       struct ListNode *next;   //定义next指针,指向下一个节点,维持节点连接
  }
  • 在节点ListNode定义中,定义为节点为结构变量。
  • 节点存储了两个变量:value 和 next。value 是这个节点的值,next 是指向下一节点的指针,当 next 为空指针时,这个节点是链表的最后一个节点。
  • 注意注意val只代表当前指针的值,比如p->val表示p指针的指向的值;而p->next表示链表下一个节点,也是一个指针。
  • 构造函数包含两个参数 _value 和 _next ,分别用来给节点赋值和指定下一节点

参考:

C++ list 容器

https://www.cnblogs.com/ckings/p/3677561.html

1.头插法

https://blog.csdn.net/Ding_xiaofei/article/details/80530190

编译通过

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) { 
*        }
*  };
*/
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public: 
        vector<int>  printListFromTailToHead(ListNode* listNode) {
    // 头插法构建逆序链表
    ListNode* head = new ListNode(-1);//创建一个什么样的元素呢?-1改为0 编译也通过,创建一个新的元素
    while (listNode != NULL) 
    {
        ListNode* memo = listNode->next;//1
        listNode->next = head->next;//2
        head->next = listNode;//3
        listNode = memo;//4
      //其中的1和4相当于对原来的listNode 每次向右移动一个结点 memo相当于一个暂存链表指针变量,赋给它的值可以实现指向一个新的链表
     // 2和3相当于使用新的listNode结点头插在head的新链表中
    }
    // 构建 ArrayList
   vector<int> ret;//可变容器
    head = head->next;//指向下一个结点
    while (head != NULL) {
     ret.push_back(head->val);
      head=head->next;
    }
    return ret;
}
};

注意上面程序中出现:打印时需要head=head->next  是为了指向第一个结点,如下区分头结点和第一个结点

草稿:

头插法见:

 

头插法: 每次都让新结点在前面

//创建一个n个结点的链表L
void CreateListHead(LinkList *L,int n)
 {
   LinkList p;
   int i;
   srand(time(0));
   *L=(LinList)malloc(sizeof(Node));
   (*L)->next=NULL;//只有头结点
   for(i=0;i<n;i++)
    {
 
    p=(LinkList)malloc(sizeof(Node));
    p->data=rand()%100+1;
    p->next=(*L)->next;
    (*L)->next=p;//在表头插入
    }
 }
明白!

2.压栈

class Solution 
{
public:
    vector<int> printListFromTailToHead(ListNode* head)//向量容器可以放置很多变量
    {
        vector<int> value;//向量
        ListNode *p=NULL;   
        p=head;
        stack<int> stk;//栈   
        while(p!=NULL)  //将链表值压栈
        {
            stk.push(p->val);
            p=p->next;
        } 
        while(!stk.empty())//出栈到容器value中
        {
            value.push_back(stk.top()); 
            stk.pop();  
        }
        return value;
    }
};

3.链表值存下来并进行数组翻转 

class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) 
     {
        vector<int> value;//定义一个动态数组
        ListNode *p=NULL;
        p=head;
        while(p!=NULL)
        {
            value.push_back(p->val);//在数组的最后添加一个数据
            p=p->next;
        }
        //reverse(value.begin(),value.end()); //C++自带的翻转函数
        int temp=0;
        int i=0,j=value.size()-1;
        while(i<j)
        {
            temp=value[i];    //swap函数,swap(value[i],value[j]);
            value[i]=value[j];
            value[j]=temp;
            i++;
            j--;
        }
        return value;
    }
};

4、递归(类似于压栈,找到最后一个位置的值并逐个的往前返回,之前的递归函数还没有运行)

class Solution 
{
public:
    vector<int> value;
    vector<int> printListFromTailToHead(ListNode* head) 
    {
        ListNode *p=NULL;//定义一个链表
        p=head;
        if(p!=NULL)//递归最关键的是基线条件和递归条件
        {
            if(p->next!=NULL)//下一个指向为空说明上一个判断找到的是链表的最后一个位置
            {
                printListFromTailToHead(p->next);
            }
            value.push_back(p->val);
        }
        return value;
    }
};

5.链表就地反转

一次反转相当于执行两次操作:先删除一个结点,再将删除的结点插入到头结点与指向的下一个结点之间

参考:http://www.cnblogs.com/byrhuangqiang/p/4311336.html

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public: 
        vector<int>  printListFromTailToHead(ListNode* head) {
         ListNode* Head1=new ListNode(-1);
         //if (head==NULL)
             // return head;
          ListNode* dummy=new ListNode(-1);
          dummy->next=head;
          ListNode* prev=dummy->next;
          ListNode* pCur=prev->next;
          while (pCur!=NULL) {
             prev->next=pCur->next;
             pCur->next=dummy->next;
             dummy->next=pCur;
             pCur=prev->next;
         }    
            
  
    // 构建 ArrayList
   vector<int> ret;
    Head1=dummy->next;
    while(Head1!=NULL) {
     ret.push_back(Head1->val);
      Head1=Head1->next;
    }
    return ret;
}
};
//错误
不通过
您的代码已保存
段错误:您的程序发生段错误,可能是数组越界,堆栈溢出(比如,递归调用层数太多)等情况引起
case通过率为0.00%

为此需要定义三个指针

C++相关:

https://www.runoob.com/w3cnote/cpp-vector-container-analysis.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heda3

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值