剑指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;

    } 
}

题目

输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

思路

 判断A中有一部分子树的结构与B是一样的,则采用递归。

1.在树A中找到与B的根结点值相同的结点R

2.判断树A中以结点R为根结点的子树是否包含与B一样的结构。根据根结点找到相同结构的部分,再往下比较

解答

/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }
}
*/
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        boolean result=false;
        //检查空指针
        if(root1!=null && root2!=null){
            //当A的某一结点的值和树B的头结点值相同,则做第二步判断
            if(root1.val == root2.val)
                //判断树A中以R为根结点的子树是不是和树B具有相同的结构
                result = DoesTree1HaveTree2(root1, root2);
            //如果当前根节点不相同,就看root1的左结点和root2的根节点比较。就是低一层比较
            if(!result)
                result=HasSubtree(root1.left, root2);
            if(!result)
                result=HasSubtree(root1.right, root2);
        }
        return result;
    }
    
    public boolean DoesTree1HaveTree2(TreeNode root1, TreeNode root2){
        //递归的终止条件:即到达了树A或树B的叶结点
        if(root2 == null)
            return true;
        if(root1 == null)
            return false;
        //若结点R的值和树B的根结点不相同,那么它们肯定不具有相同的结点
        if(root1.val != root2.val)
            return false;
        //如果值相同,那么递归判断它们各自的左右结点值是不是相同
        return DoesTree1HaveTree2(root1.left, root2.left) &&
               DoesTree1HaveTree2(root1.right, root2.right);
    } 
}

题目

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

思路

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;
        }
    }
}
posted @ 2020-01-22 23:43  闲不住的小李  阅读(186)  评论(0编辑  收藏  举报