剑指Offer
南方的南方
这个作者很懒,什么都没留下…
展开
-
剑指Offer30:连续子数组的最大和
输入一个长度为n的整型数组a,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为 O(n)。 思路:设dp[n]代表以当前元素为截止点的连续子序列(这个子序列必包括n)的最大和,当dp[n-1]大于0时,dp[n] = dp[n-1]加上当前数。 public class Solution { public int FindGreatestSumOfSubArray(int[] array) { if(array == null || array.l原创 2021-10-14 16:25:41 · 145 阅读 · 0 评论 -
剑指Offer37:数字在升序数组中出现的次数
题目:给定一个长度为 n 的非降序数组和一个非负数整数 k ,要求统计 k 在数组中出现的次数 要求:空间复杂度 O(1),时间复杂度 O(logn) 思路:用二分查找找到k,找到k后,k的左右两边有可能还有k,再查看左右两边是否有k即可。 import java.util.*; public class Solution { public int GetNumberOfK(int [] array , int k) { int index = Arrays.binarySearch原创 2021-10-14 14:47:00 · 162 阅读 · 0 评论 -
剑指Offer27:字符串的排列
题目:输入一个长度为 n 字符串,打印出该字符串中字符的所有排列,你可以以任意顺序返回这个字符串数组。 例如输入字符串ABC,则输出由字符A,B,C所能排列出来的所有字符串ABC,ACB,BAC,BCA,CBA和CAB。 数据范围:n < 10n<10 要求:空间复杂度 O(n!)O(n!),时间复杂度 O(n!)O(n!) import java.util.*; public class Solution { public ArrayList<String> Permuta原创 2021-10-14 14:42:41 · 152 阅读 · 0 评论 -
剑指Offer61:序列化二叉树
题目:请实现两个函数,分别用来序列化和反序列化二叉树,不对序列化之后的字符串进行约束,但要求能够根据序列化之后的字符串重新构造出一棵与原二叉树相同的树。 二叉树的序列化(Serialize)是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树等遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#) 二叉树的反序列化(Deserialize)是指:根据某种遍历顺序得到的序列化字符串原创 2021-10-13 22:44:29 · 65 阅读 · 0 评论 -
剑指Offer60:把二叉树打印成多行
题目:给定一个节点数为 n 二叉树,要求从上到下按层打印二叉树的 val 值,同一层结点从左至右输出。每一层输出一行。 思路:层次遍历。 import java.util.ArrayList; /* public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val;原创 2021-10-13 19:37:53 · 73 阅读 · 0 评论 -
剑指Offer58:对称的二叉树
题目:请实现一个函数,用来判断一棵二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。 思路: 递归比较左边的左子树与右边的右子树、左边的右子树与右边的左子树。 /* public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; }原创 2021-10-13 19:16:39 · 62 阅读 · 0 评论 -
剑指Offer57:二叉树的下一个结点
题目:给定一个二叉树其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的next指针。下图为一棵有9个节点的二叉树。树中从父节点指向子节点的指针用实线表示,从子节点指向父节点的用虚线表示 解法: 1.判断节点有没有右节点,如果有,则遍历右节点的左节点一直到底。 2.如果没有右节点,我们就需要取出父节点,这里有两种情况,一是当前节点是父节点的左节点,那么返回父节点即可;二是当前节点是父节点的右节点,那么我们令当前节点等于父节点,直到当前节点为父节点原创 2021-10-13 16:28:48 · 52 阅读 · 0 评论 -
剑指Offer39:平衡二叉树
题目:输入一棵节点数为 n 二叉树,判断该二叉树是否是平衡二叉树。 在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树 平衡二叉树(Balanced Binary Tree),具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。 样例解释: 解法:在求左右子树深度的时候加个判定。 public class Solution { private boolean isBalanced = true; public boolean原创 2021-10-06 00:13:30 · 67 阅读 · 0 评论 -
剑指Offer26:二叉搜索树与双向链表
题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。如下图所示 注意: 1.要求不能创建任何新的结点,只能调整树中结点指针的指向。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继 2.返回链表中的第一个节点的指针 3.函数返回的TreeNode,有左右指针,其实可以看成一个双向链表的数据结构 4.你不用输出双向链表,程序会根据你的返回值自动打印输出 解法:定义一个前置节点,当前节点的left等于前置节点,前置节点的right等于当前节点。 public class原创 2021-10-05 23:19:32 · 72 阅读 · 0 评论 -
剑指Offer24:二叉树中和为某一值的路径
题目:输入一颗二叉树的根节点root和一个整数expectNumber,找出二叉树中结点值的和为expectNumber的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。 如二叉树root为{10,5,12,4,7},expectNumber为22 解法:这里要注意的是路径必须是得到叶子节点的。 我们用先序遍历,一直遍历到叶子节点且当target为0时满足条件,这时是的节点顺序就是符合条件的,这里要重新创建ArrayList对象,划分新的内存空间,因为结尾处要remove最后原创 2021-10-05 21:32:38 · 88 阅读 · 0 评论 -
剑指Offer23:二叉搜索树的后序遍历序列
题目:输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则返回true,否则返回false。假设输入的数组的任意两个数字都互不相同。(ps:我们约定空树不是二叉搜索树) 解法:每颗子树都是搜索树,找到根节点(最后一位),左右子树分叉点,然后不断递归遍历即可。 public class Solution { public boolean VerifySquenceOfBST(int [] sequence) { if(sequence == null || sequ原创 2021-10-04 16:03:30 · 50 阅读 · 0 评论 -
剑指Offer62:二叉搜索树的第k个结点
题目:给定一棵节点数为 n 二叉搜索树,请找出其中的第 k 小的TreeNode结点。 解法:用中序遍历,遍历的第n的个节点就是第k小的。 public class Solution { private TreeNode result; private int count; TreeNode KthNode(TreeNode pRoot, int k) { if(pRoot == null || k == 0) return null;原创 2021-10-04 13:45:55 · 66 阅读 · 0 评论 -
剑指Offer59:按之字形顺序打印二叉树
题目:给定一个二叉树,返回该二叉树的之字形层序遍历,(第一层从左向右,下一层从右向左,一直这样交替) 示例 输入:{8,6,10,5,7,9,11} 返回值:[[8],[10,6],[5,7,9,11]] 解法:正常进行先序遍历,等到从右向左的时候把ArrayList逆转。 import java.util.*; public class Solution { public ArrayList<ArrayList<Integer> > Print(TreeNode pRoo原创 2021-10-04 13:02:25 · 89 阅读 · 0 评论 -
剑指Offer42:和为S的两个数字
题目:输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,返回两个数的乘积最小的,如果无法找出这样的数字,返回一个空数组即可。 解法:使用双指针,一个指针指向元素较小的值,一个指针指向元素较大的值。指向较小元素的指针从头向尾遍历,指向较大元素的指针从尾向头遍历。 如果两个指针指向元素的和 sum == target,那么得到要求的结果。 如果 sum > target,移动较大的元素,使 sum 变小一些。 如果 sum < target,移动原创 2021-10-03 21:17:19 · 54 阅读 · 0 评论 -
剑指Offer41:和为S的连续正数序列
题目:小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? 解法: 假设输入sum=20,遍历的范围是1到 sum/2 + 1(因为最少要有两个数,所以不会超过sum/2,考虑到奇数的问题,加1) 1.定义两个指针,左指针从1开始,右指针从2原创 2021-10-03 21:06:52 · 52 阅读 · 0 评论 -
剑指Offer33:丑数
题目:把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第 n个丑数。 解法:我们可以维护三个list,分别是乘2得到的丑数,乘3得到的丑数,乘5得到的丑数,但这样复杂度较高,而且会得到重复的丑数。实际上每次我们只用比较3个数:用于乘2的最小的数、用于乘3的最小的数,用于乘5的最小的数。这样只需要维护三个指针,而不用维护三个数组。 import java.util.*; public cl原创 2021-10-03 16:25:08 · 55 阅读 · 0 评论 -
剑指Offer32:把数组排成最小的数
题目:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。 解法:关键在于如何判定两个数的大小位置。利用贪心的思想,整个数是最小的,那么任意两个数的排列也是较小的。所以判定方式为:若s1 + s2大于s2+s1,那么s1更大。 import java.util.ArrayList; public class Solution { public String PrintMinN原创 2021-10-03 15:10:58 · 75 阅读 · 0 评论 -
剑指Offer31:整数中1出现的次数(从1到n整数中1出现的次数)
题目:输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数。例如,1~13中包含1的数字有1、10、11、12、13因此共出现6次 解法一:暴力解法 import java.util.*; public class Solution { public int NumberOf1Between1AndN_Solution(int n) { int count = 0; // 循环 1->n for(int i=1;i<=n;i++原创 2021-10-03 14:32:14 · 78 阅读 · 0 评论 -
剑指Offer28:数组中出现次数超过一半的数字
题目:给一个长度为 n 的数组,数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。 解法一:用一个Map装下每个数出现的次数。 import java.util.*; public class Solution { public int MoreThanHalfNum_Solution(int [] array) { HashMap<Int原创 2021-10-03 12:30:47 · 119 阅读 · 0 评论 -
剑指Offer51:构建乘积数组
题目:给定一个数组A[0,1,…,n-1],请构建一个数组B[0,1,…,n-1],其中B中的元素B[i]=A[0]A[1]…*A[i-1]A[i+1]…*A[n-1]。不能使用除法。(注意:规定B[0] = A[1] * A[2] * … * A[n-1],B[n-1] = A[0] * A[1] * … * A[n-2];)对于A长度为1的情况,B无意义,故而无法构建,因此该情况不会存在。 示例: 输入:[1,2,3,4,5] 输出:[120,60,40,30,24] 解法:就是第 i 次遍历跳过 i原创 2021-10-03 10:29:41 · 55 阅读 · 0 评论 -
剑指Offer34:第一个只出现一次的字符
题目:在一个长为 字符串中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数) 解法:每次用""来替换字符串的第i个字符,如果长度只减少 1 ,那么说明第 i 个字符只出现一次 public class Solution { public int FirstNotRepeatingChar(String str) { for(int i=0;i<str.length();i++){ String temp原创 2021-10-03 10:29:26 · 48 阅读 · 0 评论 -
剑指Offer38:二叉树的深度
题目:输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。 解法一:递归 public int TreeDepth(TreeNode root) { if(root==null){ return 0; } int left=TreeDepth(root.left); int right=TreeDepth(root.right); return Math.max(left,right)原创 2021-10-03 00:35:38 · 89 阅读 · 0 评论 -
剑指Offer64:滑动窗口的最大值
题目:给定一个长度为 n 的数组 num 和滑动窗口的大小 size ,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,原创 2021-10-02 22:28:33 · 212 阅读 · 0 评论 -
剑指Offer56:删除链表中重复的节点
题目:在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5 解法:判断当前节点和之后节点有没有重复即可,比较特殊的就是需要有个前置节点来做处理。 public class Solution { public ListNode deleteDuplication(ListNode pHead) { if(pHead ==原创 2021-10-02 22:29:30 · 52 阅读 · 0 评论 -
剑指Offer55:链表中环的入口
题目:给一个长度为n链表,若其中包含环,请找出该链表的环的入口结点,否则,返回null。 示例: 输入:{1,2,3,4,1,5} 输出:节点1 解法:有环就是会指向重复节点,重复的节点就是环的入口,遍历过程中输入与之前重复的节点即可。这里借助HashMap结构 import java.util.*; public class Solution { public ListNode EntryNodeOfLoop(ListNode pHead) { if(pHead == null原创 2021-10-02 22:30:43 · 76 阅读 · 0 评论 -
剑指Offer44:翻转单词
题目:牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“nowcoder. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a nowcoder.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么? 示例: 输入:"nowcoder. a am I" 返回值:"I am a nowcoder." 解法:借助栈即可。 import原创 2021-10-02 22:28:59 · 46 阅读 · 0 评论 -
剑指Offer36:两个链表的第一个公共节点
题目:输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。 示例: 输入:{1,2,3,6,7},{4,5,6,7} 输出:{6,7} 解法一: 利用HashSet,先把一个链表装入HashSet,再遍历另一个链表。 import java.util.*; public class Solution { public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) { if(pHe原创 2021-10-02 22:30:15 · 50 阅读 · 0 评论 -
剑指Offer25:复杂链表的复制
题目:输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)。 下图是一个含有5个结点的复杂链表。图中实线箭头表示next指针,虚线箭头表示random指针。为简单起见,指向null的指针没有画出。 解法一:分两次遍历,第一次遍历建立一个正常链表,并且把节点都存储起来,第二次遍历把随即节点补上,这里要用到存储起来的节点。 imp原创 2021-10-02 22:29:50 · 59 阅读 · 0 评论 -
剑指Offer20:从上往下打印二叉树
题目:从上往下打印出二叉树的每个节点,同层节点从左至右打印。 思路:用一个队列按需要存放节点位置即可。从根节点开始,出队列,得到值,再把它的左右节点存进队列即可。 import java.util.ArrayList; import java.util.Queue; import java.util.*; /** public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null;原创 2021-09-17 17:47:09 · 43 阅读 · 0 评论 -
剑指Offer19:包含min函数的栈
题目:定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数,并且调用 min函数、push函数 及 pop函数 的时间复杂度都是 O(1) push(value):将value压入栈中 pop():弹出栈顶元素 top():获取栈顶元素 min():获取栈中最小元素 示例: 输入: [“PSH-1”,“PSH2”,“MIN”,“TOP”,“POP”,“PSH1”,“TOP”,“MIN”] 输出: -1,2,1,-1 解析: "PSH-1"表示将-1压入栈中,栈中元素为-1原创 2021-09-17 13:33:39 · 47 阅读 · 0 评论 -
剑指Offer18:栈的压入、弹出序列
题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的) 解法:1.用指针i指向pushA的第一个位置, 指针j指向popA的第一个位置;2.如果pushA[i] != popA[j], 那么应该将pushV[i]放入栈中, ++i;3.否则,pushV[i原创 2021-06-06 23:20:18 · 61 阅读 · 2 评论 -
剑指Offer17:顺时针打印矩阵
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10. 解法: ...原创 2021-06-05 23:19:11 · 50 阅读 · 0 评论 -
剑指Offer16:二叉树的镜像
题目:操作给定的二叉树,将其变换为源二叉树的镜像。 解法: public TreeNode Mirror (TreeNode pRoot) { // write code here if(pRoot == null) return null; TreeNode temp = pRoot.left; pRoot.left = pRoot.right; pRoot.right = temp; Mirror(pRoot.left);原创 2021-06-04 14:19:38 · 48 阅读 · 0 评论 -
剑指Offer15:树的子结构
题目:输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构) 解法: public class Solution { public boolean HasSubtree(TreeNode root1,TreeNode root2) { if (root1 == null || root2 == null) return false; return isSubtreeWithRoot(root1, root原创 2021-06-01 16:38:54 · 40 阅读 · 0 评论 -
剑指Offer14:合并两个排序的链表
题目:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。 解法一:比较两个链表当前节点的大小,小的加入新节点,链表向后移一位 public class Solution { public ListNode Merge(ListNode list1,ListNode list2) { if(list1 == null) return list2; if(list2 == null)原创 2021-05-31 23:09:58 · 57 阅读 · 3 评论 -
剑指Offer13:反转链表
题目:输入一个链表,反转链表后,输出新链表的表头。原创 2021-05-30 22:57:59 · 43 阅读 · 0 评论 -
剑指Offer12: 链表中倒数第k个结点
题目:输入一个链表,输出该链表中倒数第k个结点。如果该链表长度小于k,请返回空。 解法一:用一个数组装着所有节点 public ListNode FindKthToTail (ListNode pHead, int k) { // write code here ListNode temp = pHead; int size = 0; ArrayList<ListNode> nodes = new ArrayList<ListNode>();原创 2021-05-28 23:28:09 · 59 阅读 · 0 评论 -
剑指Offer11:调整数组顺序使奇数位于偶数前面
题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。 解法一: public int[] reOrderArray (int[] array) { ArrayList<Integer> one = new ArrayList<Integer>(); ArrayList<Integer> two = new ArrayList<原创 2021-05-10 15:53:24 · 43 阅读 · 0 评论 -
剑指Offer10:二进制中1的个数
题目:输入一个整数,输出该数32位二进制表示中1的个数。其中负数用补码表示。 解法一: Java自带 public int NumberOf1(int n) { return Integer.bitCount(n); } 解法二: 常规解法 public int NumberOf1(int n) { int count = 0; int flag = 1; while (flag != 0) { //flag只有以为是1,也只有这意味取且后可能为1,如果n原创 2021-04-27 22:44:49 · 47 阅读 · 0 评论 -
剑指Offer9:矩形覆盖
题目 解题思路:与跳格子类似,要么一次性拼2 x 1,要么一次拼2 x 2,其他都是这两种组合。对于2 x n,就是从2 x n-1 + 2 x n-2得到,即f(n)=f(n-1)+f(n-2) 解法一: 递归 public class Solution { public int rectCover(int target) { if (target<=2) return target; ...原创 2021-04-25 22:59:29 · 69 阅读 · 0 评论