算法笔记|Day3链表基础
☆☆☆☆☆leetcode 203.移除链表元素
题目链接:leetcode 203.移除链表元素
题目分析
1.直接使用原来的链表进行删除操作,需要判断该节点是否为头结点,若不为头结点可直接通过前一个节点移除,若为头结点需要更新头结点;
2.采用虚拟头结点,所有节点就可以采用统一方式进行移除;
3.时间复杂度为O(n),空间复杂度为O(1)。
代码
1.直接使用原来的链表进行删除操作,不采用虚拟头结点
/**
* 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) {
while(head!=null&&head.val==val){
head=head.next;
}
ListNode cur=head;
while(cur!=null){
while(cur.next!=null&&cur.next.val==val){
cur.next=cur.next.next;
}
cur=cur.next;
}
return head;
}
}
2.采用虚拟头结点
/**
* 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) {
ListNode dummy=new ListNode();
dummy.next=head;
ListNode cur=dummy;
while(cur.next!=null){
if(cur.next.val==val){
cur.next=cur.next.next;
}else{
cur=cur.next;
}
}
return dummy.next;
}
}
☆☆☆☆☆leetcode 707.设计链表
题目链接:leetcode 707.设计链表
题目分析
1.采用虚拟头结点的方法,对链表进行增、删、查等操作(查找本身可以不使用虚拟头结点,为了方便一并使用);
2.在头部和尾部增添一个元素,相当于在index节点之前增添一个元素中index取0和size的情况;
3.时间复杂度为O(1)(设计index的操作为O(index)),空间复杂度为O(n)。
代码
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 MyLinkedList {
int size;
ListNode head;
public MyLinkedList() {
size=0;
head=new ListNode();//这里是虚拟头结点,因为没有显式地为头节点head的ListNode对象指定值
}
public int get(int index) {
if(index<0||index>=size){
return -1;
}
ListNode cur=head;
while(index>=0){
cur=cur.next;
index--;
}
return cur.val;//包含一个虚拟头节点,所以查找第 index+1 个节点
}
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;
}
index=index<0?0:index;
size++;
ListNode cur=head;
while(index>0){
cur=cur.next;
index--;
}
ListNode newnode=new ListNode(val);
newnode.next=cur.next;
cur.next=newnode;
}
public void deleteAtIndex(int index) {
if(index>size||index>=size){
return;
}
size--;
ListNode cur=head;
while(index>0){
cur=cur.next;
index--;
}
cur.next=cur.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);
*/
注意:链表的索引是从0开始
☆☆☆☆☆leetcode 206.反转链表
题目链接:leetcode 206.反转链表
题目分析
1.采用双指针法,当前结点为cur,前一个结点为pre(反转后cur的下一个结点),同时需要将cur.next结点保存到temp,时间复杂度为O(n),空间复杂度为O(1);
2.采用递归方法,思路同双指针法,单独写一个函数reverse用来翻转,并在主函数中调用,时间复杂度为O(n),空间复杂度为O(n)。
代码
1.双指针法
/**
* 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 reverseList(ListNode head) {
ListNode pre=null;
ListNode cur=head;
ListNode temp=null;
while(cur!=null){
temp=cur.next;
cur.next=pre;
pre=cur;
cur=temp;
}
return pre;
}
}
2.递归法
/**
* 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 reverseList(ListNode head) {
return reverse(head,null);
}
public ListNode reverse(ListNode cur,ListNode pre) {
if(cur==null){
return pre;
}
ListNode temp=null;
temp=cur.next;
cur.next=pre;
return reverse(temp,cur);
}
}