剑指offer
文章平均质量分 73
zmingyang
这个作者很懒,什么都没留下…
展开
-
链表中倒数第k个节点--剑指offer(JAVA)
题目:输入一个链表,输出该链表中倒数第k 个结点。为了符合大多数人的习惯,本题从1 开始计数,即链表的尾结点是倒数第1 个结点.例如一个链表有6 个结点,从头结点开始它们的值依次是1 、2、3、4、5 、6。这个链表的倒数第3 个结点是值为4 的结点。思路:由于链表没有从后往前的指针,因此直接的想法是将每个链表值储存在某些数据结构中,但这样需要额外的空间。或者把指针遍历两边,第一遍记录总节点数,从而计算出倒数第K个节点正数应该在第几个,然后第二遍找到目标节点。这样的时间复杂度为O(n2),因为需要遍历原创 2020-07-10 18:26:11 · 248 阅读 · 0 评论 -
调整数组顺序使奇数位于偶数前面--剑指offer(JAVA)
题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。思路:设置两个指针,一个指向开头设为i并从前往后遍历,一个指向结尾设为j并从后往前遍历。当i读到当前数为奇数时,i继续往后走,当读到偶数时则停下。j从后往前遍历,同理。当两指针都停下,则交换数字。最终当i>=j时,循环结束。public class Solution { public void ReorderOddEven(int[] array){原创 2020-07-10 17:46:58 · 153 阅读 · 0 评论 -
表示数值的字符串--剑指offer(JAVA)
题目:请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串”+100”,”5e2”,”-123”,”3.1416”和”-1E-16”都表示数值。 但是”12e”,”1a3.14”,”1.2.3”,”±5”和”12e+4.3”都不是。思路:对字符进行逐个遍历,如果遇到不符条件就立刻终止返回false。若全部符合则最终返回true首先对特殊字符进行处理1.e、E 1)不能出现两次 2)不能是字符串末尾2. ‘+’,’-’ 1)其位置要么在开头要么在e或E后 2)后原创 2020-07-10 17:33:56 · 135 阅读 · 0 评论 -
删除链表的节点--剑指Offer(JAVA)
题目1:在O(1)时间内删除链表节点给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间内删除该节点。思路:如果直接从头节点遍历,找到待删节点n的上一节点,然后将上一节点的下节点设为n的下节点,即可删除n,但此方法时间复杂度为O(n)。实际上,完成该操作不一定需要节点n的上一节点,我们把n的下一节点的值赋给n,再将n的下一节点设为下下节点即可。需要考虑的特殊情况是n不存在下一节点,此时就只能遍历了。public class Solution { //l1为头结点,l2为待删节点原创 2020-07-10 11:27:04 · 201 阅读 · 0 评论 -
打印从1到最大的n位数--剑指offer(JAVA)
题目:输入数字n,按顺序打印出从1到最大的n位十进制数。比如输入3,则打印出1,2,3一直到最大的3位数999.思路:因为没有指定n的范围,因此直接对数字进行打印,不管是int型还是long型都有可能会溢出。因此我们使用数组来完成。基于此,有不基于递归的方法1和基于递归的方法2。方法1中,设置好用于存放数字的数组后,需要设置数组加一,以及进位的方法。方法2中,直接实现对于每位数字从1到9的打印,需要留意的是当前正在对哪一位数字进行操作,因此每次递归需要一个值进行判断。两种方法都需要打印函数,该原创 2020-07-10 10:22:17 · 150 阅读 · 0 评论 -
数值的整数次方--剑指offer(JAVA)
题目:实现函数double Power(double base, int exponent),求base的exponent次方。不得使用库函数,同事不需要考虑最大数问题。思路:本题的关键在于考虑问题要全面。由于要考虑整数次方,就要考虑指数为负,为0,为正的情况,同时结合base是否为0的情况。当指数为负,底数(base)为0时,就会出现对0做除法,报错。最后,对算法再进行优化,减少乘法次数。public class Solution { public double Power(doub原创 2020-07-09 11:07:39 · 119 阅读 · 0 评论 -
二进制中1的个数--剑指offer(JAVA)
题目:请实现一个函数,输入一个整数,输出该整数二进制表示中1的个数。例,输入9,9的二进制表示为1001,因此输出2.思路:本题很明显要使用到位运算,将该数字n的二进制的每一位与1相与,那么要么这个n不断右移,要么数字1不断左移。因为考虑到负数右移会强制把最高位位置1,在该题目中间就会引起错误,因此采用第二种左移的方法。public class Solution { private int NumberOf1(int n) { int count = 0;原创 2020-07-09 10:15:45 · 124 阅读 · 0 评论 -
剪绳子--剑指offer(JAVA)
题目:给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1,m<=n),每段绳子的长度记为k[1],…,k[m]。请问k[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。思路:使用递归会有很多重复计算,因此最好从下往上计算,使用动态规划法解题。建立数组res[ ]用来存放结果。当长度为0~3时,其结果对应相等。因为2,3越切越小。当长度大于4时,结果等于max(f(i)*原创 2020-07-09 09:56:00 · 172 阅读 · 0 评论 -
矩阵中的路径--剑指offer(JAVA)
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。 例如a b t gc f c sj d e h这样的3 X 4 矩阵中包含一条字符串"bfce"的路径,但是矩阵中不包含"abfb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。思路:本题可使用回溯法解决。定义一个与矩阵等原创 2020-07-08 11:08:32 · 165 阅读 · 0 评论 -
旋转数组的最小数字--剑指offer
题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1.思路:最直观的思路是直接遍历一遍。但这种思路没有用到旋转数组的特性。 我们可以把旋转数组看成两个递增数组,例如上文的{3,4,5},和{1,2}。因此通过判断中间数字属于第一个递增数组或者第二个递增数组,即可实现二分法。具体思路如下:1.使用两个指针分别指向数组的第一个元素和最后一个原创 2020-07-07 11:48:40 · 91 阅读 · 0 评论 -
斐波那切数列--剑指offer
题目:写一个函数,输入n,求斐波那切数列的第n项。斐波那切数列的定义如下0 n=0f(n) = 1 n=1f(n-1)+ f(n-2) n>1思路:直接进行递归会出现大量的重复计算,效率很低。因此使用循环的方法解决。public class Solution { public static long Fibonacci(int n){ if (n<=0) return 0原创 2020-07-07 10:40:13 · 159 阅读 · 1 评论 -
两个栈实现队列,两个队列实现栈
题目:1.使用两个栈实现一个队列。实现队列的两个函数,入队和出队。2.使用两个队列实现一个栈,实现栈的入栈出栈。思路:使用辅助,用题目1举例,使用栈1和栈2实现。入队操作:1.先将栈1所有元素放到栈2,2.将新元素放入栈13.将栈2元素放回栈1这样,新元素就在栈1的底部。出队操作:直接将栈1栈顶元素出栈即可。题目二同理import java.util.Stack;/* 使用两个栈 完成一个队列*/public class aQueen { public aQueen(原创 2020-07-07 10:25:09 · 167 阅读 · 0 评论 -
数组中重复的数字
题目:在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了多少次。请找出数组中任意一个重复的数字。例:如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或3.思路:本题可以用多种方法解决1.遍历数组,预存上一个数字tmp,若tmp等于当前数字则返回当前数字,否则更改tmp的值即可。这种方法的时间复杂度为O(nlogn)2.使用哈希表来解决,每扫描一个数字就判断一下是否在哈希表中。如果已存原创 2020-07-06 10:37:12 · 149 阅读 · 0 评论 -
在排序数组中查找数字--剑指Offer(JAVA)
题目:统计一个数字在排序数组中出现的次数。例如,输入排序数组{1,2,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4.思路:利用二分法找到该数字第一次出现的位置与最后一次出现的位置进而求得次数。具体做法:利用middle=(start+end)/2,找到中间数字,并与目标数字比较,1.中间数字大于目标数字,则将搜索范围缩小为start到middle-12.中间数字小于目标数字,将搜索范围缩小为middle+1到end3.中间数字等于目标数字,此时分为找首次出现位置和最后一次原创 2020-06-20 21:49:12 · 187 阅读 · 0 评论 -
两个链表的第一个公共节点--剑指Offer(JAVA)
题目:输入两个链表,找出它们的第一个公共节点。链表节点定义如下:public class ListNode { int val; ListNode next = null; //构造节点 public ListNode(int val){ this.val = val; } }思路:如链表定义所示,两个链表都是单向链表。从公共节点开始,他们后续的节点都是一样的。因为链表是单向的,所以不能从后往前遍历。但题目所示结构其实是“后进原创 2020-06-20 20:15:02 · 165 阅读 · 0 评论 -
第一个只出现一次的字符--剑指offer(JAVA)
题目:在字符串中找出第一个只出现一次的字符。如输入"abaccdeff",则输出’b’。思路:使用哈希表来存储每个字符出现的次数。import java.util.HashMap;import java.util.Map;public class Solution { public char getFirstNotRepeatingChar(String s) { if (s==null||s.length()==0) return '原创 2020-06-20 20:07:54 · 82 阅读 · 0 评论 -
数据流的中位数--剑指Offer(JAVA)
题目:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。思路:我们选用存放数据的容器是最大堆和最小堆,左侧为最大堆,右侧为最小堆。最大堆的数字全部小于最小堆的数字,且最小堆的尺寸要么与最大堆相同,要么比最大堆尺寸大一。因此,当原本两堆大小相同时,新来的数字首先被加到最大堆,之后最大堆将堆顶数字加给最小堆(先加入最大堆的意义在于,保证传递给最小堆数字后,仍保持两堆大小关原创 2020-06-17 14:15:20 · 146 阅读 · 0 评论 -
丑数--剑指offer(JAVA)
题目:我们把只包含因子2, 3,5的数称作丑数。求从小到大的顺序的第1500个丑数。思路:第一种思路就是挨个遍历,查看每个数是不是丑数,当找到第1500个丑数时返回。还有另一种思路,仅仅对丑数进行处理。我们从题目可知,每个丑数都是由其他丑数乘以2,3,5获得的。这样我们把求得的丑数都保存下来,用之前的丑数分别乘以2,3,5,找出这三这种最小的并且大于当前最大丑数的值,即为下一个我们要求的丑数。public class Solution { public static void main(S原创 2020-06-16 22:08:47 · 186 阅读 · 0 评论 -
最长不含重复字符的子字符串--剑指offer(JAVA)
题目:请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度思路:首先定义一个数组列表longestSubstring 用来存放最长子字符串,并定义一个数组列表 cur用来存放正在遍历的字符。遍历字符串的字符时。若字符没出现过,则加入cur,若该字符已经出现,则比较两个数组列表的长度,将长的一个赋给longestSubstring,并将cur清零,加入新遍历到的重复字符。最后遍历结束时,再次将两字符串进行比较,将长的一个赋给longestSubstring。import j原创 2020-06-16 21:55:11 · 222 阅读 · 0 评论 -
礼物的最大价值--剑指offer(JAVA)
题目:在一个 m*n 的棋盘中的每一个格都放一个礼物,每个礼物都有一定的价值(价值大于0).你可以从棋盘的左上角开始拿各种里的礼物,并每次向右或者向下移动一格,直到到达棋盘的右下角。给定一个棋盘及上面个的礼物,请计算你最多能拿走多少价值的礼物?思路:我们利用递归的思路来分析。定义函数f(i,j)表示到达坐标为(i,j)的格子时能拿到的礼物总和的最大值。根据题目要求,我们要么从(i-1,j),要么从(i,j-1)到达(i,j)。因此f(i,j) = max( f( i-1 , j ) , f( i ,原创 2020-06-16 20:37:03 · 241 阅读 · 0 评论 -
把数字翻译成字符串--剑指offer(JAVA)
题目: 给定一个数字,我们按照如下规则把它翻译为字符串:0翻译成"a",1翻译成"b",……,11翻译成"l",……,25翻译成"z"。一个数字可能有多个翻译。例如12258有5种不同的翻译,它们分别"bccfi", “bwfi”, “bczi”, “mcfi” 和"mzi" 。请编程实现一个函数用来计算一个数字有多少种不同的翻译方法思路:使用递归的方法解决,每次读取一个或两个数字,递归结束后再删除当前添加字符。package jianzhioffer;import java.util.Arra原创 2020-06-16 20:28:54 · 158 阅读 · 0 评论 -
把数组排成最小的数--剑指offer(JAVA实现)
题目:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。思路:把数组中的数字按照特殊比较规则进行排列,最终输出即可。特殊比较规则指两个数字如何排列能使拼接起来数最小。一种方法是先比较最高位,若不同直接分结果。若相同则比较下一位,若其中一个数字没有下一位,看另外一个数字的下一位较上一位是否变小了。如比较3,32。首位相同,次位2小于3,所以32<3。这种方法比较麻烦,另一种原创 2020-06-15 19:14:02 · 117 阅读 · 0 评论 -
数组中出现次数超过一半的数字(JAVA)
题目:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如,输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2;思路:方法一:将数组排序,取中位数,查看其出现次数。若大于数组长度的一半则输出方法二:遍历数字的时候保存两个值,一个是数字的值,另一个是其出现的次数。当我们遍历到一个数字的时候,如果他跟我们之前保存的数字一致,则次数加一,否则次数减一。当次数为0时,保存下一个数字并把次数设为一,由于我们要找的数字占所原创 2020-06-14 21:47:51 · 210 阅读 · 0 评论 -
二叉搜索树与双向链表--剑指offer(JAVA实现)
题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。思路:首先由于要求转换之后的链表是排好序的,我们可以中序遍历树中的每个节点,这是因为中序遍历算法的特点是按照从小到大的顺序遍历二叉树的每个节点。具体遍历时,我们可以把树分为三部分,左子树、根、右子树。根据双向链表的定义,根节点将与左子树对应链表的最后一个节点互联,同理与右子树对应链表的第一个节点互联。理清思路就可以使用递归实现:public class MS36 { pu原创 2020-06-12 11:26:59 · 170 阅读 · 0 评论 -
二叉树中和为某一值的路径(JAVA)
题目:输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。思路:由于要打印路径,且路径总是以根节点开头。因此我们想到前序遍历。之后由于需要对所有路径进行遍历,且存在返回上一节点的情况,想到使用回溯法。考虑回溯条件,当两种情况需要回溯:1.当前节点为空2:当前节点的左右子节点都已经遍历过。以下为代码实现:TreeNode定义:public class TreeNode { int val;原创 2020-06-11 18:10:03 · 190 阅读 · 0 评论 -
二叉树的下一个节点--剑指offer(JAVA实现)
题目:给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。思路:我们具体分情况考虑。当一个节点有右子树,那么他的下一个节点就是其右子树的最左子节点。当以节点没有右子树,那么再分为他是他父亲的左孩子还是右孩子。当该节点是其父亲节点的左孩子,那么他的下一节点就是其父亲。当该节点是其父亲节点的右孩子,那么他的下一节点是距离最近的父节点是该父节点的父节点的左孩子的节点。import java.util.Scanner;pu原创 2020-06-10 22:11:19 · 193 阅读 · 0 评论 -
重建二叉树--剑指offer(JAVA实现)
题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。思路:前序遍历第一个数字就是根节点的值m,然后在中序遍历结果中,在m左侧即为m的左子树,右侧即为右子树。这样,我们就在前序遍历和中序遍历两个序列中分别找到了左右子树对应的子序列。通过递归,即可构建该二叉树。public class MS7 { publ原创 2020-06-10 22:03:00 · 165 阅读 · 0 评论 -
二叉树的三种遍历(递归和非递归)
首先给出二叉树的定义:public class BinaryNode { int element; BinaryNode leftChild; BinaryNode rightChild; public BinaryNode(int element){ this.element = element; } public String toString() { return "BinaryNode [element=" + ele原创 2020-06-10 21:56:24 · 221 阅读 · 0 评论 -
从尾到头打印列表--剑指offer(JAVA实现)
题目:输入一个链表的头结点,从尾到头打印每个节点的值。链表节点定义如下:struct ListNode{int m_nKey;ListNode* m_pNext;}思路:我们希望之执行一个打印操作,不改变原本内容。因此,根据栈后进先出的特点,使用栈即可简单解决。import java.util.Stack;public class MS6 { public static ArrayList<Integer> printListFrom原创 2020-06-10 21:49:21 · 130 阅读 · 0 评论 -
数组中重复的数字
题目一:在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3。思路一:利用哈希表解决问题。从头到尾扫描数组的每个数字,每扫描到一个数字,用O(1)的时间来判断哈希表是否包含了该数字。如果哈希表里还没有该数字,就加入哈希表,否则就找到了一个重复数字; public static void原创 2020-06-10 21:41:16 · 182 阅读 · 0 评论 -
正则表达式匹配--剑指offer(JAVA实现)
问题描述:请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配。思路:对字符串和模式字符串进行遍历。由于是前的字符可以出现任何次,所以算法执行是逆字符串顺序。分别设置字符串的开头i=str.length()-1,模式字符串开头m=mode.length()-1。当对应字原创 2020-06-06 11:06:50 · 246 阅读 · 0 评论 -
打印1到最大的N位数--剑指Offer(JAVA实现)
题目:输入数字n,按顺序打印出从1到最大的n位十进制数。比如输入3,则打印出1、2、3一直到最大的3位数即999。思路:由于未指定n的大小,当n特别大时,无论是整形(int)或者长整型(long)都会溢出。因此使用数组的方法来避开陷阱。方法一为普通循环法,方法二为递归法。package jianzhioffer;public class MS17 { public static void main(String[] args) { int n = 2;原创 2020-06-05 12:08:12 · 252 阅读 · 0 评论 -
机器人的运动范围--回溯法(JAVA实现)
题目:地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?思路:使用一个与矩阵等大小的布尔数组防止重复计算。用两个栈记录坐标,最后返回栈大小即为运动范围package jianzhioffer;import j原创 2020-06-02 21:36:38 · 165 阅读 · 0 评论 -
替换空格(JAVA实现)
题目描述:请实现一个函数,把字符串中的每个空格替换成“%20”。例如,输入“We are happy.”,则输出“We%20are%20happy.”解题思路:为了减少时间复杂度,减少字符重复向后移动,把从前向后替换改为从后向前替换。具体实现是通过StringBuffer构建新字符串,通过设置新的长度,将新的index与原来的index进行逐一对应。构造出需要的字符串。public class MS5 { public static void main(String[] args) {原创 2020-05-18 23:55:52 · 176 阅读 · 0 评论 -
二维数组的查找
题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个证书,判断该数组中是否含有该整数。二维数组使用例子中给出的二维数组1 2 8 92 4 9 124 7 10 136 8 11 15要搜索的整数N设为7总体思路是不断缩小搜索范围,实现方法如下:1.先排除没有可能的列数2.再排除没有可能的行数3.对可能包含目标的小二维数组遍历,查找有无N按照例子来说,首先将N与第一行的数从原创 2020-05-18 18:25:55 · 140 阅读 · 0 评论