题目:
定义一个函数,输入一个单向链表的头节点,反转该链表,并输出反转后的头节点
思路:
- 链表数据结构:
- 单向链表:{value,next}
- 双向链表:{value,prev,next}
- 链表是数组的补充,数组需要一段连续的内存空间,而链表是零散的
- 链表查询慢,新增和删除块;数组查询块,新增和删除较慢
- 反转链表,没有捷径,我们所说的返回一个链表,实际上是返回的头节点
- 链表只能从头部开始遍历,重新设置next 指向即可,即把前一个节点的next指向前一个节点
- 遍历过程中,要存储3个指针 prevNode curNode nextNode
- 时间复杂度O(n)
代码实现:
/*** @description 反转单向链表* @author ykk*/ /*** 单向链表的数据结构*/ export interface ILinkListNode {value: number,next?: ILinkListNode }/*** 根据数组返回一个单向链表* @param arr 数组* @returns 单向链表*/ export function createLinkList(arr:number[]):ILinkListNode{const length = arr.length;if(length === 0) throw new Error('arr is empty')let curNode:ILinkListNode = {value: arr[length -1]}if(length === 1){return curNode}for(let i = length - 2; i >= 0; i--){curNode = {value: arr[i],next: curNode}}return curNode } /*** 反转链表* @param listNode 链表头节点* @returns 返回反转后的链表头节点*/ export function reverseLinkList(listNode:ILinkListNode):ILinkListNode{let preNode: ILinkListNode | undefined = undefinedlet curNode: ILinkListNode | undefined = undefinedlet nextNode:ILinkListNode | undefined = listNodewhile(nextNode){//第一个元素,删掉 next, 防止循环引用if(curNode && !preNode){delete curNode.next}//反转指针if(preNode && curNode){curNode.next = preNode}preNode = curNodecurNode = nextNodenextNode = nextNode?.next}curNode!.next = preNodereturn curNode! }
测试用例:
/*** @description 反转单链表测试* @author ykk */import {ILinkListNode,createLinkList, reverseLinkList} from './reverse-link-list'describe('反转单链表', () =>{it('单个元素',()=>{const node:ILinkListNode = {value: 100}const node1 = reverseLinkList(node)expect(node1).toEqual({value: 100})})it('多个元素',() =>{const node = createLinkList([100,200,300])const node1 = reverseLinkList(node)expect(node1).toEqual({value:300,next: {value: 200,next:{value: 100}}})}) })