文章:4. 翻转链表.url
链表 链表是一种通过指针串联在一起的线性结构,每个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)
链表的入口节点称为链表的头节点也就是head。
链表类型 单链表 上面定义的就是单链表
双链表 单链表中的指针域只能指向节点的下一个节点。
双链表:每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点。
双链表既可以向前查询也可以向后查询。
循环链表 循环链表,链表首尾相连。
可以用来解决约瑟夫环问题。
链表的存储方式 数组是在内存中连续分布的,但是链表在内存中不是连续分布的。
链表通过指针域的指针链接在内存中的各个节点,所以链表中的节点在内存中不是连续分布的,而是散乱分布在内存中的某地址上,分配机制取决于操作系统的内存管理。
链表的定义 1 2 3 4 5 struct ListNode { int val; ListNode *next; ListNode (int x): val (x),next (NULL ){} }
通过自己定义构造函数初始化节点:
1 ListNode* head = new ListNode (5 );
使用默认构造函数初始化节点:
1 2 ListNode* head = new ListNode (); head->val = 5 ;
所以如果不定义构造函数使用默认构造函数的话,在初始化的时候就不能直接给变量赋值!
链表的操作 删除节点 将需要删除的节点的前一个指针的next 修改为指向需要删除的节点next
C++最好再手动释放需要删除的节点,Java和Python用自己的内存回收机制,不需要自己手动释放
添加节点 1.将新节点的next指针修改为新节点的前一个节点的next
2.将新节点的位置的前一个指针的next指针修改为指向新节点
性能分析 数组(长度固定,改动长度需要重新定义一个新数组)
插入/删除(时间复杂度)O(n)
查询(时间复杂度)O(1)
适用场景: 数据量固定,频繁查询,较少增删
链表(长度不固定,可以动态增删)
插入/删除(时间复杂度)O(1)
查询(时间复杂度)O(n)
适用场景: 数据量不固定,频繁增删,较少查询
其他语言
1 2 3 4 5 6 7 8 9 10 11 12 public class ListNode { int val; ListNode next; public ListNode () {} public ListNode (int val) { this .val = val; } public ListNode (int val,ListNode next) { this .val = val; this .next = next; } }
1 2 3 4 type ListNode struct{ Val int Next *ListNode }
203.移除链表元素 【方法一】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public ListNode removeElements (ListNode head, int val) { while (head != null && head.val == val){ head = head.next; } if (head == null ){ return head; } ListNode pre = head; ListNode cur = head.next; while (cur != null ){ if (cur.val == val){ pre.next = cur.next; }else { pre = cur; } cur = cur.next; } return head; } }
Go语言的话还需要注意语法问题,不是用null
,而是nil
;不是用while
,而是for
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 func removeElements (head *ListNode, val int ) *ListNode { for head != nil && head.Val == val{ head = head.Next; } if (head == nil ){ return head; } pre := head; cur := head.Next; for cur != nil { if (cur.Val == val){ pre.Next = cur.Next; }else { pre = cur; } cur= cur.Next; } return head; }
【方法二】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Solution { public ListNode removeElements (ListNode head, int val) { while (head != null && head.val == val){ head =head.next; } if (head == null ) return head; ListNode dummyNode = new ListNode (); dummyNode.next = head; ListNode cur = head; while (cur != null && cur.next != null ){ if (cur.next.val == val){ cur.next = cur.next.next; }else { cur = cur.next; } } return dummyNode.next; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 func removeElements (head *ListNode, val int ) *ListNode { dummyHead := &ListNode{} dummyHead.Next = head; cur := dummyHead for cur != nil && cur.Next != nil { if cur.Next.Val == val{ cur.Next = cur.Next.Next }else { cur = cur.Next } } return dummyHead.Next }
707.设计链表 文章:代码随想录 (programmercarl.com)
题目:707. 设计链表.url
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 class ListNode { int val; ListNode next; ListNode(){} ListNode(int val){ this .val = val; } } class MyLinkedList { int size ; ListNode head; public MyLinkedList () { size = 0 ; head = new ListNode (0 ); } public int get (int index) { if (index <0 ||index>= size)return -1 ; ListNode dummy = head; for (int i = 0 ; i <= index ;i++){ dummy = dummy.next; } return dummy.val; } public void addAtHead (int val) { addAtIndex(0 ,val); } public void addAtTail (int val) { addAtIndex(size,val); } public void addAtIndex (int index, int val) { if (index > size)return ; if (index <0 )index =0 ; size++; ListNode dummy = head; for (int i = 0 ; i <index ; i++){ dummy = dummy.next; } ListNode add = new ListNode (val); add.next = dummy.next; dummy.next = add; return ; } public void deleteAtIndex (int index) { if (index >= size || index < 0 )return ; size--; if (index ==0 ) { head = head.next; return ; } ListNode dummy = head; for (int i = 0 ;i<index;i++){ dummy = dummy.next; } dummy.next = dummy.next.next; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 type MyLinkedList struct { SingleNode *ListNode Size int } func Constructor () MyLinkedList { return MyLinkedList{&ListNode{},0 } } func (this *MyLinkedList) Get(index int ) int { if index<0 || index >= this.Size || this == nil { return -1 ; } cur := this.SingleNode for i := 0 ; i <= index ;i++{ cur = cur.Next } return cur.Val } func (this *MyLinkedList) AddAtHead(val int ) { this.AddAtIndex(0 ,val) } func (this *MyLinkedList) AddAtTail(val int ) { this.AddAtIndex(this.Size,val) } func (this *MyLinkedList) AddAtIndex(index int , val int ) { if index > this.Size{ return } if index <0 { index = 0 } this.Size+=1 cur := this.SingleNode for i:= 0 ;i<index;i++{ cur = cur.Next } node := &ListNode{val,cur.Next} cur.Next = node } func (this *MyLinkedList) DeleteAtIndex(index int ) { if index >= this.Size || index < 0 { return } this.Size -=1 cur := this.SingleNode for i:= 0 ;i<index;i++{ cur = cur.Next } cur.Next = cur.Next.Next }
206.反转链表 文章:代码随想录 (programmercarl.com)
题目:206. 反转链表 - 力扣(LeetCode)
【方法一】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution { public ListNode reverseList (ListNode head) { ListNode cur = head; ListNode pre = null ; ListNode temp = null ; while (cur != null ){ temp = cur.next; cur.next = pre; pre = cur; cur = temp } return pre; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 func reverseList (head *ListNode) *ListNode { var pre *ListNode cur := head for cur != nil { temp := cur.Next cur.Next = pre pre = cur cur = temp } return pre }
【方法二】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class Solution { public ListNode reverseList (ListNode head) { return reverse(null ,head); } public ListNode reverse (ListNode pre,ListNode cur) { if (cur == null )return pre; ListNode temp = cur.next; cur.next = pre; return reverse(cur,temp); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 func reverse ( prev *ListNode, cur *ListNode) *ListNode{ if cur == nil { return prev } temp := cur.Next cur.Next = prev return reverse(cur,temp) } func reverseList (head *ListNode) *ListNode { return reverse(nil ,head) }
【算法总结】
【语言总结】