数据结构与算法
努力不停努力
我要成为自己眼中最耀眼的一束光
展开
-
LeetCode322.零钱兑换(记忆化搜索,动态规划)
LeetCode322.零钱兑换解法记忆化搜索动态规划记忆化搜索/*返回可以凑成总金额的最少的硬币个数*/func coinChange(coins []int, amount int) int { var f = make([]int, amount) /* 记忆化搜索,自顶向下, f[i]表示兑换i+1元需要的最少硬币数 */ var searchChange func(coins []int, amount int) int searchChange = func(coin原创 2021-10-11 11:17:52 · 318 阅读 · 0 评论 -
LeetCode312. 戳气球 (分治,记忆化搜索,动态规划)
LeetCode312. 戳气球 解题思路记忆化搜索动态规划解题思路官方题解参考题解核心思想:由于戳气球的操作会导致两个气球从不相邻变成相邻,使得后续操作难以处理。于是我们倒过来看这些操作,将全过程看成每次添加一个气球。solve(i, j)表示 开区间(i, j) 所能获得的最大硬币数。当开区间只包含一个气球mid时,solve(i, j) = val[i] * val[mid] * val[j]记忆化搜索自顶向下分治+递归+记忆/*解法一: 记忆化搜索 由于戳气球的操作原创 2021-10-10 16:34:51 · 296 阅读 · 0 评论 -
LeetCode309. 最佳买卖股票时机含冷冻期(动态规划)
LeetCode309. 最佳买卖股票时机含冷冻期 /*计算最大利润,不能同时参与多笔交易,卖出后无法在第二天买入(冷冻期为1天)动态规划 每一天会有三种不同的状态: 1. 目前持有一支股票,对应的[累计最大收益]为dp[i][0] 2. 目前不持有任何股票,且处于冷冻期中,对应的[累计最大收益]为dp[i][1] 3. 目前不持有任何股票,且不处于冷冻期中,对应的[累计最大收益]为dp[i][2] 注意:这里处于冷冻期是指第二天即i+1不处于冷冻期 状态转移: 1. 目原创 2021-10-10 13:36:22 · 207 阅读 · 0 评论 -
KMP算法
KMP模式匹配算法推导代码例题推导KMP是一种字符串模式匹配的改进算法。假定模式串为B,主串为A,当B[j]和A[i]不匹配时,i不会回退,j并不会从位置0开始重新匹配,而是回退到合适的位置。那么,KMP算法首先应该解决的就是如何找到合适的回退位置。代码显然时间复杂度为O(n + m), 空间复杂度为O(m),n是文本串的长度,m是模板串的长度 /** * kmp算法 * * 计算模板串S在文本串T中出现了多少次 * @param S stri原创 2021-06-12 16:13:02 · 107 阅读 · 0 评论 -
旋转数组的最小数字 (二分法)
旋转数组的最小数字NC71直接上代码和注释 /** * 二分法 * 如果二分之后能够明确目标值在二分的哪一侧, * 即可使用二分法 * * 二分得到一个mid,arr[mid]要和一个compVal比较以判断 * 目标值的位置, * 若 compVal为arr[right], * 1. arr[mid] > compVal, 最小值一定是在mid的右侧,原创 2021-06-08 11:06:36 · 133 阅读 · 0 评论 -
牛客NC125 未排序数组中累加和为给定值的最长子数组长度(动态规划、哈希法)
牛客NC125直接上代码和注释目录动态规划哈希法类似的题目动态规划时间复杂度O(n ^ 2),空间复杂度O(1) /** * 动态规划 * 状态dp[i][j],子数组[i-j]的和 * * 可以进行空间压缩 * max length of the subarray sum = k * @param arr int整型一维数组 the array * @param k int整型 target *原创 2021-06-07 17:08:52 · 260 阅读 · 0 评论 -
矩阵最长递增路径 (记忆化的递归搜索,动态规划)
牛客NC138 矩阵最长递增路径leetcode329 矩阵中的最长递增路径记忆化的深度优先遍历每个点的最长递增路径是确定,因此我们可以记录每个点的最长递增路径的长度,下一次访问到该点时就直接返回路径长度即可。会不会出现路径重复的情况(如下图的情况)呢?很明显是不会的,因为路径是递增的,这种情况会破坏路径的递增关系。 private int[][] dirs = new int[][]{{1, 0}, {0, -1}, {-1, 0}, {0, 1}}; private in原创 2021-06-02 13:40:47 · 242 阅读 · 0 评论 -
股票交易的最大收益(二)(两次交易,动态规划)
牛客NC135股票交易的最大收益(二)import java.util.*;public class Solution { /** * 动态规划, * dp[i][0],直到第i天第一次买入的最大收益 * dp[i][1],直到第i天第一次卖出的最大收益 * dp[i][2],直到第i天第二次买入的最大收益 * dp[i][3],直到第i天第二次卖出的最大收益 * 买入就减收益,卖出原创 2021-06-02 11:11:41 · 925 阅读 · 0 评论 -
牛客NC126 换钱的最小货币数(动态规划)
原题链接 动态规划递归 时间复杂度过高动态规划时间复杂度为O(n * aim), 空间复杂度为O(aim),n是arr数组的长度 /** * 最少货币数 * 动态规划: * 状态: dp[i],凑成i元需要的货币数 * * @param arr int整型一维数组 the array * @param aim int整型 the target * @return int整型 */原创 2021-05-18 12:40:55 · 242 阅读 · 0 评论 -
经典算法题:约瑟夫环
约瑟夫环问题问题定义解法1. 模拟链表2. 数学方法(时间复杂度较低)例题问题定义0,1,···,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字(删除后从下一个数字开始计数)。求出这个圆圈里剩下的最后一个数字。例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。解法1. 模拟链表该方法时间复杂度为O(n * m)/** * @author 49367 * @date 20原创 2021-05-14 15:27:52 · 375 阅读 · 0 评论 -
树的直径(最长路径)
无向连通树无向连通树即其直径定义如何求直径深度优先遍历证明:树形DP例题无向连通树即其直径定义有一无向连通树,该树的直径就是树上最远两点的距离。无向连通树: 从一个顶点出发能够到达任意一个顶点,且有n个顶点,n-1条边,没有环。如何求直径深度优先遍历深度优先遍历。先从任意一个顶点 u 出发寻找以其为起点的最长路径,再从终点出发寻找以该终点 s 为起点的最长路径。以该终点为起点的最长路径即为树的直径。证明:如果u是树直径(最长路径) s -> t上的一点,那么以u为起点寻找最长路径,终原创 2021-05-12 20:56:51 · 672 阅读 · 1 评论 -
LFU缓存
LFULFU算法实现堆 + 版本号双哈希表+LinkedList双哈希表+自定义双向链表 (时间复杂度最低)LFU算法最近最少次数访问,缓存满的时候,优先淘汰掉最少访问的数据,若最少访问次数的数据有多个,淘汰掉访问时间与现在相隔最远的数据。实现堆 + 版本号由于涉及到构建堆,所有操作的时间复杂度均为O(logN)public class LFU{ class Node{ int key; int val; int count;原创 2021-04-30 17:41:03 · 411 阅读 · 1 评论 -
牛客NC6 二叉树的最大路径和(二叉树的遍历,递归,动态规划)
原题链接/** * @author 49367 * @date 2021/4/28 10:54 */public class MaxPathSumNC6 { private int maxSum = Integer.MIN_VALUE; /** * 获取树的最大路径,开始结点和结束结点都可以是任意结点 * @param root TreeNode类 * @return int整型 */ public int maxPathSum (原创 2021-04-28 13:45:24 · 209 阅读 · 0 评论 -
牛客NC30 数组中未出现的最小正整数
原题链接解题思路:使用堆排序,构造小顶堆。时间复杂度O(nlogn),空间复杂度O(1)使用HashMap,时间复杂度O(n),空间复杂度O(n)原地哈希,时间复杂度O(n), 空间复杂度O(1)具体实现: /** * 原地哈希算法 (哈希算法的改良版) * 给定一个数组arr,数组长度为len,未出现的最小正整数一定不会超过len + 1, * 即 [1, len] 这个区间的数都出现了,那么未出现的最小正整数就是len + 1,原创 2021-04-25 12:25:02 · 278 阅读 · 0 评论 -
牛客 NC60 判断该二叉树是否为搜索二叉树和完全二叉树 (二叉树,层序遍历,中序遍历)
原题链接判断搜索二叉树可以用中序遍历或者递归判断搜索二叉树的方法用递归 /** * * @param root TreeNode类 the root * @return bool布尔型一维数组 */ public boolean[] judgeIt (TreeNode root) { // write code here boolean[] res = new boolean[]{false, false};原创 2021-04-19 18:33:56 · 125 阅读 · 0 评论 -
牛客NC92 输出两个字符串的最长公共子序列(动态规划)
原题链接public class Solution{ /** * 动态规划 * 状态:dp[i][j] 表示s1前i个字符和s2前j个字符的最长公共子序列的长度 * * 状态转移方程: * 若s1[i] = s2[j], dp[i + 1][j + 1] = dp[i][j] + 1 * 为什么不考虑dp[i + 1][j]或dp[i][j + 1]? *原创 2021-04-18 14:20:26 · 548 阅读 · 0 评论 -
牛客NC35 最小编辑代价 (动态规划,压缩空间的动态规划)
原题链接理解动态规划后,压缩空间是一大难点,需要找出遍历过程中需要用到的状态和不需要用到的状态,去掉不需要用到的状态,存储需要用到的状态。import java.util.*;public class Solution { /** * 动态规划 * 状态:dp[i + 1][j + 1],str1[0-i]编辑成str2[0-j]的最小cost * * min edit cost * @param str1 string字符串 t原创 2021-04-14 23:01:30 · 238 阅读 · 0 评论 -
实现简单计算器 (逆波兰表达式)
牛客NC137 表达式求值(原题链接)逆波兰表达式相关博客将一个大问题分解成一个个小问题来求解,就不会被难题的复杂度给吓倒。代码实现:核心函数: /** * 写一个整数计算器,支持加减乘三种运算和括号 * 返回表达式的值 * @param s string字符串 待计算的表达式 * @return int整型 */ public int solve (String s) { // write code here原创 2021-04-13 13:08:24 · 122 阅读 · 0 评论 -
牛客NC59 矩阵的最小路径和 (动态规划,压缩空间的动态规划)
原题链接解题方法暴力递归(时间复杂度过高)动态规划压缩空间的动态规划(可以降低空间复杂度)暴力递归(时间复杂度过高)每个位置都尝试向右走和向左走,时间复杂度较高,为 O(2 ^ (n * m))public class Solution{ private int minPathSum; /** * @param matrix int整型二维数组 the matrix * @return int整型 */ public int minPathSu原创 2021-04-12 22:20:35 · 130 阅读 · 0 评论 -
牛客NC73 数组中出现次数超过一半的数字 (候选法、摩尔投票算法)
牛客网原题链接leetcode剑指Offer39如何理解摩尔投票算法核心思路:对拼消耗玩一个诸侯争霸的游戏,假设你方人口超过总人口一半以上,并且能保证每个人口出去干仗都能一对一同归于尽。最后还有人活下来的国家就是胜利。那就大混战呗,最差所有人都联合起来对付你,或者其他国家也会相互攻击),但是只要你们不要内斗,最后肯定你赢。最后能剩下的必定是自己人。 /** * 找出数组中出现次数超过数组长度len的一半的数,若没有则返回0 * 最佳解法: * 候选法原创 2021-04-12 20:30:22 · 177 阅读 · 0 评论 -
牛客NC62 判断是不是平衡二叉树 (二叉平衡树)
原题链接这虽然是一道简单题,但是要找到最佳的解法还是比较困难的解题方法最直接的思路使用Map结构存储高度信息后序遍历自底向上同时返回高度信息我的解法 (自定义高度类存储高度信息)他人的解法(不需要自定义类)最直接的思路这道题,最直接的思路就是从上到下,判断每一个结点的左子树和右子树的高度差是否小于或等于1,所有结点都满足平衡二叉树的条件才能返回true。也可以根据后序遍历,从下往上判断。但是,这个解法有个问题,就是我们在求位于上方的结点的最大高度的时候,其实已经把下方的结点的最大高度也给求出来了,原创 2021-04-12 17:15:52 · 249 阅读 · 0 评论 -
全排列算法
全排列的几种算法相关题目字典序算法回溯法(深度遍历 + 剪枝)结果不要求排序结果要求排序相关题目牛客NC121字符串的排列leetcode剑指 Offer 38. 字符串的排列字典序算法public class Solution{ char[] charArray; ArrayList<String> res; /** * 使用字典序算法 * @param str * @return */ public原创 2021-04-10 16:37:44 · 66 阅读 · 0 评论 -
剑指 Offer 59 - II. 队列的最大值 设计一个能够获得最大值的队列(队列)
原题链接相关题目,相关数据结构及其设计:设计一个能够获得最小值的栈能够获取最大值的队列class MaxQueue { private Deque<Integer> dataQueue; private Deque<Integer> maxQueue; public MaxQueue() { dataQueue = new LinkedList<>(); maxQueue = new LinkedList&l原创 2021-04-08 23:19:45 · 98 阅读 · 0 评论 -
牛客NC90 设计一个能够返回最小值的栈(栈)
原题链接/** * @author 49367 * @date 2021/4/8 20:58 */public class GetMinStackNC90 { /* 利用栈先进后出的特性。 */ private Deque<Integer> dataStack = new LinkedList<>(); private Deque<Integer> minStack = new LinkedList<>();原创 2021-04-08 23:04:34 · 79 阅读 · 0 评论 -
牛客NC32 求平方根(二分法,牛顿迭代法)
原题链接 二分法牛顿迭代法 [参考链接1](https://blog.csdn.net/u010947534/article/details/87874019) [参考链接2](https://blog.csdn.net/weixin_42109012/article/details/91359268)二分法任何有边界的有序数字的集合的查找操作都可以使用二分法。这道题一开始我们很容易想到从num = 1开始求,num 加 1 直到 x / num = num为止。由于我们是按升序取数字的,且当 x &原创 2021-04-08 20:56:42 · 235 阅读 · 0 评论 -
牛客NC48 在转动过的有序数组中寻找目标值(二分查找)
原题链接不知道未经过转动的原数组是升序排列还是降序排列的情况下,我们可以先按升序二分查找,再按降序二分查找。 /** * 二分查找 * 当前数组肯定是有两部分是有序的,所以取mid时, * 要么 [l, mid] 是有序的,要么 [mid + 1, r]是有序的 * * @param A int整型一维数组 * @param target int整型 * @return int整型 */ p原创 2021-04-07 17:22:15 · 119 阅读 · 0 评论 -
最小生成树
最小生成树定义MST性质普利姆算法定义n个结点通过(n - 1) 条边即可相连,每条边都有各自的权重(代价),最小生成树就是从大于或等于n - 1条边中找出能连接n个结点的代价和最小的(n - 1)条边。MST性质假设 N = (V, {E}) 是连通网,其中V是所有顶点的集合,E是所有边的集合。#求最小生成树普利姆算法...原创 2021-04-06 23:09:59 · 308 阅读 · 0 评论 -
牛客NC91 最长递增子序列(动态规划、贪心+二分查找)
原题链接 动态规划(时间复杂度 O(n^2))贪心 + 二分查找 (时间复杂度 O(nlogn))动态规划(时间复杂度 O(n^2)) /** * return the longest increasing subsequence * @param arr int整型一维数组 the array * @return int整型一维数组 */ /** * 动态规划 * 状态 dp[i][2], dp[i][0]是以 a原创 2021-04-06 20:40:28 · 618 阅读 · 0 评论 -
牛客NC17 最长回文子串(动态规划)
原题链接 中心扩散法动态规划中心扩散法 /** * 中心扩散法 * * @param A * @param n * @return */ public int getLongestPalindrome(String A, int n) { // write code here char[] chars = A.toCharArray(); if (chars.length ==原创 2021-04-05 15:42:27 · 239 阅读 · 0 评论 -
LeetCode1143. 最长公共子序列 (动态规划)
原题链接 /** * 动态规划 * 状态 dp[i][j] 表示 text1前i个字符 和 text2前j个字符 的最长公共子序列的长度 * * 状态转移方程 * if text1[i] == text2[j], dp[i + 1][j + 1] = dp[i][j] + 1; * if text1[i] != text2[j], dp[i + 1][j + 1] = Math.max原创 2021-03-30 22:32:12 · 72 阅读 · 0 评论 -
根据二叉树遍历结果构建二叉树
目录[LeetCode105. 从前序与中序遍历序列构造二叉树](https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/)[LeetCode106. 从中序与后序遍历序列构造二叉树](https://leetcode-cn.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/)[LeetCo原创 2021-03-30 20:26:17 · 280 阅读 · 0 评论 -
二叉树遍历
前序遍历中序遍历后序遍历class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null;}前序遍历 /** * 前序遍历 * @param temp */ private List<Integer> dlr(TreeNode root) { LinkedList<Integer> res = new Linked.原创 2021-03-29 17:36:31 · 51 阅读 · 0 评论 -
判断链表中是否有环 返回环的入口结点 (快慢指针)
set集合法 (时间复杂度O(n), 空间复杂度O(n))快慢指针法(时间复杂度O(n),空间复杂度O(1))逐个删除法 (时间复杂度O(n),空间复杂度O(1)) class ListNode { int val; ListNode next; ListNode(int x) { val = x; next = null; } }set集合法 (时间复杂度O(n), 空间复杂度O(.原创 2021-03-29 16:42:33 · 209 阅读 · 0 评论 -
java LRU缓存实现
LRU缓存实现LinkedHashMap源码剖析继承LinkedHashMapLinkedHashMap源码剖析继承LinkedHashMap可以通过继承 LinkedHashMap 实现 LRU 缓存结构。代码如下:public class LRUCache<K, V> extends LinkedHashMap<K, V> { private final int MAX_ENTRIES; public LRUCache (int maxEntries)原创 2021-03-29 15:03:13 · 110 阅读 · 1 评论 -
数独问题
假设输入为 0 的位置是要求填数的位置,每次填数的时候都通过深度遍历判断填的数能不能解决数独问题,不能就再填另一个可以填的数,再进行判断。import java.util.Scanner;/** * @author 49367 * @date 2021/3/26 11:07 */public class Sudoku { private static final int SIZE = 9; // 数独矩阵 private static char[][] map = n原创 2021-03-27 14:07:28 · 58 阅读 · 0 评论 -
LeetCode 剑指 Offer 66. 构建乘积数组 (动态规划,表格分区)
原题链接class Solution { /** * 动态规划 * left[i] 为 a[i] 左边元素的乘积 (不包含 a[i]) * right[i] 为 a[i] 右边元素的乘积 (不包含 a[i]) * 则结果 res[i] = left[i] * right[i] * * @param a * @return */ public int[] construc原创 2021-03-25 17:23:24 · 82 阅读 · 0 评论 -
LeetCode剑指 Offer 60. n个骰子的点数 (动态规划)
原题链接class Solution { /** * 动态规划 * dp[] 记录点数和的概率 * 已知 n = 1 时,f(1, dp[]) = {1/6, 1/6, 1/6, 1/6, 1/6, 1/6} * 新增骰子的点数只能是 1 - 6,原先 n - 1 个骰子的点数和分别加上新增骰子的点数,即为 n 个骰子的点数和 * dp[i] 即为 n 个骰子投出的最小点数和的概率 * 已原创 2021-03-25 14:58:03 · 78 阅读 · 0 评论 -
LeetCode 剑指 Offer 56 - I. 数组中数字出现的次数 (异或,位运算)
原题链接class Solution { /** * 时间复杂度 O(n), 空间复杂度 O(1) * 方法:异或 * 2 ^ 3 ^ 2 ^ 1 ^ 4 ^ 3 = 2 ^ 2 ^ 3 ^ 3 ^ 1 ^ 4 = 1 ^ 4 * 异或得到结果,值为 1 的位是两个只出现一次的数不相同的位, * 例: 3 ^ 5 = 011 ^ 101 = 110 * 作用:通过获取一个不相同的原创 2021-03-24 19:05:51 · 96 阅读 · 0 评论 -
LeetCode剑指 Offer 51. 数组中的逆序对 (归并排序)
原题链接(官方题解视频讲的很好)核心思想:在归并排序的过程中计算逆序对的数目 /** * 归并排序 * @param nums * @return */ public int reversePairs(int[] nums) { int len = nums.length; if(len < 2) return 0; int[] copy = new int[len]; //原创 2021-03-23 14:15:05 · 109 阅读 · 0 评论 -
LeetCode 剑指 Offer 48. 最长不含重复字符的子字符串 (动态规划,双指针)
原题链接 动态规划双指针动态规划class Solution { /** * 动态规划 * dp[j] 表示以第 j 个字符为结尾的最长不重复字符串的长度 * * 设 s[j] 的前一个相同字符 为 s[i],用 hashMap 存储对应 * 的字符和它最后一次出现的位置 * * 状态转移方程: * 如果 i < j - 1 - dp[j - 1] +原创 2021-03-22 13:17:35 · 138 阅读 · 0 评论