
剑指Offer(Java实现)
算法与数据结构
pengsel
信仰圣光吧。
展开
-
剑指Offer 32 从1到n整数中1出现的次数
题目输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。思路本文思路主要参考从1到n整数中1出现的次数:O(logn)算法注意是求1出现的次数,而不是求包含1的数字的个数。对于一个数abcde,个位出现1的个数为abcd;十位出现1的个数:如果d>1,为abc10+10;如果d==1,为abc10+e+1;如果<1,则为abc*10;同理可以求百位。pu...原创 2019-02-18 19:13:17 · 153 阅读 · 0 评论 -
剑指Offer 31 连续子数组的最大和
题目输入一个整形数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求复杂度为O(n)。思路从前往后相加为currentSum,如果发现累加和为负数,丢掉之前的累加和;greatestSum保存最大的值。public class Q31FindGreatestSumOfSubArray { /** * 当累加和出现负数时...原创 2019-02-18 16:26:07 · 114 阅读 · 0 评论 -
剑指Offer 30 最小的K个数
题目输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。思路方法一:复杂度O(n)O(n)O(n);当可以修改输入的数组时,可以采用类似于快速排序的思路,最终使得比array[k-1]小的数字在它的左边,而比array[k-1]大的数字在它的右边,最终返回k-1以前的元素。首先进行一次partition,得到一个i...原创 2019-02-16 20:51:17 · 122 阅读 · 0 评论 -
剑指Offer 28 字符串的排列
题目输入一个字符串,打印出该字符串中字符的所有排列。思路首先求所有可能出现在第一个位置的字符,即把第一个字符和后面所有的字符交换;然后固定一个字符,求后面所有字符的排列;可能出现在第一个位置的字符为stringBuilder.charAt(index),index为其中任意一个字符;在固定了在index位置的一个字符后,求后面所有字符的排列,递归调用permutation(stringB...原创 2019-02-08 13:22:08 · 178 阅读 · 0 评论 -
剑指Offer 27 二叉搜索树与双向链表
题目输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整结点指针的指向。思路对于二叉搜索树,采用中序遍历按照从小到大的顺序遍历二叉树的每一个结点,因此,只需要记录上一个结点lastNodeInList,将其和当前遍历的结点连接起来,便可实现转换。初始化:需要一个共享的静态变量lastNodeInList,以便在两次递归调用中传递上一次的结果。初始...原创 2019-02-08 12:16:38 · 114 阅读 · 0 评论 -
剑指Offer 26 复杂链表的复制
题目复制一个复杂链表。在复杂链表中,每个结点除了有一个指针指向下一个结点外,还有一个指针指向链表中的任意结点或者null。思路方法一:创建哈希表,用空间换时间方法二:分成三部分,分别实现根据原始链表的每个结点N创建对应的N’,并把N’连接在N后面设置复制出来的结点的sibling把长链表分成两个链表public class Q26Clone { static class...原创 2019-02-07 20:46:44 · 130 阅读 · 0 评论 -
剑指Offer 25 二叉树中和为某一值的路径
题目输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。从树的根节点开始往下一直到叶结点所经过的结点形成一条路径。思路前序遍历二叉树,并用一个栈stack来存储路径,用一个变量sumPath存储路径之和;每当前序遍历从子结点返回父节点时,弹出该子结点,并且sumPath减去该结点的值;findPath(BiTreeNode root,int expectedSum)创...原创 2019-02-07 18:24:59 · 158 阅读 · 0 评论 -
剑指Offer 24 二叉搜索树的后序遍历序列
题目输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。思路定义描述二叉排序(搜索)树(Binary Sort Tree)又称为二叉查找树,或者是一棵空树,或者满足:1、若它的左子树不空,则左子树上所有的结点的值均小于它的根结点的值;2、若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉排序树。对于一个后序遍历序...原创 2019-02-07 16:23:00 · 110 阅读 · 0 评论 -
剑指Offer 23 从上往下打印二叉树
题目从上往下打印出二叉树的每个结点,同一层的结点从左到右的顺序打印。思路要求同一层的结点从左向右顺序打印,可以想到队列;对于根节点,压入队列的顺序是先左结点,后右结点;考虑第二层,左子树的左结点、右结点进入队列,此时队列第一位为右子树根节点,故将右子树的左结点和右结点压入队列,可以看到第三层是有序的按照数学归纳法,假设第k层是有序的,队列中存储着有序的第k层的各个结点,递推到第k+1层...原创 2019-02-07 12:36:54 · 114 阅读 · 0 评论 -
剑指Offer 22 栈的压入、弹出序列
题目输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出序列。思路注意压入栈的元素可以随时弹出,因此弹出序列有多种;创建一个辅助栈,按照压入序列向栈中压入元素;每当压入一个元素时,如果这个元素刚好是弹出序列元素,那么直接弹出;如果不是,则把压栈序列中还没有入栈的数字压入辅助栈,直到栈顶元素为相应弹出序列元素;如果所有元素都压入栈而和按照弹出顺序的元素都不相等,...原创 2019-02-07 11:55:54 · 157 阅读 · 0 评论 -
剑指Offer 21 包含min函数的栈
题目定义栈的数据结构,实现一个能够得到栈的最小元素的min函数。调用min,push和pop的时间复杂度都是O(1)。思路错误的思路:设置一个成员变量,如果添加的元素变量比它小,则更新该成员变量。这种思路当从栈中弹出了最小元素,如何保证该成员变量是最小的;正确的做法是将每次的最小元素都保存在另外一个辅助栈中;注意边界条件:当栈为空时返回栈的最小值。public class Q21...原创 2019-02-06 20:51:19 · 127 阅读 · 0 评论 -
剑指Offer 20 顺时针打印矩阵
题目输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每个数字。思路采用一个二维数组来输入矩阵元素;顺时针打印一个二维数组,将二维数组分成多个圈,起点为(start,start),从外圈向内圈循环遍历,循环继续的条件是数组的列和行都大于2∗start2*start2∗start;由于最后一圈可能退化成只有一行或者一列,将打印一圈分成四个过程,如下图所示:过程1是必须的;过程2的前提...原创 2019-02-06 18:12:19 · 154 阅读 · 0 评论 -
剑指Offer 19 二叉树的镜像
题目输入一个二叉树,输出它的镜像。思路首先考虑对应单一一个结点,交换其左右结点需要一个引用temp来暂存一个结点,以便交换。此时要注意三种情况:两个结点都不为null;有一个结点为null;两个结点都为null。其实此处可以不管,虽说第三种不需要交换,但是需要增加对每个结点判断其左右结点是否为null,这时可以直接把这种情况也直接交换,以减少判断。此外,注意鲁棒性,mirror()函数输...原创 2019-02-06 16:43:55 · 120 阅读 · 0 评论 -
剑指Offer 18 树的子结构
题目输入两棵二叉树A和B,判断B是不是A的子结构。思路首先在A树中找到树B的根节点node,再比较两个树node和B是否相等;比较node是否包含B的树结构:采用递归的方式,遍历时只要有一个结点值不相等,就返回false;当B的子结点到达尾部null时,返回true;而如果B的子节点不为null,node的子结点为null时,要返回false,这个检查要在比较树结点值前进行,否则会...原创 2019-02-06 16:05:06 · 92 阅读 · 0 评论 -
剑指Offer 17 合并两个排序的链表
题目输入两个递增排序的链表,合并这两个链表并使得新链表中的结点仍然按照递增排序。思路非递归方式需要一个存储合并链表的头结点mergeHead和一个存储合并链表的结点mergeCurrent;初始化:判断两个链表head1和head2哪个小,小的作为mergeHead,同时将小的那一方head指向head.next;mergeHead指向前一个加入链表的元素,即mergeHead;循环...原创 2019-01-24 21:58:12 · 129 阅读 · 0 评论 -
剑指Offer 16 反转链表
题目定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。思路类似于数学归纳法:第i个结点以前的i-1个结点已经满足条件了,i-1这个节点用preNode来指代,i结点用currentNode指代,此时如果将currentNode.next直接指向preNode,则后面的链表就断了,因此要用一个结点nextNode来存储结点以防止链表断了。初始化:currentNode...原创 2019-01-24 16:48:30 · 124 阅读 · 0 评论 -
剑指Offer 15 链表中倒数第k个结点
题目输入一个链表,输出该链表中倒数第k个结点。(链表从1开始计数。)思路两个指针a和b,a指向第一个,b先指向第k个;ab同时移动,直到b指向链表的尾部;注意边界条件:输入链表为null,K<=0,K大于链表的长度。代码public static ListNode findKthToTail(ListNode head){ if(head == null||k<=0...原创 2019-01-24 16:18:46 · 98 阅读 · 0 评论 -
剑指Offer 14 调整数组顺序使奇数位于偶数前面
题目输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部。思路两个指针a和b,a指向第一个数字,b指向最后一个数字;a向后移动直到指向一个偶数,b向前移动直到指向一个奇数,交换两数;直到a和b指向同一个数。代码 public static void reorder(int[] array){ if...原创 2019-01-24 16:06:15 · 89 阅读 · 0 评论 -
剑指Offer 13 在O(1)时间删除链表结点
题目给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。分析如果按照顺序查找,时间复杂度为O(n);把后一节点的内容复制到该结点,该结点指向下下结点;删除结点位于尾部时,需要遍历得到该结点的前一结点。链表只有一个结点。代码public class DeleteNode { class Node{ public int data; ...原创 2019-01-14 21:23:39 · 126 阅读 · 0 评论 -
剑指Offer 12 打印1到最大的n位数
题目输入数字n,按顺序打印从1最大的n位十进制数。分析考虑大数问题;在字符串上模拟数字加法的解法;终止条件是第一个字符产生了进位,以此快速判断是否结束,而不是比较两个字符串;输出时注意去掉补位用的0;或者把问题转换成数字排列问题,采用递归。数字的每一位都可能是0-9中的一位数,然后设置下一位。踩了个坑Java中的for each不具备赋值作用,只能遍历,相当于赋值给了一个临时...原创 2019-01-14 21:12:55 · 202 阅读 · 0 评论 -
剑指Offer 11 数值的整数次方
题目实现函数 double power(dower base, int exponent),求base的exponent次方。分析指数可能是负数;base可能是0;不可忽视的细节,判断底数是否等于0时,由于精度丢失问题,不可以直接写base==0。采用递归减少循环次数。采用全局变量标识出错误。代码public class Power { public static b...原创 2019-01-14 20:56:06 · 196 阅读 · 0 评论 -
剑指Offer10 二进制中1的个数
题目输入一个整数,输出二进制表示中1的个数。负数采用的是补码形式。分析采用移位代替除法。输入负数时要避免进入死循环。代码public class NumberOf1 { public static int number(int num){ int count=0; for(int i=0;i&lt;32;i++){ ...原创 2019-01-14 20:46:42 · 117 阅读 · 0 评论 -
剑指Offer 09 斐波那契数列
递归虽然有简洁的优点,但它同时也有显著的缺点。递归由于是函数调用自身,而函数调用是有时间和空间的消耗的:每一次函数调用,都要在内存栈中分配空间以保存参数、返回地址及临时变量。而且往栈里压入数据和弹出数据都需要时间。题目:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。n&amp;lt;=39思路:采用递归会有大量的重复运算,所以采用循环...原创 2018-12-15 17:36:19 · 154 阅读 · 0 评论 -
剑指Offer 08 旋转数组的最小数字
查找包括顺序查找、二分查找、哈希表查找、二叉排序树查找。排序包括插入排序、冒泡排序、归并排序、快速排序。考虑额外空间消耗、平均时间复杂度、最差时间复杂度。如果面试题是要求在排序的数组中查找一个数字或者统计某个数字出现的次数,都可以尝试二分查找算法。哈希表...原创 2018-12-15 17:10:26 · 104 阅读 · 0 评论 -
剑指Offer 06 重建二叉树
题目:重建二叉树输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。代码:/** * Definition for binary tree * public class TreeNode { * ...原创 2018-12-13 19:58:13 · 108 阅读 · 0 评论 -
剑指Offer 05 从尾到头打印链表
链表节点的创建:public class Node { public Object data; //存放节点值 public Node next; //后继节点的引用 ,将data,next定义为public类型,就不需要get,set方法了 public Node(){ this(null,null...原创 2018-12-11 20:14:04 · 102 阅读 · 0 评论 -
剑指Offer 04 替换空格
题目:将一个字符串中的空格替换成“%20”。思路:如果是在原来的字符串上做替换,就有可能覆盖修改在该字符串后面的内存;如果是创建新的字符串上做替换,就可以自己分配足够多的内存。StringBuffer和StringBuilder可以多次修改,并不产生新的未使用对象。StringBuilder类与StringBuffer的区别在于StringBuilder的方法不是线程安全的(不能同步访...原创 2018-12-11 19:16:37 · 134 阅读 · 0 评论 -
剑指Offer 03 二维数组中的查找
题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。思路:选取左上角或者右下角,每次剔除一行或者一列。注意:考虑边界条件和特殊输入(NULL指针,空字符串)及错误处理。二维数组输入是空指针二维数组中没有要查找的数字public class findInArra...原创 2018-12-11 18:43:19 · 97 阅读 · 0 评论 -
剑指Offer 02 实现Singleton模式
空类型的实例不含任何信息,本来求sizeof应该为0,但是声明该类型的实例时,必须在内存占据一定的空间,否则无法使用这些实例。原创 2018-12-10 21:14:00 · 139 阅读 · 0 评论 -
剑指Offer 29 数组中出现次数超过一半的数字
题目数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。思路方法1:快速排序使得序列有序,返回最中间的数。快速排序:在数组中随机选择一个数字,调整数组中数字的顺序,使得比选中数字小的元素排在它的左边,比选中数字大的数字排在它的右边;再递归的对低子表和高子表进行排序;快速排序的优化:优化中心枢轴:可以三数取中,取三个关键字先进行排序,将中间数作为枢轴,一般是取左端、中间和右...原创 2019-02-08 17:51:28 · 120 阅读 · 0 评论