203.移除链表元素
做题小结
这道题比较简单,具体考察了链表的移动和删除。AC了。
while((head != null) && (head.val == val)){
head = head.next;
}
if(head == null){
return head;
}
ListNode prevNode = head;
ListNode currNode = head.next;
while(currNode != null){
if(currNode.val == val){
currNode = currNode.next;
prevNode.next = currNode;
}else{
prevNode = currNode;
currNode = currNode.next;
}
}
return head;
记录下随想录的代码
if (head == null) {
return head;
}
// 因为删除可能涉及到头节点,所以设置dummy节点,统一操作
ListNode dummy = new ListNode(-1, head);
ListNode pre = dummy;
ListNode cur = head;
while (cur != null) {
if (cur.val == val) {
pre.next = cur.next;
} else {
pre = cur;
}
cur = cur.next;
}
return dummy.next;
while (head != null && head.val == val) {
head = head.next;
}
// 已经为null,提前退出
if (head == null) {
return head;
}
// 已确定当前head.val != val
ListNode pre = head;
ListNode cur = head.next;
while (cur != null) {
if (cur.val == val) {
pre.next = cur.next;
} else {
pre = cur;
}
cur = cur.next;
}
return head;
707.设计链表
做题小结
这题主要考察了linked list的构造,基本逻辑就是要理解链表。
class ListNode {
int val;
ListNode next;
ListNode pred;
ListNode(){}
ListNode(int val) {
this.val=val;
}
}
class MyLinkedList {
ListNode head = null;
int size;
public MyLinkedList() {
size = 0;
}
public int get(int index) {
if(size == 0){
return -1;
}
if (index < 0 || index > size) {
return -1;
}
ListNode currentNode = head;
int cnt = 0;
while (currentNode != null){
if(cnt == index){
return currentNode.val;
}else{
cnt++;
currentNode = currentNode.next;
}
}
return -1;
}
//在链表最前面插入一个节点,等价于在第0个元素前添加
public void addAtHead(int val) {
if(head == null){
head = new ListNode(val);
size++;
return;
}
ListNode newNode = new ListNode(val);
newNode.next = head;
head = newNode;
size++;
}
//在链表的最后插入一个节点,等价于在(末尾+1)个元素前添加
public void addAtTail(int val) {
if(head == null){
head = new ListNode(val);
size++;
return;
}
ListNode pred = head;
ListNode curr = head.next;
while(curr != null){
pred = curr;
curr = curr.next;
}
pred.next = new ListNode(val);
size++;
}
// 在第 index 个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
// 如果 index 等于链表的长度,则说明是新插入的节点为链表的尾结点
// 如果 index 大于链表的长度,则返回空
public void addAtIndex(int index, int val) {
if(index == 0){
addAtHead(val);
return;
}
if(index == size){
addAtTail(val);
return;
}
if (index > size || index <0) {
return;
}
ListNode newNode = new ListNode(val);
//找到要插入节点的前驱
ListNode pred = head;
ListNode curr = head.next;
int cnt = 1;
while(curr != null){
if(cnt == index){
pred.next = newNode;
newNode.next = curr;
size++;
return;
}else{
pred = curr;
curr = curr.next;
cnt++;
}
}
}
//删除第index个节点
public void deleteAtIndex(int index) {
if (index < 0 || index > size) {
return;
}
if (index == 0) {
if(size == 0){
return;
}
head = head.next;
size--;
return;
}
ListNode pred = head;
ListNode curr = head.next;
int cnt = 1;
while(curr != null){
if(cnt == index){
pred.next = curr.next;
size--;
return;
}else{
pred = curr;
curr = curr.next;
cnt++;
}
}
}
}
随想录讲解
文章链接 随想录使用了虚拟头的方法进行构造,而我的方法则是在链表本身进行操作,没有使用虚拟头。时间复杂度上还是有一定差别,下次可以尝试使用虚拟头。
class ListNode {
int val;
ListNode next;
ListNode(){}
ListNode(int val) {
this.val=val;
}
}
class MyLinkedList {
//size存储链表元素的个数
int size;
//虚拟头结点
ListNode head;
//初始化链表
public MyLinkedList() {
size = 0;
head = new ListNode(0);
}
//获取第index个节点的数值,注意index是从0开始的,第0个节点就是头结点
public int get(int index) {
//如果index非法,返回-1
if (index < 0 || index >= size) {
return -1;
}
ListNode currentNode = head;
//包含一个虚拟头节点,所以查找第 index+1 个节点
for (int i = 0; i <= index; i++) {
currentNode = currentNode.next;
}
return currentNode.val;
}
//在链表最前面插入一个节点,等价于在第0个元素前添加
public void addAtHead(int val) {
addAtIndex(0, val);
}
//在链表的最后插入一个节点,等价于在(末尾+1)个元素前添加
public void addAtTail(int val) {
addAtIndex(size, val);
}
// 在第 index 个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
// 如果 index 等于链表的长度,则说明是新插入的节点为链表的尾结点
// 如果 index 大于链表的长度,则返回空
public void addAtIndex(int index, int val) {
if (index > size) {
return;
}
if (index < 0) {
index = 0;
}
size++;
//找到要插入节点的前驱
ListNode pred = head;
for (int i = 0; i < index; i++) {
pred = pred.next;
}
ListNode toAdd = new ListNode(val);
toAdd.next = pred.next;
pred.next = toAdd;
}
//删除第index个节点
public void deleteAtIndex(int index) {
if (index < 0 || index >= size) {
return;
}
size--;
if (index == 0) {
head = head.next;
return;
}
ListNode pred = head;
for (int i = 0; i < index ; i++) {
pred = pred.next;
}
pred.next = pred.next.next;
}
}
206.反转链表
做题小结
这题也比较简单,基本上如果对链表的逻辑比较了解的话都能够写出来。
if(head == null){
return head;
}
ListNode newHead = head;
head = head.next;
newHead.next = null;
while(head != null){
ListNode newNode = head;
head = head.next;
newNode.next = newHead;
newHead = newNode;
}
return newHead;
随想录讲解
随想录提供了2种方法-双指针和递归法。双指针法和我的逻辑相同,递归法在空间复杂度上有一定优化。
- 双指针
ListNode prev = null;
ListNode cur = head;
ListNode temp = null;
while (cur != null) {
temp = cur.next;// 保存下一个节点
cur.next = prev;
prev = cur;
cur = temp;
}
return prev;
- 递归
class Solution {
public ListNode reverseList(ListNode head) {
return reverse(null, head);
}
private ListNode reverse(ListNode prev, ListNode cur) {
if (cur == null) {
return prev;
}
ListNode temp = null;
temp = cur.next;// 先保存下一个节点
cur.next = prev;// 反转
// 更新prev、cur位置
// prev = cur;
// cur = temp;
return reverse(cur, temp);
}
}