一、请使用栈,设计一个数据结构,它具有栈的“先进后出”的特性,同时还可以获取栈中的最小值,要求此数据结构的pop、push、min方法的复杂度均为O(1)
这个题,最大的问题就在min方法上,如果不使用其他的辅助数据结构,是无法满足min方法的设计要求,即使使用一个临时变量保存当前的最小值(这种情况下,如果最小是被pop,就断片了。。)。所以我们的注意力就集中在:怎们能让一个栈是有序的?其实让栈内数据有序,使用排序的思路肯定是不行的,但是我们能够维持“最小值”的连续性就可以。看看如下的设计思路:
使用2个栈来设计这个数据结构,分别为数据栈和辅助栈 数据栈用来保存push的数据 辅助栈用来保存“最小值”的连续性: 栈底<--------->栈顶 1)添加3 数据栈:3 辅助栈:3,3为最小值 2)添加4 数据栈: 3 4 辅助栈: 3 3 因为4 > 3,为了保持“最小值”连续性,我们在4对应的辅助栈的位置上仍然添加3。 3)添加2 数据栈: 3 4 2 辅助栈: 3 3 2 因为3 > 2,最小值变了,所以讲新的最小值入栈。 如上所述,那么min方法,只需要从辅助栈中peek栈顶的元素值就行了。 当数据栈中pop元素时,也将辅助栈中对应位置的元素移除。
代码样例如下:
static class MinStack { Stack<Integer> data = new Stack<>(); Stack<Integer> helper = new Stack<>(); synchronized void push(Integer value) { data.push(value); int min = value; if(!helper.isEmpty()) { int current = helper.peek(); if(current <= value) { min = current; } } helper.push(min); } Integer min() { if(helper.isEmpty()) { return null; } return helper.peek(); } synchronized void pop() { if(data.isEmpty()) { return; } data.pop(); helper.pop(); } }
二、请编写一个算法用于判定:序列B为序列A作为栈时可能的弹出顺序(A中的数字不会重复)
听到题目,第一感觉就是:听不懂!
先描述一下:假如有序列A为[1,2,3,4,5],它作为栈时由1开始依次入栈,序列B为[5,4,3,2,1]是A作为栈时的一个弹出顺序。但是序列A在没有完全入栈时也可以弹出,比如[1,2,3,4]先入栈,然后弹出4,然后再将5入栈,那么其弹出序列就是[4,5,3,2,1]。因为A入栈和出栈的时机可以任意,所以它的出栈序列可能会有多种,请你判定一个给定的序列是否为A的一个出栈顺序。
实话说,看到这个题,我也没有思路...如下为分析过程,突破口就是要用一个辅助栈来保存A。
将A保存在数据栈,B使用一个辅助栈 A:1 2 3 4 5 B:4 5 3 2 1 (假设序列) 1) 遍历A和B,以B作为判断基准 2) 在B中第一个元素为4,因为A中1、2、3均不等于4,直到遇到4 则将它们都添加到数据栈 数据栈: 1 2 3 3)此时A与B都遇到4,我们认为是一次弹出(或者同时入栈,然后弹出) 4)B继续遍历,此时为5 判断,5是否与数据栈的栈顶一样,如果不一样,则遍历A的下一个元素。 5)此时A与B都遇到5,我们认为是一次弹出。 6)A序列遍历结束,只能根据数据栈作为判定。 7)B继续遍历,此时为3,从数据栈中弹出栈顶,比较是否也为3,如果是继续 8)重复7,直到不相等(返回false)或者数据栈全部弹出(返回true)。
解题思路总结:从B中确定弹出元素,比如a,如果辅助栈的栈顶刚还是a,则弹出,否则遍历A序列找到a,在a之前的元素全部添加到辅助栈中;如果所有的元素都查找完仍没有找到a,则认为判读失败。
代码样例:
public static void main(String[] args) { int[] source = {1,2,3,4,5}; int[] target = {3,5,4,2,1}; System.out.println(check(source,target)); } public static boolean check(int[] source,int[] target) { if(source.length == 0 || target.length == 0) { return false; } if(source.length != target.length) { return false; } int length = source.length; Stack<Integer> data = new Stack<>(); int di = 0;//数据序列的索引位置 for(int i = 0; i < length; i ++) { int item = target[i]; //入栈完毕 if(di == length) { if(data.isEmpty()) { return false; } int top = data.pop(); if(top == item) { continue; }else { return false; } } while (di < length) { int current = source[di]; if(item == current) { di++; break; } else if(data.isEmpty()){ data.push(current); di++; } else { int top = data.peek(); if(top == item) { data.pop(); break; }else { data.push(current); di++; } } } } return true; }
三、使用广度优先的方式遍历二叉树,并逐层打印节点值
广度优先,就是按照二叉树的level,逐级遍历。如果你有过此方面的算法经验,其实这个题非常简单。如果你喜欢钻牛角尖,估计这题不好办!钻牛角尖的思路就是:递归、遍历、数组等等。
推演思路:
假如输入二叉树,树的结构如下: 8 /\ 6 10 /\ /\ 5 7 9 11 当前节点 队列 8 6,10 6 10,5,7 10 5,7,9,11 5 7,9,11 7 9,11 9 11 11 空 要求打印结果:8 6 10 5 7 9 11
突破口已经有了,就是使用一个队列来保存即将参与打印的节点。太有才了,此后大家需要记住,广度遍历二叉树时要使用队列!!代码样例如下:
static class BinaryTree { BinaryTreeNode root; } static class BinaryTreeNode { BinaryTreeNode left; BinaryTreeNode right; int value; } public static void print(BinaryTree tree) { if(tree == null) { return; } BinaryTreeNode root = tree.root; if(root == null) { return; } Queue<BinaryTreeNode> data = new LinkedList<>(); data.add(root); while (!data.isEmpty()) { BinaryTreeNode current = data.poll(); System.out.print(current.value + ","); BinaryTreeNode left = current.left; if(left != null) { data.add(left); } BinaryTreeNode right = current.right; if(right != null) { data.add(right); } } }
我们还需要简单考虑一下,如果打印结果的要求是“逐层”?
比如上述二叉树,打印结果为: 8 6 10 5 7 9 11
此时我们发现一个队列其实无法满足设计需要,我们需要用两个队列:
1) 队列1 队列二 8 空 空 6 10 2) 队列1 队列二 空 6 10 5 7 10 5 7 9 11 空 基本思路就是,在将其中一个队列出队的时候,将其 子节点添加到另一个队列的尾部,且每次都将当前队列 完全出队,此后再以同样的方式操作另一个队列。
代码样例:
public static void print(BinaryTree tree) { if(tree == null) { return; } BinaryTreeNode root = tree.root; if(root == null) { return; } Queue<BinaryTreeNode> first = new LinkedList<>(); Queue<BinaryTreeNode> second = new LinkedList<>(); first.add(root); while (true) { if(first.isEmpty() && second.isEmpty()) { break; } if(first.isEmpty()) { inner(first,second); }else { inner(second,first); } } } private static void inner(Queue<BinaryTreeNode> first,Queue<BinaryTreeNode> second) { while (!second.isEmpty()) { BinaryTreeNode current = second.poll(); System.out.print(current.value + ","); BinaryTreeNode left = current.left; if(left != null) { first.add(left); } BinaryTreeNode right = current.right; if(right != null) { first.add(right); } } System.out.println(); }
四、输入一个整数数组,判断该数组是否为某二叉搜索树的后序遍历结果
我们首先分析一下二叉树后序遍历结果的特点,比如{5,7,6,9,11,10,8}是一个正常的二叉树后序遍历结果;最后一个元素一定是root节点,即为8;从数组的一个元素开始,首次遇到的比8大的元素之前的元素列表都是8的左子树,其他的为右子树,比如{5,7,6}为左子树,{9,11,10}为右子树。当然每个子树也是“后序遍历”的结果,比如对于左子树,6就是其根节点,5是其左节点,7是有节点。这种比较的合法性是可传递的,即任何节点的左子树元素都应该小于它的值,右子树的元素都大于它的值。(无重复元素)
比如输入{7,4,6,5},判断这个序列是否为后序遍历结果;由此得知:5是跟节点,{7,4,6}是它的右子树,但是其中4小于5,不符合判定规则,因此判断结果为false。
代码样例:
public static boolean check(int[] source,int start,int end) { if(start == end) { return true; } int root = source[end]; int i = start; //判断左子树的位置 for(;i < end; i++) { if(source[i] > root) { break; } } int j = i; for(;j < end - 1;j++) { if(source[j] < root ) { return false; } } boolean left = true; if(i > 0) { left = check(source, start, i - 1); } if(!left) { return false; } boolean right = true; if (i < end - 1) { right = check(source, i, end - 1); } return left && right; }
相关推荐
JAVA算法编程题目及答案 本资源提供了50道JAVA算法编程题目及答案,涵盖了算法设计、数据结构、程序设计等多个方面的知识点。以下是对标题、描述、标签和部分内容的详细解释: 标题:JAVA算法编程题目及答案 本...
C#数值计算算法编程 周长发,有利于数值算法编程开发
本资料主要关注并行计算的三个方面:结构、算法和编程,旨在通过习题解答帮助学习者深入理解和应用这些概念。 1. **并行计算结构**: 并行计算结构通常分为共享内存和分布式内存两大类。共享内存系统中,所有...
《算法&&编程》这个主题包含了两个至关重要的计算机科学领域,它们是解决问题和构建软件系统的基础。算法是设计解决特定问题的步骤序列,而编程则是将这些算法转化为计算机可执行的语言。这里,我们深入探讨这两个...
通过阅读本书,你将熟悉遗传算法与编程语言相关的问题和概念,掌握构建自己的算法所需的全部知识,并且将获得用遗传算法解决问题的能力。请拿起本书,进入遗传算法这个迷人的领域,看看真正能工作的Java代码,并运用...
12 用 C#实现数伯叶算算法的要点 7 第 2 章 复数运算 .................................. · ·12 2.1 复数类设计 12 2.2 复数乘法 25 23 复数附法 26 2.4 复数的膜 书,27 25 复数的根 28 2.6 复数的实茄指数 29...
并行计算 陈国良编著 呵呵 大家来下载 是第三版《并行计算:结构•算法•编程(第3版)》是并行计算系列丛书之开篇,它以并行计算为主题,围绕并行计算机、并行算法和并行程序设计展开讨论,强调融并行计算机体系结构、...
在《并行计算——结构·算法·编程》这本书中,作者深入探讨了这一主题,提供了丰富的习题来帮助读者理解和掌握相关概念。现在,我们来详细探讨这些习题答案中可能涵盖的知识点。 首先,结构方面,可能包括以下内容...
游戏算法电子书 感觉不错 分享给大家 游戏核心算法编程内幕.pdf
《游戏核心算法编程内幕》由三部分组成。其中第一部分主要介绍游戏编程的基本概念;第二部分详细介绍游戏编程中的各种技术和算法;第三部分是附录,介绍游戏编程中相关技术和知识以及其他相关读物。《游戏核心算法...
《JAVA遗传算法编程》这本书是面向对遗传算法有兴趣并希望通过Java语言进行实现的读者的一本专业指南。遗传算法(Genetic Algorithm,简称GA)是一种基于生物进化论中的自然选择和遗传原理的优化方法,它在解决复杂...
PDF格式的C#数值计算算法编程,记录了各种初级、高级算法。
一本基于java遗传算法编程技术的讲解书书籍,全书讲解很全面,适合对遗传算法感兴趣的读者。本书共分为6章,每章都会有实例。
第三本书可能涉及动态规划、回溯法、贪心策略和分支限界等高级算法。动态规划用于解决具有重叠子问题和最优子结构的问题,如背包问题和斐波那契数列。回溯法用于在庞大的解决方案空间中寻找解,如八皇后问题和迷宫...
"Python编程入门与算法进阶.pptx" Python编程入门与算法进阶是一本全面介绍Python编程语言和算法的书籍。本书分为两个部分,第一部分是Python编程入门,第二部分是算法进阶。 在Python编程入门部分,本书详细讲解...
《Scratch编程入门与算法进阶》是一本面向青少年和初学者的Scratch编程和算法教育书籍,本书以图文并茂的方式,系统地介绍了Scratch编程的基础知识和常用算法,旨在帮助读者深入理解计算机编程的基本概念和思想,...
在编程领域,算法是解决问题的核心工具,它们是逻辑和数学思维在编程中的应用。"编程语言算法100例"这个资源集成了多种编程语言下的基础算法实例,旨在帮助程序员理解和掌握算法的基本概念,以及如何在实际编程中...