代码随想录算法训练营第三天| 203.移除链表元素 707.设计链表 206.反转链表
203.移除链表元素
原方法:
- head是指向头节点的指针
- 先处理头节点的特殊情况,再判断链表为空,因为可能头节点处理后为空了
- cur是一个指针,用来遍历链表
class Solution {
public ListNode removeElements(ListNode head, int val) {
while(head != null && head.val == val){
head = head.next;
}
if(head == null){
return head;
}
ListNode cur = head;
while(cur.next != null){
if(cur.next.val == val){
cur.next = cur.next.next;
}else{
cur = cur.next;
}
}
return head;
}
}
虚拟头节点
- 加了虚拟头节点就不用单独处理别的情况了
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummy =new ListNode();
dummy.next = 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;
}
}
递归:分三步
-
head代表当前节点,head.next代表下一个节点
-
如果后续链表已处理好的情况下,如何处理当前节点
-
基准问题(终止条件):空链表不需要移除元素
-
分析问题(最简单情况):当节点指向的子链中没有val值时,只用判断自己,若自己不等于val则返回自己,否则返回head.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 removeElements(ListNode head, int val) {
//递归方法
//确定问题:删除链表中的val值,返回新的头节点
//基准问题:空链表不需要移除元素
if(head == null){
return head;
}
//分析问题:当节点指向的子链中没有val值时,只用判断自己
head.next = removeElements(head.next, val);
if(head.val == val){
return head.next;
}else{
return head;
}
}
}
707.设计链表
最痛苦的一集
- 注意合法条件,index插入时,index可以等于size,相当于尾插
- java不能用while(i--),不合法
- 记得更新size
class MyLinkedList {
class ListNode{
int val;
ListNode next;
ListNode(int val){
this.val = val;
}
}
private int size = 0;
private ListNode dummyhead;
public MyLinkedList() {
this.size = 0;
this.dummyhead = new ListNode(0);
}
public int get(int index) {
ListNode cur = dummyhead.next;
if(index < 0 || index > size - 1){
return -1;
}else{
for(int i = 0; i < index; i++){
cur = cur.next;
}
}
return cur.val;
}
public void addAtHead(int val) {
ListNode newNode = new ListNode(val);
newNode.next = dummyhead.next;
dummyhead.next = newNode;
size++;
}
public void addAtTail(int val) {
ListNode cur = dummyhead;
ListNode newNode = new ListNode(val);
while(cur.next != null){
cur = cur.next;
}
cur.next = newNode;
size++;
}
public void addAtIndex(int index, int val) {
if(index < 0 || index > size - 1){
return;
}
ListNode cur = dummyhead;
ListNode newNode = new ListNode(val);
for(int i = 0; i < index; i++){
cur = cur.next;
}
newNode.next = cur.next;
cur.next = newNode;
size++;
}
public void deleteAtIndex(int index) {
if(index < 0 || index > size - 1){
return;
}
ListNode cur = dummyhead;
for(int i = 0; i < index; i++){
cur = cur.next;
}
cur.next = cur.next.next;
size--;
}
}
/**
* 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.反转链表
双指针法
- cur : 遍历链表
- pre : 记录cur前面节点地址
- temp : 记录cur后面节点地址
class Solution {
public ListNode reverseList(ListNode head) {
ListNode prev = null;
ListNode curr = head;
while(curr != null){
ListNode next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
}
递归法
-
head代表当前节点,head.next代表下一个节点
-
确定问题 : 若后续链表反转好的情况下,如何处理自己
-
基准问题(终止条件) : 当head == null,和head.next == null时不需要操作
-
分析问题 : 当前节点的后一个节点指向自己,当前节点指向null
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode newHead = reverseList(head.next);
head.next.next = head;
head.next = null;
return newHead;
}
}