题目描述
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
理清思路
方法一 尾填数组法
尾填数组法是指正向遍历链表,将节点数据从数组的尾部开始填入。
- 第一次遍历链表,计算出链表的长度size
- malloc分配size大小的内存
- 第二次遍历链表,获取节点数据,并从数组的尾部开始填充节点数据
- 最后,返回数组即可。
方法二 递归法
递归法,首先一直递归到链表尾部,然后开始返回,每返回一层,获取该节点数据。
- 第一次遍历链表,计算出链表的长度size
- 分配内存空间
- 开始递归遍历链表
- 最后返回数组
方法三 栈
栈,具有先进后出的特性,利用栈原理可以很好的解决此题。
- 构建栈结构,并实现压栈、出栈等函数
- 首先遍历链表,计算出链表长度
- 分配返回数组的内存空间
- 创建栈空间
- 再次遍历链表,按顺序将节点数据压入栈中
- 出栈,将栈元素保存在返回数组中
- 最后,返回数组
代码实现
方法一 尾填数组法
int* reversePrint(struct ListNode* head, int* returnSize){
struct ListNode *ptr;
int size = 0;
int *arr = NULL;
if(head == NULL)
{
*returnSize = 0;
return NULL;
}
ptr = head;
//首先遍历一遍链表,计算出链表的长度
while(ptr != NULL)
{
size++;
ptr = ptr->next;
}
*returnSize = size;
arr = (int *)malloc(sizeof(int)*size);
if(arr == NULL)
{
printf("malloc failed!\n");
*returnSize = 0;
return NULL;
}
//再遍历一遍链表,获取节点数据
ptr = head;
size--;
while(ptr != NULL)
{
arr[size] = ptr->val;
ptr = ptr->next;
size--;
}
return arr;
}
方法二 递归法
void recurve(struct ListNode* node , int *returnSize,int *arr)
{
if(node == NULL)
{
return;
}
recurve(node->next,returnSize,arr);
arr[(*returnSize)++] = node->val;
}
int* reversePrint(struct ListNode* head, int* returnSize){
struct ListNode* ptr = NULL;
int size;
int *arr = NULL;
if(head == NULL)
{
*returnSize = 0;
return NULL;
}
//首先遍历链表,计算出链表长度
ptr = head;
while(ptr != NULL)
{
size++;
ptr = ptr->next;
}
//分配内存空间
arr = (int *)malloc(sizeof(int)*size);
if(arr == NULL)
{
printf("malloc failed!\n");
*returnSize = 0;
return NULL;
}
*returnSize = 0;
//递归遍历链表
recurve(head,returnSize,arr);
return arr;
}
递归之前记得将returnSize初始化为0*returnSize = 0;
,否则returnSize存有随机值,运行时会出现越界操作。
方法三 栈
struct stack{
int top;
int *list;
};
//创建栈空间
struct stack* create_stack(int size)
{
struct stack *stk = NULL;
if(size == 0)
{
return NULL;
}
stk = (struct stack *)malloc(sizeof(struct stack));
if(stk == NULL)
{
return NULL;
}
stk->top = -1;
stk->list = (int *)malloc(sizeof(int)*size);
if(stk->list == NULL)
{
return NULL;
}
return stk;
}
//压栈操作
void stack_push(struct stack *stk,int val)
{
if(stk == NULL)
{
return NULL;
}
stk->list[++(stk->top)] = val;
}
//弹栈操作
int stack_pop(struct stack *stk)
{
if(stk == NULL)
{
return NULL;
}
return stk->list[(stk->top)--];
}
//释放栈空间
void free_stack(struct stack *stk)
{
if(stk == NULL)
{
return NULL;
}
free(stk->list);
free(stk);
}
int* reversePrint(struct ListNode* head, int* returnSize){
int size = 0;
struct stack *mystack;
struct ListNode* ptr = NULL;
int *arr = NULL;
int i = 0;
if(head == NULL)
{
*returnSize = 0;
return NULL;
}
//首先遍历链表,计算出链表的长度
ptr = head;
while(ptr != NULL)
{
size++;
ptr = ptr->next;
}
*returnSize = size;
//分配返回数组内存空间
arr = (int *)malloc(sizeof(int)*size);
if(arr == NULL)
{
printf("malloc arr failed!\n");
*returnSize = 0;
return NULL;
}
//分配栈空间
mystack = create_stack(size);
//再次遍历链表,将节点数据压入栈中
ptr = head;
while(ptr != NULL)
{
stack_push(mystack,ptr->val);
ptr = ptr->next;
}
//将栈中数据弹出,填充到返回数组中
for(i = 0; i < size; i++)
{
arr[i] = stack_pop(mystack);
}
return arr;
}
实现弹栈算法时,注意将stk->top = -1;
,可以巧妙避免越界操作。