203.移除链表元素
思路:
使用虚拟头节点, 并给一个临时指针,从链表头 比较到 链表尾部
代码
/**
* 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(0,head);
ListNode index = dummy;
while(index != null){
while(index.next != null && index.next.val == val){
index.next = index.next.next;
}
index = index.next;
}
return dummy.next;
}
}
问题:我的代码写复杂了,实际上不需要用连续的while循环来删除,只需要继续指向下一个节点,不断循环即可。另外需要两个指针,一个指向前一个节点,一个指向当前节点,便于删除。
题解代码:
/**
* 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(0,head);
ListNode index = dummy.next;
ListNode pre = dummy;
while(index != null){
if(index.val == val){
pre.next = index.next;
}else{
pre = index;
}
index = index.next;
}
return dummy.next;
}
}
设计链表
思路
这个题目有助于对链表增删改查的理解。
错误:第一次的写时候,更新链表的同时忘记更新size,导致链表的大小没有被控制。另外参考答案中,增加到头部和尾部,都利用了增加到某个索引的位置这个函数,感觉更加简洁!
代码
//单链表
class ListNode {
int val;
ListNode next;
ListNode(){}
ListNode(int val) {
this.val=val;
}
}
class MyLinkedList {
ListNode dummy;
int size;
public MyLinkedList() {
dummy = new ListNode(0);
size = 0;
}
public int get(int index) {
if(index > size - 1 || index < 0 ){
return -1;
}
ListNode temp = dummy;
for (int i = 0;i<=index;i++){
temp = temp.next;
}
return temp.val;
}
public void addAtHead(int val) {
ListNode new_node = new ListNode(val);
new_node.next = dummy.next;
dummy.next = new_node;
size+=1;
}
public void addAtTail(int val) {
ListNode new_node = new ListNode(val);
ListNode temp = dummy;
while(temp.next != null){
temp = temp.next;
}
temp.next = new_node;
size+=1;
}
public void addAtIndex(int index, int val) {
if(index > size ){
return;
}
if(index == size){
addAtTail(val);
return;
}
ListNode new_node = new ListNode(val);
ListNode temp = dummy;
for (int i = 0;i<index;i++){
temp = temp.next;
}
new_node.next = temp.next;
temp.next = new_node;
size+=1;
}
public void deleteAtIndex(int index) {
if(index >= size || index < 0){
return;
}
ListNode temp = dummy;
for (int i = 0;i<index;i++){
temp = temp.next;
}
temp.next= temp.next.next;
size-=1;
}
}
/**
* 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.反转链表
思路
思路:给一个虚拟头节点,然后双指针,循环直到链表末尾:让后一个节点的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){
return null;
}
ListNode dummy = new ListNode(0,head);
ListNode second = dummy;
ListNode first = dummy.next;
ListNode pre = null;
pre = first.next;
first.next = null;
second = first;
first = pre;
while (first != null){
pre = first.next;
first.next = second;
second = first;
first = pre;
}
return second;
}
}