剑指offer(56~60)

删除链表中的重复结点

题目描述:

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

思路分析:
  • 首先添加一个头节点,以方便碰到第一个,第二个节点就相同的情况
  • 设置 pre ,last 指针,pre指针指向当前确定不重复的那个节点,而last指针相当于工作指针,一直往后面搜索
算法实现:
public class Solution {
    public ListNode deleteDuplication(ListNode pHead)
    {
        if (pHead==null || pHead.next==null){
            return pHead;
        }
        ListNode head = new ListNode(0);
        head.next = pHead;
        ListNode p  = head;
        ListNode q = head.next;
        while (q!=null){
            if(q.next!=null && q.val == q.next.val){
                while (q.next!=null && q.val == q.next.val){
                    q = q.next;
                }
                p.next = q.next;
                q = q.next;
            }else{
                p = p.next;
                q = q.next;
            }
        }
        return head.next;
    }
}

二叉树的下一个结点

题目描述:

给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。

思路分析:

分三种情况讨论:

  • 二叉树为空,则返回空;
  • 节点右孩子存在,则设置一个指针从该节点的右孩子出发,一直沿着指向左子结点的指针找到的叶子节点即为下一个节点;
  • 节点不是根节点。如果该节点是其父节点的左孩子,则返回父节点;否则继续向上遍历其父节点的父节点,重复之前的判断,返回结果。
算法实现:
public class Solution {
    public TreeLinkNode GetNext(TreeLinkNode pNode)
    {
        if(pNode == null)
            return null;
        if(pNode.right != null){
            pNode = pNode.right;
            while(pNode.left != null){
                pNode = pNode.left;
            }
            return pNode;
        }
        while(pNode.next != null){
            if(pNode.next.left == pNode)
                return pNode.next;
            pNode = pNode.next;
        }
        return null;
    }
}

对称的二叉树

题目描述:

请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。

思路分析:

采用递归的方法。定义一个函数比较:

  • 左子树的左子树和右子树的右子树是否相同
  • 左子树的右子树和右子树的左子树是否相同
算法实现:
public class Solution {
    boolean isSymmetrical(TreeNode pRoot)
    {
        if(pRoot == null)
            return true;
        return comRoot(pRoot.left,pRoot.right);
    }
    private boolean comRoot(TreeNode left,TreeNode right){
        if(left == null)
            return  right == null;
        if(right == null)
            return false;
        if(left.val == right.val)
            return comRoot(left.left,right.right) && comRoot(left.right,right.left);
        return false;
    }
}

按之字形顺序打印二叉树

题目描述:

请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。

思路分析:

定义一个队列用来保存每层的节点,并把根节点添加进队列中进行初始化,当队列不为空时,逐个出队列中的元素,并把这个元素加到列表中,再把它的左结点和右结点添加进队列中,注意:在使用队列来进行层次遍历。不需要使用两个队列分别存储当前层的节点和下一层的节点,因为在开始遍历一层的节点时,当前队列中的节点数就是当前层的节点数,只要控制遍历这么多节点数,就能保证这次遍历的都是当前层的节点。要想实现之字形打印可以定义一个boolean变量,每打印一行就对该变量进行取反即可。

算法实现:
public class Solution {
    public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> list = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(pRoot);
        boolean reverse = false;
        while(!queue.isEmpty()){
            ArrayList<Integer> eachDepth = new ArrayList<>();
            int count = queue.size();
            while(count > 0){
                count --;
                TreeNode node = queue.poll();
                if(node == null)
                    continue;
                eachDepth.add(node.val);
                queue.add(node.left);
                queue.add(node.right);
            }
            if(reverse)
                Collections.reverse(eachDepth);
            reverse = !reverse;
            if(eachDepth.size() != 0)
                list.add(eachDepth);
        }
        return list;
    }
}

把二叉树打印成多行

题目描述:

从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。

思路分析:
  • 非递归方法,思路同上。
  • 用递归的方法,方法中传递一个当前结点所在层次就可以用前序遍历实现了。
算法实现:
非递归方法:
public class Solution {
    ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> list = new ArrayList<>();
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        if(pRoot != null)
            queue.add(pRoot);
        int num = 1;
        while(!queue.isEmpty()){
            ArrayList<Integer> eachDepth = new ArrayList<>();
            int temp = 0;
            while(num > 0){
                num --;
                TreeNode node = queue.poll();
                eachDepth.add(node.val);
                if(node.left != null){
                    temp ++;
                    queue.add(node.left);
                }
                if(node.right != null){
                    temp ++;
                    queue.add(node.right);
                }
            }
            num = temp;
            list.add(eachDepth);
        }
        return list;
    }
}
递归实现:
public class Solution {
    ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        ArrayList<ArrayList<Integer>> list = new ArrayList<>();
        depth(pRoot,1,list);
        return list;
    }
    
    private void depth(TreeNode root,int depth,ArrayList<ArrayList<Integer>> list){
        if(root == null)
            return ;
        if(depth > list.size())
            list.add(new ArrayList<Integer>());
        list.get(depth-1).add(root.val);
        depth(root.left,depth+1,list);
        depth(root.right,depth+1,list);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值