今日任务
● 链表理论基础
● 203.移除链表元素
● 707.设计链表
● 206.反转链表
链表理论基础
建议:了解一下链接基础,以及链表和数组的区别
文章链接:https://programmercarl.com/%E9%93%BE%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html
链表的存储方式
了解完链表的类型,再来说一说链表在内存中的存储方式。
数组是在内存中是连续分布的,但是链表在内存中可不是连续分布的。
链表是通过指针域的指针链接在内存中各个节点。
所以链表中的节点在内存中不是连续分布的 ,而是散乱分布在内存中的某地址上,分配机制取决于操作系统的内存管理。
203.移除链表元素
建议: 本题最关键是要理解 虚拟头结点的使用技巧,这个对链表题目很重要。
题目链接/文章讲解/视频讲解::https://programmercarl.com/0203.%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8%E5%85%83%E7%B4%A0.html
思路:设置虚拟头结点,统一操作,从头遍历,满足条件则删除
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */ class Solution { public ListNode removeElements(ListNode head, int val) { if(head == null){ return head; } ListNode dummy = new ListNode(-1,head); ListNode pre = dummy; ListNode cur = pre.next; while(cur != null){ if(cur.val == val){ pre.next = cur.next; }else{ pre = cur; } cur = cur.next; } return dummy.next; } }
感慨:两年前考研前刷过的题目,现在用java又刷一次。哎
递归:
class Solution { public ListNode removeElements(ListNode head, int val) { if(head==null) return null; head.next=removeElements(head.next,val); if(head.val==val){ return head.next; }else{ return head; } } }
707.设计链表
建议: 这是一道考察 链表综合操作的题目,不算容易,可以练一练 使用虚拟头结点
题目链接/文章讲解/视频讲解:https://programmercarl.com/0707.%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8.html
思路:定义不会写,照抄;其他自己写方法
单链表:
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) { ListNode cur = head; if(index < 0 || index >= size){ return -1; } for(int i = 0; i <= index; i++){ cur = cur.next; } return cur.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 < 0){ index = 0; } if(index > size){ return; } size++; ListNode pre = head; for (int i = 0; i < index; i++) { pre = pre.next; } ListNode cur = new ListNode(val); cur.next = pre.next; pre.next = cur; } public void deleteAtIndex(int index) { if(index < 0 || index >= size){ return; } size--; if(index == 0){ head = head.next; return; } ListNode pre = head; for(int i = 0; i < index; i++){ pre = pre.next; } pre.next = pre.next.next; } } /** * Your MyLinkedList object will be instantiated and called as such: * MyLinkedList obj = new MyLinkedList(); * int param_1 = obj.get(index); * obj.addAtHead(val); * obj.addAtTail(val); * obj.addAtIndex(index,val); * obj.deleteAtIndex(index); */
双链表自己想:
class ListNode{ int val; ListNode next,prev; ListNode() {}; ListNode(int val){ this.val = val; } } class MyLinkedList { int size; ListNode head,tail; public MyLinkedList() { this.size = 0; this.head = new ListNode(0); this.tail = new ListNode(0); head.next=tail; tail.prev=head; } public int get(int index) { if(index < 0 || index >= size){ return -1; } ListNode cur = this.head; if(index >= size / 2){ cur = tail; for(int i = 0;i < size -index; i++){ cur = cur.prev; } }else{ for(int i = 0; i <= index; i++){ cur = cur.next; } } return cur.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 cur = this.head; for(int i = 0; i < index; i++){ cur = cur.next; } ListNode newNode = new ListNode(val); newNode.next = cur.next; newNode.prev = cur; cur.next.prev = newNode; cur.next = newNode; } public void deleteAtIndex(int index) { if(index < 0 || index >= size){ return; } size--; ListNode pre = this.head; for(int i = 0; i < index; i++){ pre = pre.next; } pre.next.next.prev = pre; pre.next = pre.next.next; } } /** * Your MyLinkedList object will be instantiated and called as such: * MyLinkedList obj = new MyLinkedList(); * int param_1 = obj.get(index); * obj.addAtHead(val); * obj.addAtTail(val); * obj.addAtIndex(index,val); * obj.deleteAtIndex(index); */
206.反转链表
题目链接/文章讲解/视频讲解:https://programmercarl.com/0206.%E7%BF%BB%E8%BD%AC%E9%93%BE%E8%A1%A8.html
思路:1)递归: 递归出口,只剩1个结点,直接返回 。后边忘了,不会写
// 从后向前递归 class Solution { ListNode reverseList(ListNode head) { // 边缘条件判断 if(head == null) return null; if (head.next == null) return head; // 递归调用,翻转第二个节点开始往后的链表 ListNode last = reverseList(head.next); // 翻转头节点与第二个节点的指向 head.next.next = head; // 此时的 head 节点为尾节点,next 需要指向 NULL head.next = null; return last; } }
2)双指针:
// 双指针 class Solution { public ListNode reverseList(ListNode head) { ListNode prev = null; ListNode cur = head; ListNode temp = null; while (cur != null) { temp = cur.next;// 保存下一个节点 cur.next = prev; prev = cur; cur = temp; } return prev; } }标签:index,head,ListNode,cur,val,随想录,next,链表,移除 From: https://www.cnblogs.com/gaoyuan2lty/p/16911375.html