代码随想录算法训练营第三天| 203. 移除链表,707.设计链表 ,206.反转链表
上学期刚学完数据结构,印象还是有点的,做起来也没想象的难。
203.移除链表 leetcode203 Remove Linked List Elements
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummyHead = new ListNode(0,head);
ListNode cur = dummyHead; //利用虚拟头节点
while(cur.next !=null){ //遍历链表
if(cur.next.val ==val){ //找到相符的值
cur.next = cur.next.next; //如果是,则跳过该值
}else{
cur = cur.next; //不是的话,则继续遍历
}
}
return dummyHead.next; //返回头指针
}
}
这道题,需要记住设置一个虚拟头指针,然后用虚拟头指针遍历链表,(务必不能使用head遍历,如果用了,则改变了head节点值,影响后续操作),因此需要利用其他指针获取head节点,来进行操作。
总结!记住设置虚拟头指针即可!
707.设计链表 leetcode 707 design linked list
class ListNode{ //设置节点属性
int val;
ListNode next;
ListNode(){
}
ListNode(int val){
this.val = val;
}
}
class MyLinkedList {
int size; //节点个数
ListNode head; //头节点
public MyLinkedList() { //初始化链表
head = new ListNode(0);
size = 0;
}
public int get(int index) {
//if(head==null)return -1; //如果链表为空
if(index<0||index>=size)return -1; //位置不存在
ListNode cur = head; //设置虚拟头节点
int i = 0 ;
while(i++ <= index){ //遍历,直到index
cur = cur.next;
}return cur.val; //返回在index的节点的值
}
//头插
public void addAtHead(int val) {
size++; //节点个数+1
ListNode cur = new ListNode(val); //构造新节点 ,把val放进去
cur.next = head.next; //注意头插next问题!!
head.next = cur;
}
//尾插
public void addAtTail(int val) {
size++;
ListNode cur = new ListNode(val); //构造新节点
ListNode pre = head; //设置虚拟头指针
while(pre.next!=null){ //遍历直到末尾位置
pre = pre.next;
}
cur.next = null; //设置新节点的next
pre.next = cur; //swap
pre = cur;
}
//在index插入
public void addAtIndex(int index, int val) {
if (index > size) { //边界问题
return;
}
if (index < 0) {
index = 0;
}
size++;
ListNode pre = head;
for (int i = 0; i < index; i++) { //遍历链表,直到index
pre = pre.next;
}
ListNode toAdd = new ListNode(val); //构造新节点
toAdd.next = pre.next;
pre.next = toAdd;
}
在index删除节点
public void deleteAtIndex(int index) {
if(index<0||index >=size)return;
size--;
if (index == 0) { //如果只有头节点,则删除
head = head.next;
return;
}
ListNode pre = head; //虚拟头节点
int i =0;
while(i++ < index){
pre = pre.next;
}
pre.next = pre.next.next; //跳过index节点
}
}
java比c++设置链表简单,不需要考虑释放节点。
1.注意边界问题,这个方面还是不太行
2.关键: 不能利用head节点遍历链表,还是要用其他指针取head节点
206.反转链表206 Revese Linked List
双指针法:
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null; //
ListNode cur = head; //虚拟头
while(cur!=null){
ListNode temp = cur.next; //临时节点保存cur.next
cur.next = pre; //第一次的话,cur.next指向null
pre = cur; //pre保存cur节点,形成循环
cur = temp; //遍历cur,不能指向cur.next
}
return pre;
}
}
最后cur = temp不能写成 cur = cur.next,
因为cur节点此时的next已经是pre节点,不是原先的数,所以不可以取cur.next。