203.移除链表元素
这里创建了一个虚拟的头结点指向head,这样非常方便,后续操作跟是不是头结点就没啥关系了。注意最后要return的是node.next啊啊啊啊,因为head可能被删除了
/**
* 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 node = new ListNode(0);
node.next = head;
ListNode temp = node;
while(temp.next != null){
if(temp.next.val == val){
temp.next = temp.next.next;
}else{
temp = temp.next;
}
}
return node.next;
}
}
一开始创建新结点的时候也可以用另一种包含值和下一个结点的构造方法:( 参考:java中new ListNode(0)常见用法详细区别(全))
ListNode node = new ListNode(0, head);
707.设计链表
设计的是依托答辩,希望没人看到,留着自我鞭策。ListNode也没定义就拿来用,甚至忘了借鉴第一题!淦
欸,看完题解回来看我自己一上来写的什么玩儿,九敏,居然还count,真的是while上瘾吗,大无语事件了就是说
class MyLinkedList {
private int val;
private ListNode next;
ListNode head = new ListNode(0);
public MyLinkedList() {
}
public int get(int index) {
int count = 0;
while(head.next != null){
head = head.next;count++;
if(count == index){
return head.val;
}
}
return -1;
}
public void addAtHead(int val) {
ListNode addHead = new ListNode();
addHead.next = head.next;
addHead.val = val;
head.next = addHead;
}
public void addAtTail(int val) {
ListNode addTail = new ListNode();
while(head.next != null){
head = head.next;
}
head.next = addTail;
addTail.val = val;
addTail.next = null;
}
public void addAtIndex(int index, int val) {
ListNode addIndex = new ListNode();
int count = 0;
while(head.next != null){
head = head.next;
count++;
if(count == index){
addIndex.next = head.next;
addIndex.val = val;
head.next = addIndex;
break;
}
}
}
public void deleteAtIndex(int index) {
int count = 0;
while(head.next != null){
head = head.next;
count++;
if(count == index){
head.next = head.next.next;
break;
}
}
}
}
/**
* 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);
*/
题解加深了我对构造函数初始化功能的理解,在MyLinkedList 和ListNode类中都要写构造函数,MyLinkedList中的构造函数可以创建一个哨兵结点并且初始化链表长度,ListNode中构造函数可以直接指定新建结点的值,就不用在代码里给val重新赋值。
定义size的目的是保存当前链表长度,便于实现在链表尾部添加结点,以及判断index的有效性。这里head作为哨兵,就可以将链表头结点(第一个真正的链表结点)当作普通结点处理。
还有就是,头尾添加结点都可以直接把添加结点那个方法拿过来用,别傻傻的再写一遍了五五。
重!新!写!的!👇(写的真好,中间曾经错过一次原因竟是在添加的时候一开始判断条件写成了size>index??????九敏啊)
class MyLinkedList {
int size;
ListNode head;//head是哨兵
public MyLinkedList() {
size = 0;
head = new ListNode(0);
}
//得到index上的值
public int get(int index) {
if(index < 0 || index >= size){
return -1;
}
ListNode cur = head;
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);
}
//在index处添加结点
public void addAtIndex(int index, int val) {
if(index > size){
return;
}
ListNode addIndex = new ListNode(val);
ListNode cur = head;
for(int i = 0; i < index; i++){
cur = cur.next;
}
addIndex.next = cur.next;
cur.next = addIndex;
size++;
}
//删除index处结点
public void deleteAtIndex(int index) {
if(index < 0 || index >= size){
return;
}
ListNode cur = head;
for(int i = 0; i < index; i++){
cur = cur.next;
}
cur.next = cur.next.next;
size--;
}
}
//定义结点
class ListNode{
int val;
ListNode next;
public ListNode(int val) {
this.val = val;
}
}
/**
* 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.反转链表
路漫漫大佬的双指针解法一,后面解法还没看,画了图真的很好理解呀,具体解释详见注释┗|`O′|┛ 嗷~~。
阿里嘎多路漫漫桑,搬运一下你画的图:
此处省略n步
下面代码跟上图指针是反过来的~~~~
/**
* 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;//翻转过后的cur的下一个指针,也就是正常顺序里的cur的前一个指针
ListNode cur = head;//当前指针
while(cur != null){
ListNode temp = cur.next;//定义一个中间变量存储cur的下一个结点,防止两条链走丢
cur.next = pre;//让cur跟下一个结点断开,去连cur前面那个结点,这一步实现了反转
//下面这两行是让两个指针都往前走一步,这两行顺序不能颠倒,否则pre就会指错
pre = cur;
cur = temp;
}
return pre;
}
}