![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
数据结构与算法
zy763
这个作者很懒,什么都没留下…
展开
-
子数组异或和为0的最多划分
题目描述给定一个整型数组arr,其中可能有正有负有零。你可以随意把整个数组切成若干个不相容的子数组,求异或和为0的子数组最多可能有多少个?整数异或和定义:把数组中所有的数异或起来得到的值。思路参考自《程序员代码面试指南》。1.动态规划。dp[i]表示arr[0…i]对应的自数组异或和为0的最多子数组个数。考虑arr[i]所在的子数组异或和是否为0,可以分为两种情况:(1)arr[i]所在的子数组异或和不为0,此时dp[i] = dp[i-1]。(2)arr[i]所载的子数组异或和为0,此时dp[i]原创 2021-01-31 14:10:10 · 473 阅读 · 2 评论 -
子矩阵的最大累加和问题
题目描述给定一个矩阵matrix,其中的值有正、有负、有0,返回子矩阵的最大累加和例如,矩阵matrix为:-90 48 7864 -40 64-81 - 7 66其中,最大的累加和的子矩阵为:48 78-40 64-7 66所以返回累加和209。例如,matrix为:-1 -1 -1-1 2 2-1 -1 -1其中,最大累加和的子矩阵为:2 2所以返回4思路第一层循环:枚举开始的行数i,范围从0到n-1。第二层循环:枚举结束的行数j,范围从i到n-1。第三层循环:原创 2021-01-31 13:55:53 · 201 阅读 · 0 评论 -
打气球的最大分数
题目描述给定一个数组arr,长度为n。代表排有分数的气球。 每打爆一个气球都能获得分数,假设打爆气球的分数为X,获得分数的规则如下:1)如果被打爆气球的左边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为L:如果被打爆气球的右边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为R.获得分数为L*X*R2)如果被打爆的气球的左边有没被打爆的气球,找到离被打爆气球最近的气球,假设分数为L:如果被打爆气球的右边所有气球都已经被打爆,获得分数为L*X。3)如果被打爆气球的左边所有的气球都已经被原创 2021-01-29 14:55:19 · 166 阅读 · 0 评论 -
分金条的最小花费
题目描述给定一个正数数组arr,arr的累加和代表金条的总长度,arr的每个数代表金条要分成的长度。规定长度为k的金条分成两块,费用为k个铜板。返回把金条分出arr中的每个数字需要的最小代价。思路贪心算法。将arr中的值都放在最小堆中,每次弹出堆顶的两个元素,将这两个元素之和计入到结果,并将两个元素之和放入最小堆。直到最小堆中只有一个元素。此时返回累加的结果。代码实现import java.util.Scanner;import java.util.PriorityQueue;public原创 2021-01-29 14:39:11 · 260 阅读 · 0 评论 -
换钱的方法数
题目描述给定数组arr,设数组长度为n,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim,代表要找的钱数,求换钱的方法数有多少种。由于方法的种数比较大,所以要求输出对进行取模后的答案。思路动态规划:设置dp数组,dp[i][j]表示用arr[0…i]这些货币组成金额j的方法数。根据arr[i]是否使用,可以分为两种情况:arr[i]不使用。此时产生的方法数为dp[i-1][j],即使用arr[0…i-1]组成金额j的方法数。arr[原创 2021-01-29 14:35:14 · 140 阅读 · 0 评论 -
换钱的最少货币数
题目描述给定数组arr,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个aim,代表要找的钱数,求组成aim的最少货币数。思路动态规划。使用dp数组,dp[i][j] 表示使用arr[0…i]的货币凑出j的面值需要的最少货币数。根据最后的arr[i]是否使用进行讨论:面值为arr[i]的货币不使用,此时dp[i][j] = dp[i-1][j]。面值为arr[i]的货币使用,此时dp[i][j] = dp[i][j-arr[i]]+1,d原创 2021-01-28 14:49:05 · 200 阅读 · 0 评论 -
数值的整数次方
题目描述给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。保证base和exponent不同时为0。思路时间复杂度为O(logN)。本质上是把指数转化为其二进制表示进行求解。再使用一个指针cur记录当前位上的数。从右向左分析指数二进制上的数字,是1代表cur的值应该累乘到结果,是0表示当前值不应该累乘到结果。因为指数的二进制形式最多有O(logN)位,所以时间复杂度为O(logN)。代码public class Solution {原创 2021-01-27 22:25:22 · 56 阅读 · 0 评论 -
二叉树的镜像
题目描述操作给定的二叉树,将其变换为源二叉树的镜像。思路递归。对于一个节点,交换其左子树和右子树的指针。然后对左子树和右子树递归执行此操作。递归出口是节点为空。代码/**public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; }}*/原创 2021-01-27 22:18:19 · 63 阅读 · 0 评论 -
二叉搜索树与双向链表
题目描述输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。思路对二叉树进行一次中序遍历得到一个有序的序列,使用队列保存二叉树中序遍历后的序列。再通过每次在队列中弹出一个元素生成双向链表的每个节点来生成完整的双向链表。代码实现import java.util.*;/**public class TreeNode { int val = 0; TreeNode left = null; TreeNode rig原创 2021-01-23 15:05:36 · 50 阅读 · 0 评论 -
合并两个有序的链表
题目描述输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。注意的问题关键在于使用哪个位置的指针。如果变量设置的不清晰会导致实现流程很复杂。可以使用一个指针cur,开始时指向head,不断对cur.next赋值并不断另cur=cur.next实现从前到后的指针移动。使用一个虚拟的头节点可以更加方便。注意最后的结果应该返回head.next。代码实现/*public class ListNode { int val; ListNode原创 2021-01-22 22:41:50 · 57 阅读 · 0 评论 -
数组中重复的数字
题目描述在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中第一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。返回描述:如果数组中有重复的数字,函数返回true,否则返回false。如果数组中有重复的数字,把重复的数字放到参数duplication[0]中。(ps:duplication已经初始化,可以直接赋值使用。)思路记一个巧妙的方原创 2021-01-22 22:35:52 · 67 阅读 · 0 评论 -
数据流中的中位数
题目描述如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。思路使用两个堆,一个最大堆堆存储已插入数据的前一半,另一个最小堆存储已插入数据的后一半。当数据总数为偶数时,数据流的中位数就是两个堆的堆顶元素之和的二分之一;当数据总数为奇数时,数据流的中位数是第二个堆的堆顶(规定原创 2021-01-22 22:26:19 · 123 阅读 · 0 评论 -
字符流中第一个不重复的字符
题目描述请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。思路Insert(char ch):Insert函数,参数为在字符流中最新读取的字符。设置保存字符的队列LinkedList,保存只出现一次的字符,头部到尾部的顺序正好是字符出现的顺序。设置长度为128的整型数组arr,arr[i]为字符i在字符流读出的字符中出现的次数。Ins原创 2021-01-17 19:52:10 · 272 阅读 · 0 评论 -
树的子结构
题目描述输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)注意的问题把每个函数的作用弄清楚:HasSubtree(TreeNode root1,TreeNode root2):以root2为根的树是否可以是以root1为根的树的子结构。当root1和root2都不为空时,若root1.val != root2.val,此时root2的树如果能是root1的子结构,必然有两种情况:①以root2为根的树是以root1.left为根的树的子结构。②以root2为原创 2021-01-17 18:35:21 · 51 阅读 · 0 评论 -
栈的压入、弹出序列
问题描述输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)思路设置一个栈模拟栈的压入、弹出过程。代码实现import java.util.ArrayList;import java.util.Stack;public class Solution原创 2021-01-16 20:08:42 · 55 阅读 · 0 评论 -
对称的二叉树
问题描述请实现一个函数,用来判断一棵二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。代码实现/*public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; }}*/public class Solution {原创 2021-01-16 20:05:22 · 60 阅读 · 0 评论 -
二叉树的下一个结点
问题描述给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。思路分情况讨论:1.如果当前节点的右子树不为空,则下一个节点为当前节点右子树上的最左节点。2.如果当前节点的右子树为空,则需要向上寻找:**从当前节点开始,寻找一个祖先节点,这个节点是父节点的左子节点,那么答案就是这个父节点。**如果一直走到null都没有这样的节点和父节点,那么说明当前节点没有中序遍历的后继节点,返回null。代码实现/*public原创 2021-01-16 19:56:56 · 64 阅读 · 0 评论 -
寻找第K大
题目描述有一个整数数组,请你根据快速排序的思路,找出数组中第K大的数。给定一个整数数组a,同时给定它的大小n和要找的K(K在1到n之间),请返回第K大的数,保证答案存在。实现思路partition函数,取arr[L]作为划分元素,将L+1~R的元素小于arr[L]的放到arr[L]右侧,大于arr[L]的放到arr[L]左侧,arr[L]放到中间。并返回arr[L]最终的位置(可以确定arr[L]这个数字在整个arr中是第几小)。二分法,设置L=1,R=n-1,调用partition(arr,L,原创 2021-01-15 18:23:06 · 91 阅读 · 1 评论 -
丑数
问题描述把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。实现思路维护三个队列,分别保存2、3、5的倍数,每次从三个队头取出最小的元素即为下一个丑数。实际上不用有实际的队列,而是可以采用指针法实现:假设arr保存第1~N个丑数,则初始化arr[1]=1,设置3个指针p2,p3,p5指向已经加入arr的最后一个丑数,则初始化p2=p3=p5=1。则arr[p2]*2表示原创 2021-01-15 18:06:26 · 68 阅读 · 0 评论 -
缺失数字
题目描述从0,1,2,…,n这n+1个数中选择n个数,组成有序数组,找出这n个数中缺失的那个数,要求O(n)尽可能小。代码实现import java.util.*;public class Solution { /** * 找缺失数字 * @param a int整型一维数组 给定的数字串 * @return int整型 */ public int solve (int[] a) { // write code here原创 2021-01-15 17:54:45 · 88 阅读 · 0 评论 -
链表中环的入口节点
题目描述对于一个给定的链表,返回环的入口节点,如果没有环,返回null。解法快慢指针法。1.设置快指针fast和慢指针slow。2.快指针一次移动两步,慢指针一次移动一步,则快慢指针一定会在环中相遇。3.一个指针从环中的相遇点出发,另一个指针从链表的头部出发,则一定会在环的入口节点相遇。代码实现/** * Definition for singly-linked list. * class ListNode { * int val; * ListNode next;原创 2021-01-15 16:35:00 · 89 阅读 · 0 评论 -
设计getMin功能的栈
题目描述实现一个特殊功能的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作。实现思路设置一个栈 minStack 专门用来保存栈 dataStack 的最小值。1.push 操作:将数值压入 dataStack 中,若 minStack 为空或 minStack 不为空且 minStack 的栈顶元素大于当前数值,则将数值也压入 minStack。2.pop 操作:将数据从 dataStack 弹出,若 minStack 不为空且 minStack 的栈顶元素等于 dataStac原创 2021-01-14 18:09:26 · 179 阅读 · 0 评论 -
将升序数组转化为平衡二叉搜索树
题目描述给出一个升序排序的数组,将其转化为平衡二叉搜索树。平衡二叉搜索树树中任何结点的左子树和右子树高度最多相差1。实现思路将数组从中点分成左右两份,用左侧的数字构建左子树,右侧的数字构建右子树,递归执行,直到数组长度为0。则可以保证树中任意节点的左子树高度和右子树高度最多相差1。代码实现import java.util.*;/* * public class TreeNode { * int val = 0; * TreeNode left = null; * T原创 2021-01-14 16:40:10 · 543 阅读 · 0 评论 -
矩阵中的路径
问题描述请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。思路1.深度优先遍历。尝试从矩阵的每一个位置为起点进行深度遍历,每个位置的下一步可以有上下左右四个方向,任何一个方向返回 true 都说明路径存在,否则说明路径不存在。2.设置 flag 数组,保存矩阵中的每个位置是否来过。可以将 flag 数组也加入 dfs原创 2021-01-14 16:28:23 · 135 阅读 · 0 评论 -
用一个栈实现另一个栈的排序
题目描述一个栈中元素的类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈。除此之外,可以申请新的变量,但不能申请额外的数据结构。如何完成排序?实现思路原来的栈为 stack,辅助栈为 help。不断从 stack 中弹出元素,弹出的元素记为 cur。1.如果 help 为空或 cur 小于 help 的栈顶元素,则将cur直接压入help。2.如果 cur 大于 help 的栈顶元素,则从 help 一直弹出元素压入stack,直到 cur 小于 help 的栈顶元素。3.原创 2021-01-14 16:15:04 · 166 阅读 · 0 评论 -
奇数下标都是奇数或者偶数下标都是偶数
题目描述给定一个长度不小于2的数组arr,实现一个函数调整arr,要么让所有的偶数下标都是偶数,要么让所有的奇数下标都是奇数。思路设置两个指针even和odd。不断检测arr[n-1]位置的数字,如果是奇数就发送到odd所在的位置(交换arr[n-1]和arr[odd]),并人让odd += 2;如果是偶数就发送到even所在的位置(交换arr[n-1]和arr[even]),并让even += 2。所以初始时even=0, odd=1。直到even超过n-1或odd超过n-1位置(说明n-1和n原创 2021-01-12 17:55:37 · 145 阅读 · 0 评论 -
两个链表生成相加链表
题目描述假设链表中每一个节点的值都在 0 - 9 之间,那么链表整体就可以代表一个整数。给定两个这种链表,请生成代表两个整数相加值的结果链表。例如:链表 1 为 9->3->7,链表 2 为 6->3,最后生成新的结果链表为 1->0->0->0。思路1.加法一定时从低位到高位进行的,所以需要反转链表。2.用两个指针分别指向链表头部,从前向后遍历。遍历过程中将两个指针指向的节点数值相加,并生成新的节点。3.注意进位的问题。每一轮的节点值=当前两个节点值之原创 2021-01-12 16:51:08 · 103 阅读 · 0 评论 -
比较版本号
题目描述如果version1 > version2 返回1,如果 version1 < version2 返回-1,不然返回0.输入的version字符串非空,只包含数字和字符.。.字符不代表通常意义上的小数点,只是用来区分数字序列。例如字符串2.5并不代表二点五,只是代表版本是第一级版本号是2,第二级版本号是5.注意的问题'.'使用String.split函数的正确方式:String []s1 = version1.split("\\.");代码实现import java.原创 2021-01-12 16:43:13 · 78 阅读 · 0 评论 -
画匠问题
来源牛客网题目描述给定一个整型数组arr, 数组中的每个值都为正数,表示完成一幅画作需要的时间,再给定一个整数num,表示画匠的数量,每个画匠只能画连在一起(即数组内连续的一段)的画作。所有画家并行工作,请返回完成所有的画作的最少时间。求解思路动态规划方法。设置 dp 数组,dp[i][j] 表示第0到i号画匠完成第0到j号画的最少时间。设置 sum 数组,sum[i][j] 表示 arr[i]+arr[i+1]+…+arr[j] 的结果。考虑 dp[i][j] 的求法:只考虑最后一个画匠画原创 2021-01-12 16:31:09 · 315 阅读 · 1 评论 -
数字字符转化为字母组合的种数
数字字符转化为字母组合的种数来源数字字符转化为字母组合的种数_牛客网《程序员代码面试指南》:数字字符串转换为字母组合的种数注意的问题1.dp[i]的定义为str[0…i-1]已经转化完毕,剩下的字符转换成字母组合的结果种数。2.判断str[i]是否是给定字符时,别忘了加’’,如’0’。3.注意结果值的溢出问题。代码实现import java.util.Scanner;public class Main{ public static void main(String []args)原创 2021-01-04 19:54:30 · 325 阅读 · 0 评论 -
判断一个数是否是回文数
判断一个数是否是回文数来源判断一个数是否是回文数_牛客网代码实现import java.util.Scanner;public class Main{ public static void main(String []args){ Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); if(n < 0){ n = -n;原创 2021-01-03 18:15:40 · 99 阅读 · 0 评论