算法刷题
文章平均质量分 65
yindarui
这个作者很懒,什么都没留下…
展开
-
动态规划:子数组的最大和
简介本文主要介绍了一个系列的问题:子数组的最大和环形子数组的最大和。问题来自LeetCode。LC:53 子数组和问题给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。这个思路较为简单,考虑计算每个位置的前缀和:preSum,在遍历到下一个位置时,比较preSum+curNum是否比curSum大,如果大则 preSum+=n,否则preSum=n。每次比较完之后,需要记录下最大值。这样做其实是一种贪心的策略,如果curNum加上该位置之前的前原创 2021-08-27 20:31:36 · 258 阅读 · 0 评论 -
算法刷题系列——DFS:矩阵中的路径
问题描述链接:https://leetcode-cn.com/problems/ju-zhen-zhong-de-lu-jing-lcof给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。例如,在下面的 3×4 的矩阵中包含单词 “ABCCED”(单词中的字母原创 2021-08-04 20:25:54 · 300 阅读 · 0 评论 -
算法刷题系列——动态规划:120. 三角形最小路径和
问题描述思路思路就是动态规划,如果采用递归会超时,其最主要的是写出状态转移方程。主要就是dp求解的过程中的边界值的细节要做好。fun(depth,i)={min(fun(depth−1,i),fun(depth,i−1))+triangle[depth][i]depth>1,0<=i<triangle[depth−1].lengthfun(depth−1,i)+triangle[depth][i]depth>1,i−1<0fun(depth−1,i−1)+triang原创 2021-08-03 01:12:07 · 106 阅读 · 0 评论 -
算法刷题系列——回溯:784. 字母大小写全排列
问题描述字母大小写全排列思路分析首先这个题目要求的是全排列。那么就是无可避免地使用回溯法。这里建议对回溯的思想和经典的模板要熟悉。那么这道题我其实并没有用求排列的方式,而是使用的组合。二者的区别是:1. 排列需要用used数组来标记该遍历的位置是否加入到结果集了;2. 组合则不需要,因为下次递归的起始下标从当前遍历的位置的下一个位置开始。二者的联系是:排列是从一个数组(n个元素)中选择1、2、3…n个数字的组合。这道题为什么我没有采用排列的思路呢?因为我们无法确定递归终止的条件,因为原创 2021-08-02 22:40:05 · 190 阅读 · 0 评论 -
菜鸟刷题之路——Q31:完全二叉树的节点个数
问题 :222. 完全二叉树的节点个数给出一个完全二叉树,求出该树的节点个数。说明:完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。分析分析:利用完全二叉树的特点进行加速,一种是剪枝的方式,一种的二分的方式。二分的方式代码优美而且好理解,这里我是直接copy了LeetCode评论区的大佬的解法。Code// 二分class Solution {原创 2020-11-24 11:01:44 · 134 阅读 · 0 评论 -
菜鸟刷题之路——Q30:对链表进行插入排序
对链表进行插入排序问题:对链表进行插入排序。分析既然问题这样描述,就要考察我们对链表的熟悉程度。其过程必须按照插入排序的方式,否则没有啥意义。思路:按照插入排序的思路,利用指针找到当前元素该插入的位置 利用head和rear两个指针维护已经排好序的链表。Codejava代码,有详细注释。class Solution { /* 执行结果: 通过 显示详情 执行用时:23 ms, 在所有 Java 提交中击败了34.47% 的用户 内存消耗:37.7 MB, 在所有原创 2020-11-20 11:16:42 · 82 阅读 · 0 评论 -
菜鸟刷题之路——Q29:加油站问题(贪心算法)
问题:134. 加油站在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。说明:如果题目有解,该答案即为唯一答案。输入数组均为非空数组,且长度相同。输入数组中的元素均为非负数。分析 这是贪心算法里相当典型的案例。题目要求的是开一周,即每个点都要经过原创 2020-11-18 13:15:43 · 890 阅读 · 0 评论 -
菜鸟刷题之路——Q28:最大树
问题描述 给定一个不含重复元素的整数数组。一个以此数组构建的最大二叉树定义如下:二叉树的根是数组中的最大元素。左子树是通过数组中最大值左边部分构造出的最大二叉树。右子树是通过数组中最大值右边部分构造出的最大二叉树。 通过给定的数组构建最大二叉树,并且输出这个树的根节点。问题分析 分析:根据题目的定义,一个最大二叉树的子树也是最大二叉树,所以最大二叉树是按照递归的方式来生成的,这也是树最常见的定义方式。 我们首先看第一次递归的过程,不难发现,我们只要得到6的下标(最大值),将其作为原创 2020-11-16 11:13:16 · 108 阅读 · 0 评论 -
菜鸟刷题之路——Q27:移除K个数字
问题描述给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。注意:num 的长度小于 10002 且 ≥ k;num 不会包含任何前导零。分析分析:本题使用贪心加单调栈的方式,删除K个数即保证在删除到K个数之前,我删除的数都是较大的数。贪心策略就是使用单调栈。具体的流程代码的注释有解释。Codeclass Solution { public String removeKdigits(String num, int k) { /原创 2020-11-15 15:35:09 · 129 阅读 · 0 评论 -
菜鸟刷题之路——Q26:有多少小于当前数字的数字
问题:1365. 有多少小于当前数字的数字给你一个数组 nums,对于其中每个元素 nums[i],请你统计数组中比它小的所有数字的数目。换而言之,对于每个 nums[i] 你必须计算出有效的 j 的数量,其中 j 满足 j != i 且 nums[j] < nums[i] 。以数组形式返回答案。分析分析:首先这个题规定数字不会超过100,那么我们开辟一个数组,长度为101,整个理解为一个桶,数组的i位置对应了数字i在nums中出现的个数。所以,数组初始值都为零。遍历一遍nums来记录每原创 2020-10-26 15:21:28 · 122 阅读 · 0 评论 -
菜鸟刷题之路——Q25:颜色填充
问题:面试题 08.10. 颜色填充 问题来自leetCode。分析 首先,需要将该问题转化成一个图的问题。其实还是比较容易想到的。 问题是让我们找到和目标点相连的所有区域,很容易想到图论中的连通图。将整个image看做是一张图,即问题转化成对当前的图寻找包含给定节点的最大连通子图问题. 典型的DFS问题。Codeclass Solution { public int myColor = 0; public int newColorr = 0; public bo原创 2020-10-24 17:24:26 · 161 阅读 · 0 评论 -
菜鸟刷题之路——Q24:递归反转栈
问题只用递归实现一个栈的翻转,假设栈存储的内容是整数类型。问题来自面试,主要是考量思想。分析分析:递归本身是调用系统栈,我们以1->2->3->4->5这个序列为例子,实现翻转需要两个过程:弹出当前栈底元素,保存下来,并保持其他元素的位置不动。此时栈的大小是在不断变小的;不断取出栈底元素直到栈空,此时我们取出的顺序是:1,2,3,4,5。我们只需要再递归地把它们压入栈就实现了栈的翻转。Code// 弹出栈底元素,并保持其他元素位置不动 public in原创 2020-10-24 17:15:35 · 423 阅读 · 0 评论 -
菜鸟刷题之路——Q23:划分字母区间
问题:763. 划分字母区间分析分析:为了切分最多的字符串,我们希望每个字符串尽可能的短,这一步即为贪心的思想。但是我们如何保证我们切分的字符串是符合题目意思的呢?拿S为例子:变量说明:stratIndex:当前子串的开始下标,rearIndex当前子串的结尾下标。首先:a字符最后出现的下标为8,我们假设第一个字符的长度为a第一次出现到最后一次出现的长度,这个是可能的最小的长度,此时得到了子串s1,其startIndex为0,rearIndex为8;为了保证s1是满足条件的,我们遍历原创 2020-10-22 20:50:50 · 218 阅读 · 0 评论 -
菜鸟刷题之路——Q22:稀疏数组搜索
问题:面试题 10.05. 稀疏数组搜索分析: 分析:看到有序,必先二分。但是注意:如果我们二分的mid指向一个空的字符串那么我们需要向两边寻找到一个非空的字符串,把它作为mid,如果俩边都没有,那么直接返回-1.codeclass Solution { public int findString(String[] words, String s) { int left = 0, right = words.length - 1; while (left &原创 2020-10-22 20:12:58 · 87 阅读 · 0 评论 -
菜鸟刷题之路——Q21:黑白方格画
问题:LCP 22. 黑白方格画分析分析:LeetCode给的是简单题,但是我觉得把这个题从题面转化成组合数问题还是需要一定时间的——需要画图。首先需要明确:我们只能一次画一整行或者一整列。带着这个限制我们往下看。思想就是组合,为什么是组合可以看一下解答里面带图的分析,相信你一看就懂。注意几点:边界条件,k=1和k=0的情况其次就是返回的条件:当前选取的i行格子已经超过了总格子数k,那么直接返回之前累积的数;当前选取的i行格子刚好了总格子数k,那么返回之前累积的数+combinati原创 2020-10-19 15:32:16 · 348 阅读 · 0 评论 -
菜鸟刷题之路——Q20:删除字符串中的所有相邻重复项 II
问题描述题目来自leetCode:1209—删除字符串中的所有相邻重复项 II给你一个字符串 s,「k 倍重复项删除操作」将会从 s 中选择 k 个相邻且相等的字母,并删除它们,使被删去的字符串的左侧和右侧连在一起。你需要对 s 重复进行无限次这样的删除操作,直到无法继续为止。在执行完所有删除操作后,返回最终得到的字符串。本题答案保证唯一。# 解题思路:简单思路解题思路较多,多是利用栈操作,且思路较为直白,大体上是利用栈来记录每个元素出现的次数,当超过了阈值就开始删除字符,在此不再解释。如果原创 2020-08-31 18:29:59 · 306 阅读 · 0 评论 -
菜鸟刷题之路——Q19
问题描述又是一道滑动窗口的问题。给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{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,5],原创 2020-07-23 15:29:51 · 69 阅读 · 0 评论 -
菜鸟刷题之路——Q18
问题描述小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!解题思路解题思路有两种,我一开始想的是前缀和方式,看了别人的回答发现了更好的方法:滑动窗口。题目的一些特点:—— 1)是连续的序列,这个是关键,好好原创 2020-07-23 10:13:58 · 121 阅读 · 0 评论 -
菜鸟刷题之路——Q17
问题描述输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。解题思路思路采用的中序遍历,实现的是采用非递归。将左指针指向前节点,右节点指向后节点。Code public TreeNode Convert(TreeNode pRootOfTree) { Stack<TreeNode> st = new Stack(); if (pRootOfTree == null) return原创 2020-07-22 12:27:50 · 69 阅读 · 0 评论 -
菜鸟刷题之路——Q16
问题描述一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。解题思路问题用HashMap解决是很容易想到的。使用异或运算的特点也可以解决该问题。HashMap将数组的值作为key存入HashMap:——1)当该值存在于HashMap中,删除它——2)当该值不存在加入它最后整个HashMap中剩下的就是结果的两个值。遍历一次数组即可。由于只有两个重复的元素,所以HashMap的存储、查询效率都为O(1),这个比利用ArrayList下标来标记的效率高很原创 2020-07-20 10:53:44 · 99 阅读 · 0 评论 -
菜鸟刷题之路——Q15
问题描述问题来自牛客剑指offer每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。原创 2020-07-19 16:44:24 · 94 阅读 · 0 评论 -
菜鸟刷题之路——Q14
问题描述输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。解题思路问题的描述很鸡贼,这样描述让我一开始想的就是要记录每次的符合的两个值,但是其实,乘积最小的值一定是最外侧的两个数。这样一想的话就很简单了,从两侧开始,利用双指针:——1)如果array[right] + array[left]==sum那么我们就找到了——2)如果array[right] + array[left]小了,就把左指针向后移动——3)如果原创 2020-07-19 16:35:22 · 69 阅读 · 0 评论 -
菜鸟刷题之路——Q13
问题描述问题来自牛客剑指offer数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。问题和寻找发帖水王属于同一问题。解题思路Code...原创 2020-07-16 12:21:28 · 83 阅读 · 0 评论 -
菜鸟刷题之路——Q12
问题描述问题来自牛客剑指offer输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)解题思路两种方法,一种是利用栈进出的特点,遍历数组,一种是模拟栈的进出,在这里介绍模拟栈的方式。思路1) 首先开辟一个辅助栈,利用两个指针popCount ,pu原创 2020-07-14 13:33:51 · 98 阅读 · 0 评论 -
菜鸟刷题之路——Q11
问题描述给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。public class TreeLinkNode { int val; TreeLinkNode left = null; TreeLinkNode right = null; TreeLinkNode next = null; TreeLinkNode(int val) { this.val = val原创 2020-07-13 19:15:31 · 80 阅读 · 0 评论 -
菜鸟刷题之路——Q10
问题描述从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。解题思路首先是层次遍历,这个是基础如果是打印的话就很简单了,但是牛客这道题是让我们一层输出一行,问题就在于,我们如何知道一行结束了呢?对于完全二叉树来说,很简单就可以确定1)如果不是完全二叉树,我们是不是可以把它当做完全二叉树来看2) 当该层的节点有一个子节点为空,那么就说明下一层就会少一个节点3) 我们先假设下一层是满的,在遍历当前层时,每次出现一个空就把下层的节点上限减一4) 每次到了上限时,就说明这一层的节点遍原创 2020-07-13 16:52:28 · 81 阅读 · 0 评论 -
菜鸟刷题之路——Q9
问题描述问题来自牛客剑指offer给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。保证base和exponent不同时为0解题思路问题就是求解幂运算。考虑一下极端情况,指数为0,结果为1,指数为1,结果为base,底数为0,结果为1。指数为负数,结果返回 1/res。java提供的Math.pow可以完成。按照数学的解法,暴力递归也可以完成。快速幂运算:举例 base=5 ex=81)思路和二分法一样,对指数进行分解,比如原创 2020-07-09 10:25:45 · 113 阅读 · 0 评论 -
菜鸟刷题之路——Q8
问题描述问题来自牛客剑指offer给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1,m<=n),每段绳子的长度记为k[1],…,k[m]。请问k[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。输入描述输入一个数n,意义见题面。(2 <= n <= 60)输出描述输出答案。例如: 输入8 ,输出18。解题思路拿到问题首先是简单试了几个值,没有原创 2020-07-08 14:44:41 · 85 阅读 · 0 评论 -
菜鸟刷题之路——Q7
问题描述问题来自牛客剑指offer把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。解题思路简单说下我的理解吧。最简的思路就是排序或者直接遍历找出最小的值。思考一下会发现,这种翻转是可以对遍历过程进行剪枝的。最小值的特点为:前一个数一定大于等于自己,后一个数也一定大于等原创 2020-07-08 11:29:34 · 213 阅读 · 0 评论 -
菜鸟刷题之路——Q6
问题描述来自牛客剑指offer输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)思路首先链表相交的结构是这样的:(图片来自牛客官方):问题可以分为两种情况:等长:那就很简单了,从头到尾遍历,找到相同的就返回节点,找不到就返回null。不等长:这也是问题的比较值得思考的地方。如上图所示,不等长情况下如果直接从头遍历一次是一定找不到的。对于不等长的简单思路就是,2层循环遍历,复杂度为O(n*m),最好想的方法原创 2020-07-07 14:07:30 · 638 阅读 · 1 评论 -
菜鸟刷题之路——Q5
问题描述来自牛客剑指offer我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?比如n=3时,2*3的矩形块有3种覆盖方法:问题思路1. 首先拿到问题先尝试找出前几组的值,比如n=0,1,2,3,4,5,发现一些规律2. 不难发现,这规律是按照斐波那契数列增长的规律来的3. 思考为什么呢?4. 其实我们会发现当我们拿到一个新的问题规模时:有两种思路可以走:从问题规模的角度去考虑 1) 竖着放一个,那么此时问题的规模原创 2020-07-06 11:20:38 · 893 阅读 · 0 评论 -
菜鸟刷题之路——Q4
问题来自牛客剑指offer题目描述输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。问题思路利用排序:最直观的我觉得就是选择排序,因为选择排序是按照每次固定一个数的思路来的,我们将外层控制排列轮数的值改为K即可。利用堆结构(巧妙)利用堆(java中的PriorityQueue)先存储K个元素,形成一个大根堆。之后每次新来的数都和堆顶比较,如果大于堆顶:那么这个数一定不是前K个最小的数,如果小于堆顶,就把堆顶的数弹出,并把新的原创 2020-07-03 16:10:33 · 102 阅读 · 0 评论 -
菜鸟刷题之路——Q3
来自牛客剑指offer问题描述HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)问题思路我认为可以理解为01背包原创 2020-07-03 14:11:59 · 1462 阅读 · 0 评论 -
菜鸟刷题之路——Q1
题目要求:写一个函数,求两个整数之和,要求在函数体内不得使用+、-、*、/四则运算符号。思路:一开始考虑转化成位来计算,但是这样代码结构非常复杂且当出现负数时就难以计算。之后转化思维,从十进制数字计算的本身上来看:两个数(ab+cd)的计算过程可以看成是:a+c=e,b+d=f,如果e,f大于10,就保留ef 的个位数。如果出现进位就向前+1。举个例子:13+183. 1+1 =2 ,3+8=11保留14. 因为3——8有进位,所以向前加1 :2+1 =3,最后结果是31转化成二原创 2020-06-23 11:25:44 · 135 阅读 · 0 评论