剑指offer3.4-代码的鲁棒性

题目

输入一个链表,输出该链表中倒数第k个结点。 

思路

1.首先想到的是走到链表的尾端,再由尾端回溯k步。可是链表的节点定义看出这是单向链表,结点只有从前往后的指针,因此不能这样走。

2.只能从头节点开始遍历链表。那么我们可以先获取链表的结点数,就可以计算从前往后是需要走多少步了。但是这样需要遍历两次链表

3.为了实现只遍历一次链表,我们还是像之前翻转数组一样,设立两个指针。第一个指针从链表的头指针开始遍历向前走k-1,第二个指针始终指向头结点。当第一个指针指向k个结点的时候,两个指针同时向前遍历,这样确保两个指针距离为k。那么当第一个指针指向末尾结点时,第二个指针指向的就是倒数第k个结点。

4.并且需要注意潜在崩溃的风险。当输入的head为空指针时,代码会试图访问空指针的内存空间;输入的链表结点数小于k,for循环中会在链表上向前走k-1步,同样会造成空指针;当k是unsigned int型时,输入的参数k为0,此时for循环的k得到的不是-1,而是0xFFFFFFFF(4294967295),执行次数会非常非常大,造成程序崩溃。

解法

/*    public class ListNode {
        int val;
        ListNode next = null;
 
        ListNode(int val) {
            this.val = val;
        }
    }*/
 
public class Solution {
 
    public ListNode FindKthToTail(ListNode head,int k) {
        if(head == null)
            return null;
        ListNode P1=head;
        while(P1!=null && k-->0)
            P1=P1.next;
        //如果k大于链表的长度
        if(k>0){
            return null;
        }
        ListNode P2=head;
        while(P1!=null){
            P1=P1.next;
            P2=P2.next;
        }
        return P2;
    }
}

题目

输入一个链表,反转链表后,输出新链表的表头。 

思路

1.反转后链表的头结点就是原始链表的尾节点,即next为NULL的结点。

2.同样可以采用递归,使当前head的next指向null,不断反转。

3.或者采用头插法。构建一个新的指针用来指向

解法

/*
public class ListNode {
    int val;
    ListNode next = null;
 
    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode ReverseList(ListNode head) {
        if(head == null || head.next == null)
            return head;
        ListNode next=head.next;
        head.next=null;
        ListNode newHead=ReverseList(next);
        next.next=head;
        return newHead;
    }
    public ListNode ReverseList(ListNode head) {
 
 
           ListNode newList = new ListNode(- 1 );
 
 
           while (head != null ) {
 
 
               ListNode next = head.next;
 
 
               head.next = newList.next;
 
 
               newList.next = head;
 
 
               head = next;
 
 
           }
 
 
         return newList.next;
 
 
    }  
}

题目

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。 

思路

1.链表的合并过程如下,从合并两个链表的头结点开始,当链表1的头结点的值小于链表2的头结点值,因此链表1的头结点将为合并后链表的头结点。剩余结点中,链表2的头结点值小于链表1的头结点的值,因此链表2的头结点是剩余结点的头结点,把这个结点和之前合并好的链表的尾节点链接起来。不断比较两个链表的头结点的值。


2.为了防止访问空指针指向的内存空间引起的崩溃,需要处理当两个链表为空链表时的结果,当都为空链表时,合并的结果就是空链表。

解法

/*
public class ListNode {
    int val;
    ListNode next = null;
 
    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        if(list1==null)
            return list2;
        if(list2==null)
            return list1;
        if(list1.val<=list2.val){
            list1.next=Merge(list1.next,list2);
            return list1;
        }
        else{
            list2.next=Merge(list1,list2.next);
            return list2;
        }
    }
}

猜你喜欢

转载自www.cnblogs.com/lyeeer/p/12229982.html
今日推荐