• 剑指offer


    十、代码的鲁棒性

    1. 链表中倒数第k个节点

    题目描述:

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

    思路:

    ​ 为了实现只遍历链表一次就能找到倒数第k个节点,我们可以定义两个指针。第一个指针从链表的第一个节点开始向前走k-1步,第二个指针则保持原地不动;从第k步开始,第二个指针也开始从链表的第一个节点开始遍历。由于两个指针的距离始终保持在k-1,当第一个(走在前面的)指针到达链表的尾节点时,第二个(走在后面的)指针恰好指向倒数第k个节点。

    代码:

    /*
    public class ListNode {
        int val;
        ListNode next = null;
    
        ListNode(int val) {
            this.val = val;
        }
    }*/
    public class Solution {
        public ListNode FindKthToTail(ListNode head,int k) {
        	//当输入的head为空指针或者k为0时,返回null
            if (head == null || k == 0) {
                return null;
            }
            ListNode ahead = head;
            ListNode behind = head;
            for (int i = 1; i <= k - 1; i++) {
                ahead = ahead.next;
                //若k的值大于链表长度时,返回null
                if (ahead == null) {
                    return null;
                }
            }
            while (ahead.next != null) {
                ahead = ahead.next;
                behind = behind.next;
            }
            return behind;
        }
    }
    

    2. 链表中环的入口节点

    题目描述:

    ​ 给一个不带头结点的单链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

    思路:

    ​ 先说个定理:两个指针一个fast、一个slow同时从一个链表的头部出发,fast一次走2步,slow一次走1步,如果该链表有环,两个指针必然在环内相遇,此时只需要把其中的一个指针重新指向链表头部,另一个不变(还在环内),这次两个指针一次走一步,相遇的地方就是入口节点。

    代码:

    /*
    struct ListNode {
        int val;
        struct ListNode *next;
        ListNode(int x) :
            val(x), next(NULL) {
        }
    };
    */
    class Solution {
    public:
        ListNode* EntryNodeOfLoop(ListNode* pHead)
        {
            ListNode *fast=pHead,*slow=pHead;
            while(fast->next!=NULL){
                fast=fast->next->next;
                slow=slow->next;
                if(fast==slow){
                    break;
                }
            }
            if(fast->next==NULL){
                return NULL;
            }else{
                fast=pHead;
                while(fast!=slow){
                    fast=fast->next;
                    slow=slow->next;
                }
                return fast;
            }
        }
    };
    

    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 p = head.next;
            head.next = null;
            while (p != null) {
                ListNode q = p.next;//在每次进行头插之前,要先保存好下一个节点,防止断链
                p.next = head;
                head = p;
                p = q;
            }
            return head;
        }
    }
    

    4. 合并两个排序的链表

    题目描述:

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

    思路:

    ​ 见代码。

    代码:

    /*
    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 && list2 == null) {
                return null;
            } else if (list1 == null) {
                return list2;
            } else if (list2 == null) {
                return list1;
            }
            ListNode head = new ListNode(-1);//新建一个头结点,用来存合并之后的链表(点睛之笔)
            ListNode p = head;
            while (list1 != null && list2 != null) {
                if (list1.val < list2.val) {
                    p.next = list1;
                    list1 = list1.next;
                } else {
                    p.next = list2;
                    list2 = list2.next;
                }
                p = p.next;
            }
            if (list1 != null) {
                p.next = list1;
            } else {
                p.next = list2;
            }
            return head.next;
        }
    }
    

    5. 树的子结构

    题目描述:

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

    思路:

    ​ 见代码。

    代码:

    /**
    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;
        	//当root1或root2中有一棵为空树时,直接返回false。
            if (root1 != null && root2 != null) {
            	//判断当前的根节点是否和root2的根节点相同
                if (root1.val == root2.val) {
                	//如果相同,继续判断
                    result = doesTree1HaveTree2(root1, root2);
                }
                //若找不到,去左子树继续找
                if (result == false) {
                    result = doesTree1HaveTree2(root1.left, root2);
                }
                //若左子树中也找不到,则去右子树继续找
                if (result == false) {
                    result = doesTree1HaveTree2(root1.right, root2);
                }
            }
            return result;
        }
    
        public static boolean doesTree1HaveTree2(TreeNode root1, TreeNode root2) {
        	//若树root2遍历完了都能对应上,返回true
            if (root2 == null) {
                return true;
            }
            //若root2还没有遍历完,root1却遍历完了,返回false
            if (root1 == null) {
                return false;
            }
            if (root1.val != root2.val) {//如果有不相同的节点,返回false
                return false;
            } else {//若根节点相同,则继续判断左右子树是否相同
                return doesTree1HaveTree2(root1.left, root2.left) && doesTree1HaveTree2(root1.right, root2.right);
            } 
        }
    }
    
  • 相关阅读:
    艾氏筛法资料
    CF Soldier and Cards (模拟)
    CF Soldier and Badges (贪心)
    POJ 1308 Is It A Tree? (并查集)
    HDU 1272 小希的迷宫 (并查集)
    HDU 1213 How Many Tables (并查集)
    POJ 1611 The Suspects (并查集)
    POJ 2236 Wireless Network (并查集)
    Iptables-linux服务器做路由转发
    asdf
  • 原文地址:https://www.cnblogs.com/jiajun107/p/12497866.html
Copyright © 2020-2023  润新知