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

限于喜欢 提交于 2020-01-23 00:22:14

题目

输入一个链表,输出该链表中倒数第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;
        }
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!