问题描述
实现 MyLinkedList 类:
MyLinkedList()初始化MyLinkedList对象。int get(int index)获取链表中下标为index的节点的值。如果下标无效,则返回-1。void addAtHead(int val)将一个值为val的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。void addAtTail(int val)将一个值为val的节点追加到链表中作为链表的最后一个元素。void addAtIndex(int index, int val)将一个值为val的节点插入到链表中下标为index的节点之前。如果index等于链表的长度,那么该节点会被追加到链表的末尾。如果index比长度更大,该节点将不会插入到链表中。void deleteAtIndex(int index)如果下标有效,则删除链表中下标为index的节点。
---------------------------------------------------------------------------------------------------------------------------------
解答阐述
在这里,我进行了两种版本的写法(都是写单向链表)
版本一代码较为繁复,从题目本身单个功能上进行实现,并未进行各个功能的融合实现;
版本二简洁了有关功能的代码,将链表各个功能融合实现;
---------------------------------------------------------------------------------------------------------------------------------
代码展示
代码1:
class MyLinkedList {
ListNode head;
public MyLinkedList() {
head=null;
}
public int get(int index) {
int i = 0;
for(ListNode p = head;p!=null;p=p.next,i++){
if(i==index){
return p.val;
}
}
return -1;
}
public void addAtHead(int val) {
if(head==null){
head=new ListNode(val,null);
}
else
head = new ListNode(val,head);
}
public void addAtTail(int val) {
ListNode p =head;
if(head==null) {
head=new ListNode(val,null);
}
else if(head.next==null)
head.next=new ListNode(val,null);
else{
ListNode saved = null;
while(p.next!=null) {
saved = p.next;
p=p.next;
}
p.next=new ListNode(val,null);
}
}
public void addAtIndex(int index, int val) {
int i = 0;
if(index==0){
head=new ListNode(val,head);
}
if(index<0)
return;
for(ListNode p=head;p!=null;p=p.next,i++){
if(i==index-1){
ListNode p1 = p.next;
p.next=new ListNode(val,p1);
}
}
}
public void deleteAtIndex(int index) {
int i = 0;
if(index<0)
return;
for(ListNode p = head;p!=null;p=p.next,i++){
if(index==0) {
head = head.next;
return;
}
else if(i==index-1&&p.next!=null){
p.next=p.next.next;
}
}
}
}
class ListNode{
ListNode next;
int val;
public ListNode(int val,ListNode next){
this.val = val;
this.next = next;
}
}
代码2:
class MyLinkedList {
ListNode1 head;
public MyLinkedList() {
this.head=null;
}
public int get(int index) {
int i = 0;
for(ListNode1 p = head;p!=null;p=p.next,i++){
if(i==index){
return p.val;
}
}
return -1;
}
public ListNode1 findLastNode(){
ListNode1 p1=null;
for(ListNode1 p=head;p!=null;p=p.next){
p1 = p;
}
return p1;
}
public void addAtHead(int val){
addAtIndex(0,val);
}
public void addAtTail(int val) {
if(head==null) {
head=new ListNode1(val,null);
}
else{
ListNode1 p1 = findLastNode();
p1.next=new ListNode1(val,null);
}
}
public void addAtIndex(int index, int val) {
int i = 0;
if(index==0){
head=new ListNode1(val,head);
}
if(index<0)
return;
for(ListNode1 p = head; p!=null; p=p.next,i++){
if(i==index-1){
ListNode1 p1 = p.next;
p.next=new ListNode1(val,p1);
}
}
}
public void deleteAtIndex(int index) {
int i = 0;
if(index<0)
return;
for(ListNode1 p = head; p!=null; p=p.next,i++){
if(index==0) {
head = head.next;
return;
}
else if(i==index-1&&p.next!=null){
p.next=p.next.next;
}
}
}
}
class ListNode1 {
ListNode1 next;
int val;
public ListNode1(int val, ListNode1 next){
this.val = val;
this.next = next;
}
}
链表小结
当我们进行无哨兵链表代码书写时,尤其容易犯的错误就是在进行for或while循环时,出现空指针异常,即xxx.next或xxx.next.next时容易发生。此外对于判断条件p!=null和p.next!=null条件的运用有时可以更容易地解答题目,简化代码;此外,对于头节点非空的判断非常重要。当然如果是拥有哨兵的链表,那么对此就不用作判断,所以建议还是要写带哨兵的链表,可以极大程度的简化代码,以及防止一些bug的出现;
5万+





