203:移除链表元素
链表过段时间总是容易生疏,一开始总是很茫然删掉一个结点后,从头结点能不能顺着找到剩余的元素。其实链表就像一根链子一样,每个结点位于内存中的不同位置,各个结点之间有根链子扣着,当删除一个结点的过程相当于把前一个结点和后一个结点扣上,再把当前结点拿走(C语言中需要释放当前结点的内存,Java有自己的回收机制,因此不需要手动释放)。所以删除结点的关键在于需要两个指针,一个指向当前结点cur,另一个指向当前结点的前一个结点pre,如果当前结点是符合要求要删掉的结点,那么当前节点的前一个结点pre将指向当前结点的下一个结点cur.next,否则,pre=cur。每次循环cur都向前移动一个结点,即:cur = cur.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) {
while(head!=null && head.val == val){
head = head.next;
}
if(head == null)//有可能头节点一直都等于val,最后会导致链表为空,所以该判断应放在头节点处理完之后
return head;
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:设计链表
通过这个题,提升了写链表的熟练度,具体实现过程中需要考虑一些细节:1)判断头结点是否是空结点;2)插入结点时需要考虑插入位置,插在头、尾还是中间;3)删除结点时也要考虑所要删除结点的位置。
单链表:
class MyLinkedList {
ListNode head;
public class ListNode{
int val;
ListNode next;
public ListNode() {}
public ListNode(int val) {
this.val = val;
}
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
public MyLinkedList() {}
public int get(int index) {
int i = 0;
if(head == null)
return -1;
for(ListNode p=head;p!=null;p=p.next,i++){
if(i==index){
return p.val;
}
}
return -1;
}
public void addAtHead(int val) {
ListNode temp = new ListNode(val);
if(head == null){
head = temp;
}else{
temp.next = head;
head = temp;
}
}
public void addAtTail(int val) {
ListNode temp = new ListNode(val);
if(head == null){
head = temp;
}else{
for(ListNode p = head;p!=null;p=p.next){
if(p.next == null){
p.next = temp;
break;
}
}
}
}
public void addAtIndex(int index, int val) {
ListNode temp = new ListNode(val);
int i = 0;
if(index==0) {
if (head == null) {
head = temp;
}else {
temp.next = head;
head = temp;
}
return;
}
if(head != null){
for(ListNode p=head;p!=null;p=p.next,i++){//p表示index的前一个
if((i+1) == index){
if(p.next == null){//说明到了末尾
p.next = temp;
}else{
temp.next = p.next;
p.next = temp;
}
break;
}
}
}
}
public void deleteAtIndex(int index) {
int i = 0;
if(head == null)
return;
for(ListNode p=head;p!=null;p=p.next,i++){
if(index==0){
head = head.next;
break;
}else if(((i+1)==index)&&(i>=0)&&(p.next!=null)){
p.next = p.next.next;
break;
}
}
}
}
/**
* 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的前一个结点,依次将cur结点转向pre,再把pre移到头结点。
/**
* 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 reverseList(ListNode head) {
if((head == null)||(head.next == null))
return head;
ListNode pre = null;
ListNode cur = head;
while(cur!=null){
ListNode temp = cur;
cur = cur.next;
temp.next = pre;
pre = temp;
}
return pre;
}
}
总结:更熟悉链表了,不会像之前看见链表就害怕了。