剑指 Offer 31. 栈的压入、弹出序列
剑指 Offer 31. 栈的压入、弹出序列题目123456789101112131415161718192021输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。示例 1:输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]输出:true解释:我们可以按以下顺序执行:push(1), push(2), push(3), push(4), pop() -> 4,push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1示例 2:输入:pushed = [1,2,3,4,5], popped = [4,3,5,1,2]输出:false解释:1 不能在 2 之前弹出。 提示:0 ...
剑指 Offer 32 - I. 从上到下打印二叉树
剑指 Offer 32 - I. 从上到下打印二叉树题目123456789101112131415从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。例如:给定二叉树: [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7返回:[3,9,20,15,7]提示:节点总数 <= 1000
思路就是数的广度遍历,但是这个使用int数据接收的,我们可以先用一个list接收,然后最后把list放入数组中,这里可以使用for循环遍历也可以stream流
实现123456789101112131415161718192021222324private static class Solution { public int[] levelOrder(TreeNode root) { if (root == null) { return new int[0]; } Deque<TreeNode> ...
剑指 Offer 15. 二进制中1的个数
剑指 Offer 15. 二进制中1的个数题目1234567891011121314151617181920212223242526编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 '1' 的个数(也被称为 汉明重量).)。提示:请注意,在某些语言(如 Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。在 Java 中,编译器使用 二进制补码 记法来表示有符号整数。因此,在上面的 示例 3 中,输入表示有符号整数 -3。 示例 1:输入:n = 11 (控制台输入 00000000000000000000000000001011)输出:3解释:输入的二进制串 00000000000000000000000000001011 中,共有三位为 '1'。示例 2:输入:n = 128 (控制台输入 00000000000000000000000010000000)输出:1解释:输入的二进制 ...
剑指 Offer 17. 打印从1到最大的n位数
剑指 Offer 18. 删除链表的节点题目1234567891011121314151617给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。返回删除后的链表的头节点。注意:此题对比原题有改动示例 1:输入: head = [4,5,1,9], val = 5输出: [4,1,9]解释: 给定你链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9. 示例 2:输入: head = [4,5,1,9], val = 1输出: [4,5,9]解释: 给定你链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9. 说明:题目保证链表中节点的值互不相同若使用 C 或 C++ 语言,你不需要 free 或 delete 被删除的节点
思路使用两个变量记录上一个节点和当前节点,如果相等,则pre.next = crrent.next
实现123456789101112131415161718192021222324252627282930313233343536pu ...
剑指 Offer 14- II. 剪绳子 II
剑指 Offer 14- II. 剪绳子 II题目1234567891011121314151617181920给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m - 1] 。请问 k[0]*k[1]*...*k[m - 1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。 示例 1:输入: 2输出: 1解释: 2 = 1 + 1, 1 × 1 = 1示例 2:输入: 10输出: 36解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36 提示:2 <= n <= 1000
思路这个就是对最终结果求余,但是如果用我们的动态规划的解法,对结果求余不能使用,因为这不是简单的累乘,而是这一步的结果要与上一步的结果记性大小比较,所以不能对动态规划求余。
现在我找到的都是使用的贪心算法,然后 ...
剑指 Offer 19. 正则表达式匹配
剑指 Offer 19. 正则表达式匹配题目1234567891011121314151617181920212223242526272829303132333435363738请实现一个函数用来匹配包含'. '和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但与"aa.a"和"ab*a"均不匹配。示例 1:输入:s = "aa"p = "a"输出: false解释: "a" 无法匹配 "aa" 整个字符串。示例 2:输入:s = "aa"p = "a*"输出: true解释: 因为 '*' 代表可以匹 ...
剑指 Offer 14- I. 剪绳子
剑指 Offer 14- I. 剪绳子题目12345678910111213141516给你一根长度为 n 的绳子,请把绳子剪成整数长度的 m 段(m、n都是整数,n>1并且m>1),每段绳子的长度记为 k[0],k[1]...k[m-1] 。请问 k[0]*k[1]*...*k[m-1] 可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。示例 1:输入: 2输出: 1解释: 2 = 1 + 1, 1 × 1 = 1示例 2:输入: 10输出: 36解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36提示:2 <= n <= 58
思路这是一个明显的几何均值不等式$$\frac{n_1 + n_2 + … + n_a}{a} \geq \sqrt[a]{n_1 n_2 … n_a}$$这是高中题,结果我完全没有印象了,怀疑我的高中是怎么上的。
推论一:将绳子 以相等的长度等分为多段 ,得到的乘积最大。
当长度相等即n1=12=..=na的时候取最大值
推论二: 尽可能将绳子以长 ...
剑指 Offer 22. 链表中倒数第k个节点
剑指 Offer 22. 链表中倒数第k个节点题目12345678910输入一个链表,输出该链表中倒数第k个节点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾节点是倒数第1个节点。例如,一个链表有 6 个节点,从头节点开始,它们的值依次是 1、2、3、4、5、6。这个链表的倒数第 3 个节点是值为 4 的节点。示例:给定一个链表: 1->2->3->4->5, 和 k = 2.返回链表 4->5.
思路两次遍历首先想到的就是先遍历一遍,拿到总节点的数量,然后减去k,便得到我们要正向遍历第几个节点,然后在遍历一次
时间复杂度:O(2n)= O(n)
空间复杂度:O(1)
双指针设定两个指针之间的差值为(k-1),快的指针从头遍历到尾,则慢指针刚到到倒数k的位置
实现两次遍历:
12345678910111213141516private static class Solution { public ListNode getKthFromEnd(ListNode head, int k) { int size ...
剑指 Offer 17. 打印从1到最大的n位数
剑指 Offer 17. 打印从1到最大的n位数题目123456789101112输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。示例 1:输入: n = 1输出: [1,2,3,4,5,6,7,8,9] 说明:用返回一个整数列表来代替打印n 为正整数
原题目:
思路普通的暴力解法就能够得到答案,但是这个题目原本要就是大数情况下的打印,这个n可以使无限大的。
所以这个时候不能用int去保存打印的数字,而是需要用string保存。
但是使用string也需要注意一点:
使用int类型时,每轮可以通过+1生成下一个数字,而此方法无法直接应用到string类型。并且,String类型的数字的进位操作效率较低,例如:“9999”进位到“10000”,需要从个位到千位循环判断,进位4次,效率较低。
所以最后的结果是通过String+全排列完成,避开进位操作,通过递归生成数字的String列表。
递归生成全排列:
基于分治算法的思想,先固定高位,向低位递归,当各位已被固定时,添加数字的字符串。例如:当n=2时( ...
剑指 Offer 19. 正则表达式匹配
剑指 Offer 20. 表示数值的字符串题目1234567891011121314151617181920212223242526272829303132333435363738394041424344454647请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。数值(按顺序)可以分成以下几个部分: 1. 若干空格 2. 一个 小数 或者 整数 3. (可选)一个 'e' 或 'E' ,后面跟着一个 整数 4. 若干空格 小数(按顺序)可以分成以下几个部分: 1.(可选)一个符号字符('+' 或 '-') 2. 下述格式之一: 1. 至少一位数字,后面跟着一个点 '.' 2. 至少一位数字,后面跟着一个点 '.' ,后面再跟着至少一位数字 3. 一个点 '.' ,后面跟着至少一位数字 整数(按顺序)可以分成以下几个部分: 1. (可选)一个符号字符('+' 或 '-') 2. 至少一 ...
剑指 Offer 16. 数值的整数次方
剑指 Offer 16. 数值的整数次方题目1234567891011121314151617181920212223实现 pow(x, n) ,即计算 x 的 n 次幂函数(即,xn)。不得使用库函数,同时不需要考虑大数问题。示例 1:输入:x = 2.00000, n = 10输出:1024.00000示例 2:输入:x = 2.10000, n = 3输出:9.26100示例 3:输入:x = 2.00000, n = -2输出:0.25000解释:2-2 = 1/22 = 1/4 = 0.25 提示:-100.0 < x < 100.0-231 <= n <= 231-1-104 <= xn <= 104
思路累乘的思路,典型的快速幂思路。如果逐个累乘,需要for循环n次,但是如果用快速幂(二分),则可以在n^(1/2)^内完成。
例如:
如果求2^10^,在正常思路下,我们需要2*2*2*2*2*2*2*2*2*2,这样乘10次,但是如果我们使用二次幂的思想:我们可以用10^(1/2)^=4次循环完成
12345第一次:a = 2 * ...
剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
剑指 Offer 21. 调整数组顺序使奇数位于偶数前面题目1234567891011输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。示例:输入:nums = [1,2,3,4]输出:[1,3,2,4] 注:[3,1,2,4] 也是正确的答案之一。 提示:0 <= nums.length <= 500000 <= nums[i] <= 10000
思路典型的双指针,在快排中的选择基准值(比x小的放左边,比x大的放右边)排序就是用的这种思想
实现123456789101112131415161718192021222324252627private static class Solution { public int[] exchange(int[] nums) { if (nums == null || nums.length == 1) { return nums; } // 奇数 ...
剑指 Offer 07. 重建二叉树
剑指 Offer 07. 重建二叉树题目12345678910111213141516输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]Output: [3,9,20,null,null,15,7]示例 2:Input: preorder = [-1], inorder = [-1]Output: [-1] 限制:0 <= 节点个数 <= 5000
思路先按照题目自己构建一个二叉树,不考虑代码实现前序遍历:preorder = [3,9,20,15,7]
中序遍历:inorder = [9,3,15,20,7]
前序遍历一定能够确定3是根节点
这样在中序遍历中,3左边的值一定是这个根节点的左子树,3右边的值一定是根的右子树
3左边只有一个数9,说明这个数的左子树只有一个是9
3的右子树有三个值,(15,20,7),然后在看前序遍历,前序遍历中的(20,15,7)一定是根的右子树, ...
剑指 Offer 06. 从尾到头打印链表
剑指 Offer 06. 从尾到头打印链表1234567891011121314输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。 示例 1:输入:head = [1,3,2]输出:[2,3,1] 限制:0 <= 链表长度 <= 10000
原理:
链表只有一个头结点,想要到尾结点只能从头开始遍历
辅助空间声明一个辅助空间,先遍历一遍确定辅助空间的大小,然后对辅助空间倒序打印
1234567891011121314151617181920212223242526/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */class Solution { public int[] reversePrint(ListNode head) { ListNo ...
剑指 Offer 10- II. 青蛙跳台阶问题
剑指 Offer 10- II. 青蛙跳台阶问题题目12345678910111213141516171819一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。示例 1:输入:n = 2输出:2示例 2:输入:n = 7输出:21示例 3:输入:n = 0输出:1提示:0 <= n <= 100
思路寻找之间的关系:
n=1 输出:1
1{1}
n=2 输出:2
12最后一次跳了一阶台阶{1,1}最后一次跳了两阶台阶{2}
n=3 输出:3
12最后一次跳了一阶台阶{1,1,1},{2,1}最后一次跳了两阶台阶{1,2}
n=4 输出:5
12最后一次跳了一阶台阶{1,1,1,1},{2,1,1},{1,2,1}最后一次跳了两阶台阶& ...