前言:
说些废话。下周一有个面试,明天应该没办法刷题了,打算skip一天,面试之后补上。今天的题都是以前刷过的,快速的过一遍,后面再查漏补缺。以前自己刷题的时候,时常因为一些突然的安排而打乱节奏,希望这次在训练营能够坚持下去,加油啊!
链表理论基础
linked list相关的操作主要通过修改指针指向的node来实现
删除node时,c++需要手动释放内存
比较linked list 和 array:
linked list, 查询较少, 增删频繁
array: 查询频繁, 增删较少
array 长度固定,linked list可以动态增减
203.移除链表元素
思路: 遍历链表时,如果下一个节点的值等于val,让节点next指针直接指向下下一个节点
实现:当删除某一个节点时,我们需要通过前一个节点进行操作,但链表的head 之前没有节点,我们是通过 head = head.next 来实现。 因此我们可以单独写一段code来处理删除head的情况,更好的方式是通过设置一个虚拟头节点,指向head,这样linked list上所有的节点都可以按照统一的方式进行删除。
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummy = new ListNode(0,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;
}
}
707.设计链表
思路: 通过之前203的练习可以发现,在删除某一节点时,通过增加dummy head可以统一head 和非head节点的操作。 在某一位置插入节点同理,可以通过dummy head来操作。
实现: 初始化时定义一个dummy head , 用size记录链表的长度
注意: 当addAtIndex() 中判断index是否有效时, 不同于get() 和 deleteAtIndex(), 需要判断 index > size 而不是index >= size, 因为当需要增加节点时,index = size 的位置相当于在链表的尾部增加一个节点,是有效的。
class MyLinkedList {
class listNode {
int val;
listNode next;
listNode(int val){
this.val = val;
}
}
//定义dummy head 和size
private listNode head;
private int size;
public MyLinkedList() {
this.head = new listNode(0);
this.size = 0; // size 并不包含 dummy head
}
public int get(int index) {
// 通过size 判断index是否超过范围
if( index < 0 || index >= size){
return -1;
}
// index 0 是head, 所以寻找 index + 1 的节点
listNode cur = head;
for( int i = 0; i < index + 1; i++){
cur = cur.next;
}
return cur.val;
}
public void addAtHead(int val) {
listNode newNode = new listNode(val);
newNode.next = head.next;
head.next = newNode;
size++;
}
public void addAtTail(int val) {
listNode newNode = new listNode(val);
listNode cur = head;
while(cur.next != null){
cur = cur.next;
}
cur.next = newNode;
size++;
}
public void addAtIndex(int index, int val) {
if(index < 0 || index > size){
//为什么不是index >= size, 因为index 为size时是有效的,相当于add at the tail
return;
}
// 在index + 1的位置插入新节点
listNode newNode = new listNode(val);
listNode pre = head;
// 到达index, 也就是插入节点的前一节点
for(int i = 0; i < index; i++){
pre = pre.next;
}
newNode.next = pre.next;
pre.next = newNode;
size++;
}
public void deleteAtIndex(int index) {
if (index < 0 || index >= size) {
return;
}
listNode pre = head;
for(int i = 0; i < index; i++){
pre = pre.next;
}
pre.next = pre.next.next;
size--;
}
}
206.反转链表
思路: 链表的操作其实就是指针的操作,反转链表只需要改变next 指针的方向。
实现: 指针cur 遍历整个链表, 在这个过程中, 需要一个temp指针,先保存cur.next. 以及一个pre指针,指向cur的前一个节点,将 cur.next 指向 pre 实现翻转
class Solution {
public ListNode reverseList(ListNode head) {
ListNode cur = head;
ListNode pre = null;
ListNode temp;
while(cur != null){
temp = cur.next;
cur.next= pre;
pre = cur;
cur = temp;
}
return pre;
}
}
总结
涉及修改链表,如插入、删除、和移动,使用dummy head, 统一头节点和其他节点的处理 ...

413

被折叠的 条评论
为什么被折叠?



