203.移除链表元素
题意:删除链表中等于给定值 val 的所有节点。
示例 1:
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]
示例 2:
输入:head = [], val = 1
输出:[]
示例 3:
输入:head = [7,7,7,7], val = 7
输出:[]
看到题目第一想法
最直观的想法,分情况讨论是否是头节点。是头节点,直接改变头结点位置。不是头结点,就将应删除节点上一个节点直接指向下下个节点。 注意:操作节点前要判断是否为空。
while(head!=null&&head->val==target)
head=head->next
cur=head;
while(cur!=null &&cur->next!=null )
if(cur->next==target)
cur->next=cur->next->next
else cur=cur->next
return head
class Solution {
public ListNode removeElements(ListNode head, int val) {
while(head!=null && head.val==val){
head=head.next;
}
ListNode cur=head;
while(cur!=null&&cur.next!=null){
if(cur.next.val==val){
cur.next=cur.next.next;
}else{cur=cur.next;}
}
return head;
}
}
学习之后
发现通过引入虚拟节点可以不用单独分出头节点来讨论。 这里来给链表添加一个虚拟头结点为新的头结点,此时要移除这个旧头结点元素1。 这样就可以使用和移除链表其他节点的方式了,最后在题目中,return 头结点的时候,别忘了 return dummyNode->next;, 这才是新的头结点。
dummy head=new();
dummyhead->next=head;
cur=dummyhead
while(cur->next!=null)
if (cur->next->val==target)
cur->next=cur->next->next;
else cur=cur->next
return dammyhead->next
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummyhead= new ListNode (1,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; }
虚拟头节点,cur临时指针=虚拟头节点。
707.设计链表
题意:
在链表类中实现这些功能:
? get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
? addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
? addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
? addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
? deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。
看到题目第一想法
采用虚拟头节点来对五种操作进行编码。
cur =dummyhead.next
while(n){
cur=cur.next
n--
}
return cur.val
ListNode newNode= new ListNode();
newNode.next=dummyhead.next;
dummyhead.next=newNode;
return dummyhead.next
cur=dummyhead
while(cur.next!=null){
cur=cur.next
}
ListNode newNode =new ListNode()
cur.next=newnode
cur=dummyhead
while(n--){
cur=cur.next
}
newNode.next=cur.next;
cur.next=newNode
size++
cur=dummyhead
while(n){
cur=cur.next
n--
}
cur.next=c
size--
class ListNode{
int val ;
ListNode next;
public ListNode(){};
public ListNode(int val){
this.val=val;
}}
class MyLinkedList {
int size;
ListNode dummyHead;
public MyLinkedList() {
dummyHead=new ListNode(-1);
size=0;
}
public int get(int index) {
if(index<0||index>=size){
return -1;
}else{
ListNode cur=dummyHead;
while(index!=0){
cur=cur.next;
index--; }
return cur.next.val;
}
}
public void addAtHead(int val) {
ListNode newNode=new ListNode(val);
newNode.next=dummyHead.next;
dummyHead.next=newNode;
size++;
return ;
}
public void addAtTail(int val) {
ListNode newNode= new ListNode(val);
ListNode cur=dummyHead;
while(cur.next!=null){
cur=cur.next;
}
cur.next=newNode;
size++;
return;
}
public void addAtIndex(int index, int val) {
if(index>size){return;}
ListNode newNode=new ListNode(val);
ListNode cur= dummyHead;
if(index<0){
addAtHead(val);
return ;
}
while(index--!=0){
cur=cur.next;
}
newNode.next=cur.next;
cur.next=newNode;
size++;
return;
}
public void deleteAtIndex(int index) {
if(index<0||index>=size){
return ;}
ListNode cur=dummyHead;
while(index--!=0){
cur=cur.next;
}
cur.next=cur.next.next;
size--;
return ;}
}
针对第n个数进行操作,让cur.next=该数。
206.反转链表
题意:反转一个单链表。
示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL
看到题目第一想法
只需要改变链表的next指针的指向,直接将链表反转,无需增加删除节点。 针对此题需要两个指针一个指当前节点,一个指当前节点的前节点,用来转换指针方向,还需要一个临时节点来寄存原来节点的下一个节点,用来移动前面两个定位的节点。 首先定义一个cur指针,指向头结点,再定义一个pre指针,初始化为null。 然后就要开始反转了,首先要把 cur->next 节点用tmp指针保存一下,也就是保存一下这个节点。 为什么要保存一下这个节点呢,因为接下来要改变 cur->next 的指向了,将cur->next 指向pre ,此时已经反转了第一个节点了。 最后,cur 指针已经指向了null,循环结束,链表也反转完毕了。 此时我们return pre指针就可以了,pre指针就指向了新的头结点。
cur=head
pre=null
while(cur==null){
temp=cur.next;
cur.next=pre;
pre=cur;
cur=temp;}
return 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;
}
}
递归法
递归法相对抽象一些,但是其实和双指针法是一样的逻辑,同样是当cur为空的时候循环结束,不断将cur指向pre的过程。 关键是初始化的地方,可能有的同学会不理解, 可以看到双指针法中初始化 cur = head,pre = NULL,在递归法中可以从如下代码看出初始化的逻辑也是一样的,只不过写法变了。 递归法本质就是自己调用自己的方法。
reverse(cur,pre)
if(cur==null){
return pre;
}
temp=cur.next;
cur.next=pre;
reverse(temp,cur);
reverseList(head){
return reverse(head,null)
}
class Solution {
public ListNode reverseList(ListNode head) {
return reverse(head,null);}
public ListNode reverse(ListNode cur,ListNode pre){
ListNode temp=cur.next;
cur.next=pre;
if(temp!=null){
return reverse(temp,cur);
}
return cur;}}
```
class Solution {
public ListNode reverseList(ListNode head) {
return reverse(head,null);}
public ListNode reverse(ListNode cur,ListNode pre){
if(cur==null){
return pre;}
ListNode temp=cur.next;
cur.next=pre;
return reverse(temp,cur);}
|