zoukankan      html  css  js  c++  java
  • 第四章

        /**
         * 面试题27 输入一颗二叉树,输出一颗对称的二叉树
         * 思路:从根结点开始,交换两个子结点
         *
         * @param root
         */
        public void mirror(TreeNode root) {
            if (root == null) return;
            TreeNode temp = root.left;
            root.left = root.right;
            root.right = temp;
            mirror(root.left);
            mirror(root.right);
        }
        /**
         * 面试题28:判断输入二叉树是否是对称二叉树
         * 思路:将前序遍历和前序对称遍历获取的结点值进行比较
         *
         * @param root
         * @return
         */
        public boolean isSym(TreeNode root) {
            //invalid input
            if (root == null) return false;
            return isSymCore(root, root);
        }
    
        private boolean isSymCore(TreeNode root1, TreeNode root2) {
            //递归结束条件
            if (root1 == null && root2 == null) return true;
            if (root1 == null || root2 == null) return false;
            if (root1.val != root2.val) return false;
            //root1 and root2 是对称遍历
            return isSymCore(root1.left, root2.right) && isSymCore(root1.right, root2.left);
        }
        /**
         * 面试题30:含有O(1)min方法的栈
         * 思路:建立一个辅助栈,该栈中栈顶元素始终是当前数据栈中的最小元素。
         */
        private Stack<Integer> dateStack = new Stack<>();
        private Stack<Integer> minStack = new Stack<>();
    
        public void push(int date) {
            //入栈的数据是当前最小值,注意minStack为空的情况
            if (date < minStack.peek() || minStack.empty()) {
                minStack.push(date);
            } else minStack.push(minStack.peek());
            dateStack.push(date);
        }
    
        public int pop() {
            minStack.pop();//栈为空时抛出异常
            return dateStack.pop();
        }
    
        public int min() {
            return minStack.peek();
        }
        /**
         * 面试题31:判断压入栈和弹出栈是否匹配
         * 思路:建立一个辅助栈
         * 当辅助栈顶元素值为空,或者与出栈序列不同时,入栈序列入栈
         * 相同时,出栈序列出栈,辅助栈出栈
         *
         * @param pushA
         * @param popA
         * @return
         */
        public boolean IsPopOrder(int[] pushA, int[] popA) {
            //invalid input
            if (pushA == null || popA == null) return false;
            int pushALen = pushA.length;
            int popALen = popA.length;
            if (pushALen != popALen) return false;
            //匹配
            int pushAptr = 0;
            int popAptr = 0;
            Stack<Integer> stack = new Stack<>();
            while (popAptr != popALen) {
                if (stack.empty() || stack.peek() != popA[popAptr]) {
                    if (pushAptr == pushALen) return false;
                    else stack.push(pushA[pushAptr++]);
                } else {
                    stack.pop();
                    ++popAptr;
                }
            }
            return true;
        }
        /**
         * 面试题32: 从上到下打印二叉树
         * 思路:用队列保存下一层要打印的结点
         * 从队列中出一个结点,打印后将该结点的左右子结点加入队列中,直到队列为空结束
         * <p>
         * 面试题32(题目二): 从上到下分行打印二叉树
         * 思路:在队列中添加分行标志位
         *
         * @param root
         * @return
         */
        public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
            ArrayList<Integer> result = new ArrayList<>(); //save result
            //invalid input
            if (root == null) return result;
            LinkedList<TreeNode> queue = new LinkedList<>();//assist queue
            queue.offer(root);
            while (!queue.isEmpty()) {
                TreeNode temp = queue.poll();
                result.add(temp.val);
                if (temp.left != null)
                    queue.offer(temp.left);
                if (temp.right != null)
                    queue.offer(temp.right);
            }
            return result;
        }
        /**
         * 面试题33:判断数组是否为搜索二叉树的后序遍历序列
         * 思路:
         * 1 数组最后一个元素为该树的根节点
         * 2 根据该根节点将数组前面的元素划分为左子树部分和右子树部分
         * 3 递归调用,判断是否是后序遍历
         *
         * @param sequence
         * @return
         */
        public boolean VerifySquenceOfBST(int[] sequence) {
            //invalid input
            if (sequence == null) return false;
            int length = sequence.length;
            if (length == 0) return false;
            return VerifySquenceOfBSTCore(sequence, 0, length - 1);
        }
    
        private boolean VerifySquenceOfBSTCore(int[] sequence, int lo, int hi) {
            if (lo < 0 || hi < 0 || lo >= hi) return true;
            int rootVal = sequence[hi]; //根结点值
            int leftroot = -1;
            int rightroot = -1;
            if (sequence[lo] < rootVal) leftroot = lo;
            int i = -1;//迭代变量
            for (i = lo; i < hi; i++) { //找第一个大于根节点的值
                if (sequence[i] > rootVal) {
                    rightroot = i;
                    break;
                }
            }
            for (i = i + 1; i < hi; i++) {//判断后面的元素是否均大于根结点值
                if (sequence[i] <= rootVal)
                    return false;
            }
            return VerifySquenceOfBSTCore(sequence, leftroot, rightroot - 1) &&
                    VerifySquenceOfBSTCore(sequence, rightroot, hi - 1);
        }
        /**
         * 面试题34:二叉树中和为某一值的路径
         * 技巧,可以用三层树型结构来代测试
         * 思路:
         * 1 递归的寻找路径,在遍历过程中记录经过的路劲
         * 2 递归到叶结点时判断该路径是否符合条件,并添加到结果数组中
         *
         * @param root
         * @param target
         * @return
         */
        public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int target) {
            ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
            if (root == null) return result;
            ArrayList<Integer> path = new ArrayList<>();
            findPath(root, target, path, result);
            return result;
        }
    
        private void findPath(TreeNode root, int target, ArrayList<Integer> path, ArrayList<ArrayList<Integer>> result) {
            if (root == null) return;
            if (root.left == null && root.right == null) { //叶结点
                path.add(root.val);
                if (root.val == target)
                    result.add(new ArrayList<Integer>(path));
                path.remove(path.size() - 1);
                return;
            }
            path.add(root.val);
            findPath(root.left, target - root.val, path, result);
            findPath(root.right, target - root.val, path, result);
            path.remove(path.size() - 1);
        }
        /**
         * 面试题35:复杂链表的复制
         * 思路:
         * 1 在更复杂链表中插入相同的结点
         * 2 连接自由结点
         * 3 分离两条链表
         *
         * @param pHead
         * @return
         */
        public RandomListNode Clone(RandomListNode pHead) {
            if (pHead == null) return null;
            //     * 1 在更复杂链表中插入相同的结点
            RandomListNode copyNode = pHead;
            while (copyNode != null) {
                RandomListNode node = new RandomListNode(copyNode.label);
                node.next = copyNode.next;
                copyNode.next = node;
                copyNode = copyNode.next.next;
            }
            //     * 2 连接自由结点
            copyNode = pHead;
            while (copyNode != null) {
                copyNode.next.random = copyNode.random == null ? null : copyNode.random.next;
                copyNode = copyNode.next.next;
            }
            //     * 3 分离两条链表
            copyNode = pHead;
            RandomListNode node = pHead.next;
            RandomListNode result = pHead.next;
            while (copyNode.next.next != null) {
                copyNode.next = copyNode.next.next;
                node.next = node.next.next;
                copyNode = copyNode.next;
                node = node.next;
            }
            copyNode.next = null; //容易忽视
            return result;
        }
        /**
         * 面试题36:将二叉搜索树转化成一个排序的双向链表
         * 思路
         * 1 中序遍历递归地构造双向链表,并返回双向链表的尾部
         *
         * @param pRootOfTree
         * @return
         */
        private TreeNode tail = null; //链表的尾部
        private TreeNode head = null; //链表的头部
    
        public TreeNode Convert(TreeNode pRootOfTree) {
            ConvertCore(pRootOfTree);
            return head;
        }
    
        private void ConvertCore(TreeNode node) {
            if (node == null) return;
            ConvertCore(node.left);
            if (tail == null) {
                tail = node;
                head = node;
            } else {
                tail.right = node;
                node.left = tail;
                tail = node;
            }
            ConvertCore(node.right);
        }
        /**
         * 面试题38:打印输入字符串的所有排列
         *  递归法,问题转换为先固定第一个字符,求剩余字符的排列;求剩余字符排列时跟原问题一样。
         * (1) 遍历出所有可能出现在第一个位置的字符(即:依次将第一个字符同后面所有字符交换);
         * (2) 固定第一个字符,求后面字符的排列(即:在第1步的遍历过程中,插入递归进行实现)。
         * 需要注意的几点:
         * (1) 先确定递归结束的条件;
         * (2) 去重复;
         * (3) 按字典顺序排列;
         * @param str
         * @return
         */
        public ArrayList<String> Permutation(String str) {
            char[] strArr = str.toCharArray();
            ArrayList<String> result = new ArrayList<>();
            if(str==null||str.length()==0) return result;
            Set<String> res = new TreeSet<>(); //利用TreeSet集合类来实现去重复和排序
            Permutation(strArr, 0, res);
            result.addAll(res);
            return result;
        }
    
        private void Permutation(char[] strArr, int index,  Set<String> result) {
            if (index == strArr.length) {
                result.add(new String(strArr));
                return;
            }
            for (int i = index; i < strArr.length; i++) {
                exch(strArr, index, i); //确定一个位置的字符
                Permutation(strArr, index + 1, result);
                exch(strArr, index, i);
            }
        }
    
        private void exch(char[] arr, int i, int j) {
            char temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
  • 相关阅读:
    Table的基本操作
    MySQL数据库基本操作
    jmeter中服务器返回的cookies的查看
    jemeter的乱码问题
    cucumber的报告
    Cucumber的依赖
    idea里maven执行插件pom文件依赖设置
    Tomcat和jenkins的安装
    maven配置
    Ajax必知必会
  • 原文地址:https://www.cnblogs.com/youzoulalala/p/11337690.html
Copyright © 2011-2022 走看看