代码随想录算法训练营第三天|203.移除链表元素 、707.设计链表 、206.反转链表
一.链表基础
1.最后一个节点的指针域指向null(空指针的意思)。
2.链表在内存中不是连续分布的。
3.链表的长度可以是不固定的,并且可以动态增删, 适合数据量不固定,频繁增删,较少查询的场景。
1 #链表节点的定义 2 class ListNode: 3 def __init__(self, val, next = None): 4 self.val = val 5 self.next = next
java中对象每个对象都指向一个地址,所以递归使用Node类型
1 public class ListNode { 2 // 结点的值 3 int val; 4 5 // 下一个结点 6 ListNode next; 7 8 // 节点的构造函数(无参) 9 public ListNode() { 10 } 11 12 // 节点的构造函数(有一个参数) 13 public ListNode(int val) { 14 this.val = val; 15 } 16 17 // 节点的构造函数(有两个参数) 18 public ListNode(int val, ListNode next) { 19 this.val = val; 20 this.next = next; 21 } 22 }
203. 移除链表元素
【注意】
1.有两种方式:
- 直接使用原来的链表来进行删除操作。
- 设置一个虚拟头结点在进行删除操作——>统一了链表的操作。
2.移除头结点和移除其他结点的操作是不一样的(因为头结点没有前一个结点)。——>将头结点后移动一位
3.移除头结点是一个持续的过程,所以应该用while循环,而不是用if判断; 进行查找删除的时候要注意是否为null(避免空指针异常)。
4.甚至虚拟头结点的时候:注意返回的是dummyNode->next ,而不是head。
【代码】
#在python中判断是否为空用的是:!= None 而不是: !=null
方式一:
1 class Solution(object): 2 def removeElements(self, head, val): 3 """ 4 :type head: ListNode 5 :type val: int 6 :rtype: ListNode 7 """ 8 # 不添加虚拟节点and pre Node方式 9 # 时间复杂度 O(n) 10 # 空间复杂度 O(1) 11 12 while(head and head.val == val): #不是用if 13 head = head.next 14 15 curr = head #如果要删除头结点的下一个结点,就需要从head开始,指向next.next 16 17 while(curr): #万一head为空,就直接返回 18 while(curr.next and curr.next.val == val): #遍历删除 19 curr.next = curr.next.next 20 curr = curr.next 21 22 return head
方式二:
1 # Definition for singly-linked list. 2 # class ListNode(object): 3 # def __init__(self, val=0, next=None): 4 # self.val = val 5 # self.next = next 6 class Solution(object): 7 def removeElements(self, head, val): 8 """ 9 :type head: ListNode 10 :type val: int 11 :rtype: ListNode 12 """ 13 14 dummy_head = ListNode(next = head) #虚拟头结点 15 curr = dummy_head #如果要删除头结点的下一个结点,就需要从head开始,指向next.next 16 17 while(curr.next != None): #万一head为空,就直接返回 18 if(curr.next.val == val): #遍历删除 19 curr.next = curr.next.next 20 21 else: 22 curr = curr.next 23 24 return dummy_head.next #万一head被删除了
707. 设计链表
【注意】
1.遍历列表的时候为什么要定义一个指针?而不是直接操作头指针?
因为我们操作完列表之后,要返回头结点
2.插入结点的时候要注意插入顺序。
3.删除第n个结点的时候,注意是要使n=cur.next
1 class Node(object): 2 def __init__(self, val = 0): 3 self.val = val 4 self.next = None 5 6 class MyLinkedList(object): 7 8 def __init__(self): 9 self.head = Node() #虚拟头结点 10 self.size = 0 #记录链表的大小 11 12 13 def get(self, index): 14 """ 15 :type index: int 16 :rtype: int 17 """ 18 if index < 0 or index >= self.size: 19 return -1 20 21 cur = self.head.next 22 while(index): 23 cur = cur.next 24 index -= 1 25 #for i in range(index) 26 # cur = cur.next 27 return cur.val 28 29 30 def addAtHead(self, val): 31 """ 32 :type val: int 33 :rtype: None 34 """ 35 new_node = Node(val) 36 new_node.next = self.head.next 37 self.head.next = new_node 38 #self.head.next = Node(val,self.head.next) 39 self.size += 1 40 41 42 43 def addAtTail(self, val): 44 """ 45 :type val: int 46 :rtype: None 47 """ 48 new_node = Node(val) 49 cur = self.head #虚拟头结点 50 while(cur.next): 51 cur = cur.next 52 cur.next = new_node 53 self.size += 1 54 55 def addAtIndex(self, index, val): 56 """ 57 :type index: int 58 :type val: int 59 :rtype: None 60 """ 61 if index < 0 : 62 self.addAtHead(val) 63 return 64 elif index == self.size: 65 self.addAtTail(val) 66 return 67 elif index > self.size: 68 return 69 70 node_new = Node(val) 71 pre = self.head 72 while(index): 73 pre = pre.next #位置0号元素,列表中的第一元素 74 index -= 1 75 node_new.next = pre.next 76 pre.next = node_new 77 self.size += 1 78 79 80 def deleteAtIndex(self, index): 81 """ 82 :type index: int 83 :rtype: None 84 """ 85 if index < 0 or index >= self.size: 86 return 87 88 pre = self.head 89 while(index): 90 pre = pre.next #从虚拟头结点开始 91 index -= 1 92 pre.next = pre.next.next 93 self.size -= 1 94 95 96 97 # Your MyLinkedList object will be instantiated and called as such: 98 # obj = MyLinkedList() 99 # param_1 = obj.get(index) 100 # obj.addAtHead(val) 101 # obj.addAtTail(val) 102 # obj.addAtIndex(index,val) 103 # obj.deleteAtIndex(index)
ps:记得之后再看双链表的代码实现
206. 反转链表
【注意】
1.要把 cur->next 节点用tmp指针保存一下。
方式一:迭代法(双指针)
1 # Definition for singly-linked list. 2 # class ListNode(object): 3 # def __init__(self, val=0, next=None): 4 # self.val = val 5 # self.next = next 6 class Solution(object): 7 def reverseList(self, head): 8 """ 9 :type head: ListNode 10 :rtype: ListNode 11 """ 12 cur = head 13 pre = None 14 while(cur != None): 15 temp = cur.next 16 cur.next = pre #反转 17 pre = cur 18 cur = temp 19 return pre
方式二:递归
1 # Definition for singly-linked list. 2 # class ListNode(object): 3 # def __init__(self, val=0, next=None): 4 # self.val = val 5 # self.next = next 6 class Solution(object): 7 def reverseList(self, head): 8 """ 9 :type head: ListNode 10 :rtype: ListNode 11 """ 12 def reverse(pre,cur): 13 #递归结束条件cur = None 14 if not cur: 15 return pre 16 temp = cur.next 17 cur.next = pre #反转 18 19 return reverse(cur, temp) 20 #cur = head 21 #pre = None 22 #while(cur != None): 23 temp = cur.next 24 cur.next = pre #反转 25 #pre = cur 26 #cur = temp 27 return reverse(None, head)
ps:记得之后再看递归从后向前