数据结构与算法
文章平均质量分 53
算法题解,思路
赫萝的红苹果
心若有向往,何惧道阻且长!
https://github.com/yumoxuan-25
展开
-
秋招笔试收获
题目:有一组整型数据,里面有正数负数。从前往后遍历该数字,该数组每个节点可以选择取或者不取,在取的过程中,所取的数的和不能为负数。问最多能取多少个数?可以使用优先级队列,把已经取了的值都加入小根堆,一旦遇到添加某个值,和为负数,就将该值加入小根堆,然后从小根堆移出一个数(也就是移除最小数),再调整所取的值的和,这样就相当于将到目前为止选择的数里面的最小值和当前值进行了交换。通过数字替换,这个我倒是没想到,确实很神奇。如果当前值是所取的值里面的最小值,加入最小堆之后再移除出来还是该值。这样就能保证不应该原创 2021-09-12 16:05:34 · 66 阅读 · 0 评论 -
java比较器,匿名比较器,lambda比较器,优先级队列的使用
java有一个比较器接口Comparator,里面有一个compare方法。比较函数有两个参数a,b;返回a-b就是升序,返回b-a就是降序。不过最好用比较,不要用相减。使用场景:Arrays里面有一个sort(T[],Comparator)可以根据比较器对数组的数据进行排序。排序二维数组是最好用的选择。例如每个人都有身高和体重[h,w],有n个人,就可以弄成二维数组。然后按照身高或者体重进行排序。数组降序排序也要使用比较器,根据比较器进行排序。优先级队列里面也要使用比较器。//poin原创 2021-09-10 12:17:56 · 719 阅读 · 0 评论 -
leetcoe253 最少会议室问题
题目:有一堆会议,每个会议都有开始时间和结束时间,问至少需要几个房间可以安排下这些会议?该问题可以使用贪心来做,使用小顶堆来实现最简单。首先用一个最小堆来将会议按照会议开始时间从小到大排序,然后遍历该小顶堆。在遍历里面,如果第二个小顶堆不为空,并且第二个小顶堆的堆顶值小于等于遍历出堆的开始值,就将堆顶值出堆,然后将该会议的结束时间入堆。否则将堆的结束时间入最小堆。最后第二个堆的大小就是最少会议室数量。看代码可能更好理解。package BiShi;import java.util.Prior原创 2021-09-09 22:55:53 · 1188 阅读 · 0 评论 -
对01背包,完全背包的一些理解
01背包问题下滚动数组,为什么要先遍历物品再遍历容量?因为本质上,滚动数组和原来二维的是差不多的,计算某一个值是通过上一层结果得出的,可能需要使用到上一层,也就是i-1层的下标比当前下标j小的任何数。先遍历物品,就是先把i-1层计算出来,符合要求。而先遍历背包容量,先计算出的数组,每次循环只有一个i-1层的数据,并且每一层都会把上一个覆盖掉,但是实际计算需要的是一整层的数据,因为都可能会用到。为什么二维的时候先便利物品或者先遍历容量都可以?因为二维的时候不会出现数据覆盖,计算后面的时候,前面的值都原创 2021-08-22 10:17:30 · 415 阅读 · 1 评论 -
两个线程实现交替打印1-100
这是一道多线程的算法,直接使用类似于生产者消费者模式的算法就行.输出一次之后先唤醒其他线程,然后就调用wait方法,释放锁.另一个线程就会获取锁,并打印,重复上述流程.如果要求某个线程先打印,可以在第一个线程启动之后,睡眠100ms再启动第二个线程,这样第一个线程就一定打印第一个数据.(当然我没加睡眠也一直是先启动的线程先打印,不知道是不是概率问题)挺简单的,看代码应该都能懂.源码:package leetcode;public class JiaoTiDaYin { public st原创 2021-08-11 21:56:42 · 1944 阅读 · 0 评论 -
对回溯算法的理解
回溯算法是纯暴力算法,虽然并不高效,但有些问题能求出来就好了。比如组合,排列,分割,子集,棋盘,求树的路径等问题就适合回溯算法,一个问题,如果不确定有多少层循环,就可以使用回溯算法。事实上回溯算法都可以抽形成树形结构,结果中的每一个数据,都对应着一层递归。每层递归会把某一位数据可能出现的情况都遍历一次。以组合问题为例,假设所给数组中没有重复数据。首先一个for循环遍历数组,循环里面放这递归,递归开始前先将当前数据入临时结果,递归函数下面把该数据从临时结果中去掉;下一次递归的for循环就从当前已原创 2021-08-09 13:33:44 · 119 阅读 · 0 评论 -
归并排序的理解,归并排序的时间复杂度,归并排序链表
归并排序是一种类似于分治的思想。把整个数组不停地对半分割,然后进行递归。递归一直持续到每个分组只剩一个元素,就结束递归,进行排序。排序就是合并两个有序数组。从递归深层一直往外层合并数组,到最后就完全合并成一个有序数组。具体看下面代码的注解吧!// 归并排序(Java-递归版)static void merge_sort_recursive(int[] arr, int[] result, int start, int end) { if (start >= end)//递归结束条原创 2021-08-08 11:40:46 · 443 阅读 · 0 评论 -
40. 组合总和 II leetcode
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的每个数字在每个组合中只能使用一次。注意:解集不能包含重复的组合。示例 1:输入: candidates = [10,1,2,7,6,1,5], target = 8,输出:[[1,1,6],[1,2,5],[1,7],[2,6]]示例 2:输入: candidates = [2,5,2,1,2], target = 5,原创 2021-07-21 11:12:42 · 67 阅读 · 0 评论 -
leetcode 343. 整数拆分
给定一个正整数 n,将其拆分为至少两个正整数的和,并使这些整数的乘积最大化。 返回你可以获得的最大乘积。这道题可以使用动态规划来做。首先我们需要确定dp数组的含义:dp[i]代表当n为i的时候,所能拆分求得的最大值。然后确定状态转移方程:每个dp[i]都可以遍历自己有多少种拆分可能。比如dp[4]可以分为1+3,2+2,3+1;可以再把后面部分进行拆分,1+dp[3],2+dp[2],3+dp[1],1+3和1+dp[3]取最大的,在遍历过程中用dp[i]一直更新最大值,遍历完得到的就是dp[i原创 2021-06-20 15:44:32 · 122 阅读 · 0 评论 -
669.修建二叉搜索树
给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树不应该改变保留在树中的元素的相对结构(即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在唯一的答案。所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/trim-a-binary-search-t原创 2021-06-14 11:07:32 · 89 阅读 · 0 评论 -
leetcode236.二叉树的最近公共祖先
题目:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree这是一个第一眼看着挺简单,代码也很简单,但是很容易把人绕进去的题。首先原创 2021-06-11 22:40:40 · 101 阅读 · 2 评论 -
二叉树的层次遍历
二叉树的层次遍历使用队列来实现。如果要一层一层进行输出,那么就需要通过记录上一层的大小来进行输出。leetcode102题一开始先处理root为空的情况。将头节点如队列,然后一个while循环,结束条件为队列为空。每次循环获取队列的大小size,这个大小就是二叉树某一层的大小。然后循环size次,将队列的全部节点取出,将当前节点输出,并把非空孩子节点加入队列。这样循环size次就得到某一层的全部节点了。一直到队列为空,代表遍历完成。代码: import java.util.*;c原创 2021-05-27 16:26:30 · 63 阅读 · 0 评论 -
树的遍历(栈实现)
前序遍历:树节点的定义我没写,因为是做算法题。树的前序遍历是先输出当前节点,再输出左孩子节点,然后输出右孩子节点。首先,处理根节点为空的情况。前序遍历比较简单,用一个while循环,用栈非空作为结束条件。一开始先把根节点入栈,while循环里面就进行出栈,拿到节点。输出当前节点的值,然后将右孩子入栈,再将左孩子入栈。(因为栈是后进先出)这样就实现了前序遍历。前序遍历代码import java.util.*;class Solution { public List<Integ原创 2021-05-27 15:47:41 · 1271 阅读 · 0 评论 -
leetcode 151.翻转字符串里的单词 题解
题目给定一个字符串,逐个翻转字符串中的每个单词。说明:无空格字符构成一个 单词 。输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。思路:本题在处理字符串前后空格的时候,可以直接使用库函数,因为这不是本题的重点。本题的重点是把单词看作整体,反转整个字符串。首先用库函数去字符串的首尾空格然后将字符串转换成字符数组,用一个循环去除中间的多余空格。最后创建一个新数组,用一个循环从后往前遍历原数组,遇到空格就原创 2021-05-13 11:23:48 · 248 阅读 · 0 评论 -
数据结构与算法总结(一)——数组
一些基础数组是一种线性的数据结构,每个节点的大小一样,在内存上连续。可以通过下标快速定位想要查询的目标值,因此数组检索的效率高。数组的长度一旦设定就无法改变,删除数组的元素,事实上并不是删除,而是覆盖。数组只能通过一个新的值来覆盖旧的值。题型二分法有序数组查找,可以使用二分法。二分法最重要迷惑的点就是while循环里面是否有=,这个看情况,如果给定的数组右边是包括边界的,那么就要用=,因为当值取到最后一个元素的时候,还是可能是目标值,因此还是需要进入循环。另外一个很迷惑的点就是是否新的边原创 2021-05-10 19:02:45 · 89 阅读 · 0 评论 -
二叉树中序遍历线索化 C++ 递归实现
二叉树中序遍历线索化中序遍历有一个特点,只要不是叶子节点,遍历的时候左孩子一定是当前节点的上一个访问节点;右孩子一定是当前节点的下一个访问节点。如果把叶子节点的左右孩子都利用起来,把空的左孩子做成前驱线索,右孩子做成后继线索,就可以实现整个二叉树每一个节点的左孩子就是它的上一个访问节点,右孩子就是它的下一个访问节点。重点需要处理的就是第一个访问节点的前驱节点以及最后一个访问节点的后继节点,只需要创建一个新节点作为中介就行!代码:#include<iostream>using name原创 2020-09-21 15:16:37 · 1383 阅读 · 0 评论 -
C++ 二叉树的创建,和三种遍历方式的实现
#include<iostream>using namespace std;typedef struct BiTNode{ string data; BiTNode* lchild, * rchild;}*BiTree;void creatBiTree(BiTree &p){ string S; cout << "请按照先序遍历的顺序输入数据,#代表NULL:"; cin >> S; if (S =="#") { (p) = NUL原创 2020-08-22 11:01:41 · 1594 阅读 · 2 评论 -
C++ 树、树的存储结构(双亲表示法,孩子表示法,双亲孩子表示法)
双亲表示法双亲表示法的特点就是每一个节点里面除了存放节点数据之外,还存放着该节点的双亲节点位置。#include<iostream>#define maxTree 100using namespace std;typedef struct//双亲节点{ string data;//节点数据 int parent;//节点的双亲节点下标}Pparent;typedef struct{ Pparent nodes[maxTree];//节点数组 int r, n;//r代表原创 2020-08-18 11:18:37 · 3522 阅读 · 0 评论 -
C++ 数据结构之KMP算法 详解
KMP算法解析KMP算法是一种匹配算法,用来进行匹配查找。通过在子串的每一位都设置一个与之对应的回溯数组下标,降低算法的时间复杂度。每一个需要查找的子串,该算法都会给它生成一个与之相对于的next数组,用来进行回溯。假设需要查找的子串为:string S=“aaababa”//该串首位也用来存放数据生成的next数组为0012010//代表数组下标假如数组是匹配到了S[3]才出现匹配失败,这代表前面的S[0],S[1],S[2]都匹配成功了。S[0],S[1]和S[1],S[2]是一样的,都是a原创 2020-08-17 14:54:55 · 594 阅读 · 2 评论 -
C++ 汉诺塔的实现(递归)详解
汉诺塔是经典的递归题,可以很好地锻炼递归思维。题目:有三根铁柱,铁柱上面有铜片,铜片有大有小,每种规格只有一个。并且无论什么时候,铜片的叠加顺序只能是小的在上,大的在下。每次移动只能移动一块铜片,要我们把串在一根铁柱上的某数量的铜片移动到另一个铁柱。思路:令三根柱子分别为x,y,z。一开始全部铜片都在x上。假如有两块规格不同的铜片,那么我们的做法是把最大那块上面的那块从x放到y,然后把最大的从x放到z,再把y上面的放到z。假如有三个不同规格的铜片,那么我们的想法是先把上面那两块看成一个整体,原创 2020-08-09 22:45:53 · 1388 阅读 · 0 评论 -
C++ 队列的几种实现方式(数组、指针、链表)
用数组实现顺序队列队列遵循先进先出原则,所以入队位置固定,出队位置也固定。#include<iostream>#define maxSize 5//队列最大长度using namespace std;int tag = 0;//0代表出队,1代表入队struct qtQueue { int front, rear; int value[maxSize];};void initQueue(qtQueue &s){ s.rear = s.front = 0;}bo原创 2020-08-06 14:09:18 · 1432 阅读 · 0 评论 -
数组计算两数之和,三数之和,四数之和
这种计算几个数据之和的题目,一般分为在同一个数组中计算几个数之和等于某一个值。还有一种是给几个数组,每个数组中取一个数据,让你算几个数之和等于某一个值。一般情况下,第二中的难度会更大,因为去重会比较麻烦。如:1. 两数之和给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。题解:这个比较简单,用s原创 2021-05-12 20:06:22 · 905 阅读 · 2 评论