LeetCode - 206 - 反转链表(reverse-linked-list)

Create by jsliang on 2019-7-13 07:54:49
Recently revised in 2019-7-13 08:42:07

一 目录

不折腾的前端,和咸鱼有什么区别

| 目录 | | --- | | 一 目录 | | 二 前言 | | 三 解题 | | 四 执行测试 | | 五 LeetCode Submit | | 六 解题思路 | | 七 进一步思考 |

二 前言

  • 难度:简单

  • 涉及知识:链表

  • 题目地址:https://leetcode-cn.com/problems/reverse-linked-list/

  • 题目内容

反转一个单链表。	
示例:	
输入: 1->2->3->4->5->NULL	
输出: 5->4->3->2->1->NULL	
进阶:	
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?

三 解题

小伙伴可以先自己在本地尝试解题,再回来看看 jsliang 的解题思路。

  • 解题代码

var reverseList = (head, q = null) => {	
  if (head) {	
    return reverseList(head.next, {	
      val: head.val,	
      next: q,	
    });	
  }	
  return q;	
}

四 执行测试

  • head

let head = {	
  val: 1, next: {	
    val: 2, next: {	
      val: 3, next: {	
        val: 4, next: {	
          val: 5, next: null,	
        },	
      },	
    },	
  },	
};
  • return

{	
  val: 5, next: {	
    val: 4, next: {	
      val: 3, next: {	
        val: 2, next: {	
          val: 1, next: null,	
        },	
      },	
    },	
  },	
}

五 LeetCode Submit

√ Accepted	
  √ 27/27 cases passed (80 ms)	
  √ Your runtime beats 92.17 % of javascript submissions	
  √ Your memory usage beats 6.29 % of javascript submissions (36.1 MB)

六 解题思路

智商是硬伤,知识点也可能是

经过这次解题,jsliang 将链表给标记上了,等到系统学习算法与数据结构的时候,链表是必须搞懂的点之一。

首先,上面题解不是我写出来的,看的是评论区的题解,原代码是:

const reverseList = (head, q = null) => head !== null ? reverseList(head.next, { val: head.val, next: q }) : q;

传说中的一行题解。

然后,怕小伙伴们跟我一样懵逼,jsliang 进行了改编:

var reverseList = (head, q = null) => {	
  console.log(q);	
  if (head) {	
    return reverseList(head.next, {	
      val: head.val,	
      next: q,	
    });	
  }	
  return q;	
}

最后,为了方便小伙伴们理解,jsliangq 的过程打印了出来:

null	
{ val: 1, next: null }	
{ val: 2, next: { val: 1, next: null } }	
{ val: 3, next: { val: 2, next: { val: 1, next: null } } }	
{ val: 4, next: { val: 3, next: { val: 2, next: [Object] } } }	
{ val: 5, next: { val: 4, next: { val: 3, next: [Object] } } }	
{ val: 5, next: { val: 4, next: { val: 3, next: [Object] } } }

嗯,对着 console.log() 来思考这次递归的用意,小伙伴们应该能清楚怎么反转链表了。(虽然下次还是可能写不出,但是没关系,后面大家一起系统学习~)

七 进一步思考

上面使用了递归,下面看看迭代解法:

var reverseList = function(head) {	
  if (head == null || head.next == null) {	
    return head;	
  }	
  var current = head;	
  var previous = null;	
  while (current != null) {	
    next = current.next;	
    current.next = previous;	
    previous = current;	
    current = next;	
  }	
  return previous;	
};

提交结果是:

√ Accepted	
  √ 27/27 cases passed (80 ms)	
  √ Your runtime beats 92.17 % of javascript submissions	
  √ Your memory usage beats 70.6 % of javascript submissions (34.8 MB)

感兴趣的小伙伴可以推演下迭代的思路,在此 jsliang 就不多滴滴啦~


不折腾的前端,和咸鱼有什么区别!

640?wx_fmt=jpeg

jsliang 会每天更新一道 LeetCode 题解,从而帮助小伙伴们夯实原生 JS 基础,了解与学习算法与数据结构。

扫描上方二维码,关注 jsliang 的公众号,让我们一起折腾!

