代码随想录Day3
今日任务
203.移除链表元素
707.设计链表
206.反转链表
语言:Java
链表基本介绍
- 链表类型:单链表、双链表、循环链表
- 分布方式:非连续存储,而是散乱分布,主要取决于操作系统
- 链表特点:可以修改链表长度,查找的时间复杂度是O(N),但是增加/删除元素的时间复杂度是O(1)
203. 移除链表元素
考点:链表删除元素
链接:https://leetcode.cn/problems/remove-linked-list-elements/
/**
* 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 virNode = new ListNode(0, head); //attention
ListNode preNode = virNode;
ListNode curNode = head;
while(curNode != null){ //attention
if(curNode.val == val){
preNode.next = curNode.next; //别写反了
curNode = preNode.next; //attention
}
else{
curNode = curNode.next;
preNode = preNode.next; //别忘了一起移动
}
}
return virNode.next;
}
}
707. 设计链表
考点:链表
链接:https://leetcode.cn/problems/design-linked-list/
注意事项:可以通过自定义一个打印方法来观察每轮处理完链表结果是否是符合预期的;注意题目中关于addAtIndex(int index, int val)
的描述
改进:可以将 addAtHead 和 addAtTail 函数统一用 addAtIndex 函数来表示
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;
}
}
class MyLinkedList {
ListNode dummyHead;
ListNode head;
int len;
public MyLinkedList() {
dummyHead = new ListNode(0, null);
len = 0;
}
public int get(int index) {
if(index >= len){
return -1;
}
ListNode curNode = head;
for(int i = 0; i < index; i++){
curNode = curNode.next;
}
return curNode.val;
}
public void addAtHead(int val) {
ListNode newNode = new ListNode(val);
head = newNode;
head.next = dummyHead.next;
dummyHead.next = head;
len++;
//printLinkList();
}
public void addAtTail(int val) {
ListNode curNode = dummyHead;
for(int i = -1; i < len - 1; i++){
curNode = curNode.next;
}
ListNode newNode = new ListNode(val, null);
curNode.next = newNode;
head = dummyHead.next;
len++;
//printLinkList();
}
public void addAtIndex(int index, int val) {
if(index > len){
return;
}
else if(index == len){
addAtTail(val);
return;
}
else if(index < 0){
addAtHead(val);
return;
}
ListNode newNode = new ListNode(val);
ListNode preNode = dummyHead;
for(int i = -1; i < index - 1; i++){
preNode = preNode.next;
}
newNode.next = preNode.next;
preNode.next = newNode;
head = dummyHead.next;
len++;
//printLinkList();
}
public void deleteAtIndex(int index) {
if(index >= len){
return;
}
ListNode preNode = dummyHead;
for(int i = -1; i < index - 1; i++){
preNode = preNode.next;
}
preNode.next = preNode.next.next;
head = dummyHead.next;
len--;
//printLinkList();
}
public void printLinkList(){
ListNode curNode = head;
while(curNode != null){
System.out.print(curNode.val);
curNode = curNode.next;
}
System.out.println();
}
}
/**
* 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://leetcode.cn/problems/reverse-linked-list/
注意事项:要考虑到链表的特殊性,比如一个空结点是无法取到next或者val值的,所以在初始化时,需要“最简单地初始化”(自己随便起的名字),也就是预设链表为空或者链表只有一个元素,这样设想也会更好地适应更普遍的情况,不可在初始化其他参数时盲目取next,否则会出现自己意想不到的错误。
改进:参考代码随想录
/**
* 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) {
if(head == null || head.next == null){
return head;
}
ListNode preNode = head;
ListNode curNode = preNode.next;
ListNode nextNode = curNode.next;
head.next = null; //如果不单独处理head的指向,那么链表中就会出现环
while(nextNode != null){
curNode.next = preNode;
preNode = curNode;
curNode = nextNode;
nextNode = nextNode.next;
}
curNode.next = preNode;
return curNode;
}
}