题目
输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。
示例 1:
输入:head = [1,3,2]
输出:[2,3,1]
限制:
0 <= 链表长度 <= 10000
代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* reversePrint(struct ListNode* head, int* returnSize){
if(head == NULL)
{
*returnSize = 0;
return NULL;
}
struct ListNode* p = head;
int num = 0;
//怎样判断链表结束
while(p != NULL)
{
p = p->next;
num ++;
printf("%d",num);
}
int *arr = (int *)malloc(sizeof(int)*num);
for(int i = num-1; i >= 0; i--)
{
arr[i] = head->val;
head = head->next;
}
*returnSize = num;
return arr;
}
解法2,链表反序后进行输出
/* 链表反序, 并统计出链表长度 */
struct ListNode *reverseList(struct ListNode *head, int *returnSize) {
if (head == NULL) {
return NULL;
}
struct ListNode *pre = NULL;
struct ListNode *cur = head;
struct ListNode *tmp = NULL;
while (cur != NULL) {
(*returnSize)++;
tmp = cur->next;
cur->next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
int* reversePrint(struct ListNode* head, int* returnSize){
int *res = (int*)malloc(sizeof(int) * 10000);
int i = 0;
*returnSize = 0;
/* 链表反序 */
head = reverseList(head, returnSize);
res = (int*)malloc(sizeof(int) * (*returnSize));
/* 遍历链表, 输出链表元素 */
while (head != NULL) {
res[i++] = head->val;
head = head->next;
}
return res;
}
知识点
1、链表的结构
链表是有一个结构体,结构体内部分为数据部分和指针部分,数据部分为存放的数值,指针部分存放的是指向下一个节点的指针,代码示例如下:
struct node{
int val;//数值部分存放内容为int数值
struct node *next;//指向下一个节点的指针
}
2、创建一个节点
struct Node* temp=(struct node*)malloc(sizeof(struct node));
3、链表操作时一般需要考虑的点
(1)链表尾部新增元素时
-
链表中一个节点都没有,即head== NULL,那么这个节点既是头结点也是尾结点;
-
链表中有节点,
(2)链表中间新增元素,注意不要丢失后面元素
//创建临时节点,申请内存
struct node* temp =(struct node *)malloc(sizeof(struct node));
//节点成员进行赋值
temp->a=a;
temp->next=NULL;
//假如p指向要插入的节点位置
//连接到链表上 1.找到的节点在尾部 2.找到的节点在中间
struct node* end = NULL;//找到尾指针
if (p == end)
{
//尾巴的下一个指向新插入的节点
end->next=temp;
//新的尾巴
end=temp;
}else
{
// 先连后面 (先将要插入的节点指针指向原来找到节点的下一个)
temp->next=p->next;
//后连前面
p->next=temp;
}
注意:数组和链表的区别
对比内容 | 数组 | 链表 |
---|---|---|
内存 | 提前申请大小,在栈中分配的一块连续区域,编译期确定大小,空间利用率低 | 不需提前申请大小,空间动态申请,在堆中分配空间,运行时才能确定大小,空间利用率高 |
访问效率 | 效率很高,时间复杂度可以达到O(1):内存空间连续,访问元素时,直接从数组的首地址处向后偏移就可以访问 | 数据时效率低,时间复杂度为O(N):内存空间分散,所以不具有随机访问性,如要需要访问某个位置的数据,需要从第一个数据开始找起,依次往后遍历 |
插入删除元素效率 | 插入数据和删除数据效率低:插入数据时,待插入位置的的元素和它后面的所有元素需向后移动; 删除数据时,待删除位置后面的所有元素都需要向前移动 | 插入元素和删除元素效率较高 |