640?wx_fmt=png

jsliang 的文档库 由 梁峻荣 采用 知识共享 署名-非商业性使用-相同方式共享 4.0 国际 许可协议进行许可。
基于https://github.com/LiangJunrong/document-library上的作品创作。
本许可协议授权之外的使用权限可以从 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 处获得。



#include <stdio.h> #include <stdlib.h> #define ERROR -1 #define OK 1 //定义单链表 typedef char ElemType; typedef struct LNode // 结点类型定义 { ElemType data; struct LNode * next; }LNode, *LinkList;//LinkList为结构指针类型 //定义关于单链表的若干操作 //初始化--建空表 void InitList(LinkList *L) { *L = (LinkList)malloc(sizeof(LNode)); (*L)->next=NULL; } //尾插法建表 void create_tail(LinkList *L, int n) { LNode *p, *last; int i; last=(*L); for(i=1; i<=n; i++) { p=(LNode *)malloc(sizeof(LNode)); //产生一个新结点 fflush(stdin); //清空内存 scanf("%c", &p->data); //往新结点的数据域中存入元素 last->next=p; //将新结点接在最后一个结点的后面 last=p; //新结点成为最后一个结点 } last->next=NULL; } //求单链表的长度 int ListLength(LinkList L) { LNode *p; int length; p=L->next; //p指针指向第一个元素所在的结点 length=0; //用来存放单链表的长度 while( p!=NULL ) //结点存在 { p=p->next; //p指针向后移 length++; //个数增加1个 } return length; } //求特定元素的个数 int Count(LinkList L, ElemType x) { LNode *p; int length; p=L->next; //p指针指向第一个元素所在的结点 length=0; //用来计算特定元素的个数 while( p ) //结点存在 { if( p->data ==x) //如果找到特定元素,则个数加1 length ++; p=p->next; //p指针向后移 } return length; } //在第i个元素前插入 int ListInsert_L(LinkList *L, int i, ElemType e) { LNode *p, *s; int j; p=(*L); j=0; while( p &&j<i-1) //如果当前结点存在,且移动次数未达到所需次数(找第i-1个结点) { p=p->next; j++; } if(!p || j>i-1) return ERROR; s=(LNode *)malloc(sizeof(LNode)); //产生一新结点 s->data=e; //往新结点中存入元素 s->next=p->next; p->next=s; //新结点接在p结点之后 return OK; } //删除第i个元素 int ListDelete_L(LinkList *L, int i, ElemType *e) { LNode *p,*q; int j; p=(*L); j=0; while(p->next && j<i-1)//(找第i-1个元素)如果当前结点的下一个结点存在,且移动次数未达到所需次数 { p=p->next; j++; } if(!p->next || j>i-1) return ERROR; q=p->next; p->next=q->next; *e=q->data; free(q); //释放要删除的结点 return OK; } void reverse(LinkList *L) { LNode *p,*q,*r; p=(*L)->next; q=p->next; r=q->next; p->next=NULL; while(q!=NULL) { q->next=p; (*L)->next=q; p=q; q=r; if(r!=NULL) r=q->next; else break; } } void main() { LinkList list1; InitList(&list1); create_tail(&list1, 5); LNode *p; for(p=list1->next; p; p=p->next ) printf("%c ",p->data ); printf("\n"); /* printf("\n========================================\n"); printf("\n单链表的长度:%d\n", ListLength(list1)); printf("\n========================================\n"); printf("单链表中元素c的个数:%d\n", Count(list1, 'c')); printf("\n========================================\n"); ListInsert_L(&list1, 3, 'g'); printf("在第3个元素前插入元素g后,单链表中的元素有:\n"); for(p=list1->next; p; p=p->next ) printf("%c ",p->data ); printf("\n"); printf("\n========================================\n"); ElemType e; ListDelete_L(&list1,4, &e); printf("删除第4个元素后,单链表中的元素有:\n"); for(p=list1->next; p; p=p->next ) printf("%c ",p->data ); printf("\n"); printf("删除掉的元素是:%c\n",e); */ reverse(&list1); for(p=list1->next; p; p=p->next ) printf("%c ",p->data ); }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值