算法
__anonymous_
Stay hungry, stay foolish.
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
小技巧 ----- Java算法题标准模版
模版import java.util.*;import java.io.*;import java.math.*;class Main { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); String[] sp; BufferedWriter log = new BufferedWriter(new OutputStreamWriter(System.out)); /* 定义全局变量原创 2020-10-29 16:11:15 · 249 阅读 · 0 评论 -
小技巧 ----- 计数数组中小于 target 的元素个数
二分flag + 前缀和原创 2020-10-27 18:18:19 · 294 阅读 · 0 评论 -
小技巧 ----- 枚举整数的每一位数字
使用字符串int num = 12345;char[] c = String.valueOf(num).toCharArray();for (int i = 0; i < c.length; i++) { // c[i] - '0' 就是整数 num 从左到右的数字}先%10再/10int num = 12345;int x = num;while (x > 0) { int i = x % 10; x /= 10; // 这里的数字 i 就是整数 num 从右到左的数原创 2020-10-25 16:12:47 · 488 阅读 · 0 评论 -
AcWing 1245. 特别数的和 (数位枚举)
import java.util.*;class Main { Scanner s = new Scanner(System.in); int n; void run() { n = s.nextInt(); int sum = 0; for (int i = 1; i <= n; i++) { int x = i; while (x > 0) {原创 2020-10-25 16:06:05 · 196 阅读 · 0 评论 -
AcWing 1236. 递增三元组 (flag + 前缀和 | 二分 | 滑动窗口)
1236. 递增三元组解题思路最开始想到3重循环枚举三个数组,然后最内层用条件语句判断一下即可,但是数据范围为10510^5105,三重循环肯定会超时那么这道题很可能需要的算法复杂度为O(n)O(n)O(n)或O(nlogn)O(nlogn)O(nlogn),所以只能枚举一个数组,那么枚举哪一个呢?根据题目来看,要求Ai<Bj<CkA_i<B_j<C_kAi<Bj<Ck,那么就来枚举B数组此时我们只需要找到A数组中所有小于BjB_jBj的数和C数组中所原创 2020-10-25 15:35:10 · 356 阅读 · 0 评论 -
常用代码模板1 ----- 基础算法
一维前缀和求一维前缀和数组:从下标1开始记录for(i = 1 ... n) s[i] = s[i - 1] + a[i]从下标0开始记录s[0] = a[0]for(i = 1 ... n) s[i] = s[i - 1] + a[i]根据前缀和数组求a数组[l, r]区间和:sum = s[r] - s[l - 1]二维前缀和求二维前缀和数组:行列均从下标1开始记录for(i = 1 ... n) for(j = 1 ... m) S[i][j] = S[i -原创 2020-10-24 19:38:10 · 237 阅读 · 0 评论 -
记坑 ----- Arrays.sort()
开数组的时候一般是数据范围+10的长度,当要用到排序的时候,别直接Arrays.sort(arr),因为成员数据会直接赋默认值,数组里面默认的0就排序到前面去了关于Arrays.sort(int[] arr, int startIndex, int endIndex)区间排序的时候,需要注意的是[startIndex, endIndex),和substring一样...原创 2020-10-23 21:44:02 · 570 阅读 · 0 评论 -
AcWing 1210.连号区间 (枚举)
1210. 连号区间优化思路: 对于一个每次都增加1个长度的子区间,求这个区间内的最大值和最小值,只需要比较每次多的那个元素的值即可。import java.util.*;import java.io.*;import java.math.*;class Main { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); String[] sp; int[] arr原创 2020-10-20 00:15:59 · 178 阅读 · 0 评论 -
AcWing 1015. 摘花生 (DP)
1015. 摘花生思路状态表示:dp[i][j]表示从(1, 1)走到(i, j)的所有路线中权值最大的那条路线状态计算(集合划分):从(1, 1)走到(i, j)的所有路线集合划分为下面两类最后一步走到(i, j)时,是从上往下走的最后一步走到(i, j)时,是从左往右走的状态转移方程:dp[i][j] = max(dp[i - 1][j] + w[i][j], dp[i][j - 1] + w[i][j])ans = dp[r][c]import java.util.*;im原创 2020-10-15 17:23:11 · 194 阅读 · 0 评论 -
模版 ----- DP
动态规划解题思路以01背包问题为例一、状态表示dp[ i ][ j ]根据枚举思想抽象出一种集合步骤:明确问题目的01背包问题的目的是从一堆有权重和体积的物品中存放到一定体积的背包中,要求找到能让放在背包中的物品总价值和最大那种取法。根据枚举思想抽象出集合问题的目的是找到最佳取法,那么根据枚举思想,我们需要枚举出所有的取法,那么抽象出来的集合就是:从前 i(0 ~ n) 个物品中考虑并且选出的物品总体积不能超过 j(0 ~ m),每种不同的 i、j 取值对应着不同的集合。原创 2020-10-14 13:44:47 · 238 阅读 · 1 评论 -
AcWing 99. 激光炸弹 (二维前缀和)
99. 激光炸弹题意给定一个5000x5000的地图随机在该地图上放置物品,物品具有价值,且不同物品可以放置在同一位置有一个炸弹的爆炸范围为RxR的正方形问该炸弹在地图上爆炸一次,最多能摧毁的物品价值为多少思路枚举该正方形在地图中所有可能出现的位置利用二维前缀和计算在正方形范围内物品的价值和找出最大的那一个价值和class Main { BufferedReader reader = new BufferedReader(new InputStreamReader(Sys原创 2020-10-13 15:34:30 · 246 阅读 · 0 评论 -
模版 ----- 一维前缀和与二维前缀和
一维前缀和795. 前缀和a[i] 的前 i 项和 s[i] 的递推公式:s[i]=s[i−1]+a[i]s[i] = s[i - 1] + a[i]s[i]=s[i−1]+a[i]求出在 [l, r] 区间的和:sum[l,r]=s[r]−s[l−1]sum[l,r]=s[r]-s[l-1]sum[l,r]=s[r]−s[l−1]注意 a[i] 和 s[i] 均从下标1开始记录数据import java.util.*;import java.io.*;public class Main原创 2020-10-13 09:35:54 · 172 阅读 · 0 评论 -
AcWing 730. 机器人跳跃问题 (二分)
AcWing 730. 机器人跳跃问题思路:由题意可以推出从当前位置跳到下一个位置时,下一个位置的能量值一定为: 2∗E当前−H下一位置2*E_{当前}-H_{下一位置}2∗E当前−H下一位置由简单的数学归纳可以知道,当 E0E_0E0 满足题意的最小初始能量时,任何大于 E0E_0E0 的初始能量也满足题意,任何小于 E0E_0E0 的初始能量就不再满足题意了从上面的结论可以看出具有二段性,其中二段性的分界点即为满足题意的最小初始能量 E0E_0E0,因此该题可以用二分法二段性:左原创 2020-10-11 14:44:18 · 276 阅读 · 0 评论 -
模版 ----- 实数二分
模版// 这里根据题目要求保留结果几位小数来决定,如果保留4位小数则是1e-6(多开2位)while (r - l > 1e-6) { double mid = (r + l) / 2; if (mid在二段性右边) r = mid; else l = mid;}// 上面的循环结束后,r无限接近于l,此时的r和l即为二段性的分界点应用790. 数的三次方根思路:数据范围在 [-10000,10000] 之间,即被开方数取值在这之间那么其三次方根一定在 [-10000,1原创 2020-10-11 12:30:13 · 264 阅读 · 0 评论 -
小技巧 ----- Java中指定保留几位小数
方法1:使用String类的format方法String.format("%.6f", 小数),表示将该数保留6位小数方法2:使用BigDecimalBigDeciaml divide(BigDecimal divisor, int scale, RoundingMode roundingMode)(1) scale参数:设置小数位数(2) roundingMode参数:设置小数舍入模式详见:常用类 (三) ----- BigDecimal和BigInteger大数类...原创 2020-10-11 12:04:47 · 1359 阅读 · 0 评论 -
模版 ----- 一维指数型枚举 & 排列型枚举 & 组合型枚举
应用场景给定x个方格,每个方格可以存放0或者1两个状态(状态可以多个不一定只有2个)枚举出这n个方格的所有状态情况递归树模型:标准的x叉树,每个分支表示对于同一个方格的所有不同状态选择情况时间复杂度:O(xn)O(x^n)O(xn)代码模版import java.util.*;public class Main { Scanner s = new Scanner(System.in); // 方格数量 int x; // 每个方格对应的状态原创 2020-09-21 22:28:00 · 348 阅读 · 0 评论 -
模版 ----- 整数二分
整数二分思想确定一个区间,使得目标值一定在这个区间内从题目中找到一种性质:该性质具有二段性,比如一个数组的前半段元素符合该性质,后半段元素就不符合该性质了目标值一定为二段性的分界点处即:目标值可能在前半段的右端点,或者后半段的左端点根据上述的性质,具体可以把整数二分划分为两大类问题第一类:目标值是前半段的右端点将[L,R][L, R][L,R]分成 [L,mid−1][L, mid-1][L,mid−1]和[mid,R][mid, R][mid,R]如果midmi原创 2020-09-21 09:34:44 · 157 阅读 · 0 评论 -
计数排序
思路用辅助数组对数组中出现的元素进行计数(辅助数组下标值等于元素值时,辅助数组对应下标的元素值++),最终计数完后,扫描辅助数组,只要对应下标的值大于0,则把下标值从左到右回填到原数组中。效率分析时间复杂度:O(n + k),最好最坏情况都为O(n + k)空间复杂度:O(k)稳定性:稳定适用性:计数排序可以说是最快的排序算法,当序列边界小,数值大小比较集中时此时效率高,不会浪费很多空间。代码public static void countSort(int[] arr) {原创 2020-07-25 20:03:53 · 224 阅读 · 5 评论 -
基数排序
一、思路二、准备工作:定义一个二维数组:表示有10个桶,每个桶中装着一个数组定义一个一维数组:用来记录每个桶中存储了几个元素,指向桶的最低且为空的位置计算出待排序的数组中元素的最大位数,该最大位数对应一共要从10个桶中来回存取几次三、核心代码逻辑:把原数组按照元素的数位存放在对应的桶中再从依次从桶中取出相应元素覆盖原数组上诉代码要循环数组中元素的最大位数这么多次四、一些小技巧和结论求一个数的数位大小:(数字 + "").length(),把数转为字符串然后求其长度。求一原创 2020-07-25 18:54:40 · 120 阅读 · 0 评论 -
快速排序——三种划分方式
思路:1.分治思想:先划分成两个问题,然后对两个子问题递归排序,最后再合并。2.核心算法:快排的核心在于划分问题(找到分界点)。代码://快速排序public static void quickSort(int[] arr, int left, int right) { if(left < right) { //此处用单指针扫描来划分(可以替换划分方法) ...原创 2020-04-20 11:58:44 · 4963 阅读 · 1 评论 -
归并排序
public class MergeSort { //建立一个辅助空间 static int[] helper = new int[1024]; //归并排序: public static void mergeSort(int[] arr, int left, int right) { if(left < right) { ...原创 2020-04-20 10:21:16 · 255 阅读 · 0 评论 -
PREV-52 小数第n位 (大数)
题目:AC代码import java.math.BigDecimal;import java.util.Scanner;public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String a = scanner.next(); String b = scanner.next();原创 2020-08-21 16:58:49 · 172 阅读 · 0 评论 -
背包九讲 ----- 01背包问题模版
01背包问题题意输入:两个整数NNN、VVV,用空格隔开,分别表示待选的物品数量和背包的容积接下来有N行,每行有两个整数viv_ivi、wiw_iwi,用空格隔开,分别表示第iii个物品的体积和价值输出:背包能存放的最大价值题解(二维dp)用 f[i][j]f[i][j]f[i][j] 表示只看前 iii 个物品,背包容积为 jjj 时,背包能存放的最大价值那么 ans=ans=ans=maxmaxmax { f[N][0f[N][0f[N][0 ~ V]V]V]原创 2020-08-22 20:57:51 · 209 阅读 · 0 评论 -
LeetCode 面试题 08.01. 三步问题 (动态规划)
面试题 08.01. 三步问题class Solution { public int waysToStep(int n) { if(n == 1) return 1; if(n == 2) return 2; if(n == 3) return 4; long[] dp = new long[n + 1]; dp[1] = 1; dp[2] = 2; dp[3] = 4原创 2020-08-22 12:52:58 · 325 阅读 · 0 评论 -
牛客网 - 机器人走方格 (动态规划)
机器人走方格解法1(排列组合)公式:Cx+y−2x−1C_{x+y-2}^{x-1}Cx+y−2x−1或Cx+y−2y−1C_{x+y-2}^{y-1}Cx+y−2y−1注意点:x和y是方格的格点数机器人走的是格点public class Robot { public int countWays(int x, int y) { // write code here int n = x + y - 2; int t = x >原创 2020-08-22 13:24:29 · 458 阅读 · 0 评论 -
LeetCode 70. 爬楼梯 (递归&斐波那契 | 动态规划)
70. 爬楼梯解法1 (递归)推出递推式子:f(n) = f(n - 1) + f(n - 2)是一个斐波那契数列,用递归class Solution { public int climbStairs(int n) { if (n == 1) return 1; if (n == 2) return 2; return climbStairs(n - 1) + climbStairs(n - 2); }}解法2 (递归改循环)原创 2020-08-21 19:31:40 · 220 阅读 · 0 评论 -
LeetCode 647. 回文子串 (动态规划)
647. 回文子串题意:任意给定一个字符串,计算这个字符串的回文子串个数解法1(暴力法)思路:默认回文子串初始个数为字符串长度从子串长度为2—母串长度:找出所有的子串startIndex和endIndex判断子串是否是回文串,是的话count++class Solution { public int countSubstrings(String s) { // 子串长度 int length = 2; // 计数回文子串,默认原创 2020-08-03 16:31:26 · 175 阅读 · 0 评论 -
LeetCode1139. 最大的以 1 为边界的正方形 (二维滑动窗口&待优化)
1139. 最大的以 1 为边界的正方形题意:任意给一个只有0,1组成的矩阵,在里面找最大的由1围成的正方形{0,1,1,1,1}{0,1,0,1,1}{0,1,1,1,0}{0,1,0,1,1}{0,1,0,1,1}思路:用一个正方形窗口来扫描矩阵内的元素用窗口左上角来确定其位置最内层循环让窗口从左往由扫描矩阵最外层循环让窗口从上往下扫描矩阵收获:动态边在一定范围内移动的条件:startIndex(边的左顶点下标) + length(边长) - 1 <= bound原创 2020-08-01 12:03:59 · 282 阅读 · 0 评论 -
LeetCode 567. 字符串的排列 (滑动窗口&哈希表)
567. 字符串的排列题意:第一个字符串的排列之一是第二个字符串的子串即判断第二个字符串是否包含某个子串,这个子串的字符以及字符数量要求与第一个字符串相同解法1 (暴力法)按照第一个字符串的长度找出第二个字符串的所有相应长度的子串比较每个子串与第一个字符串的字符以及字符数量是否相同 (哈希表)class Solution { public static boolean checkInclusion(String s1, String s2) { Map<C原创 2020-08-20 17:00:54 · 330 阅读 · 0 评论 -
LeetCode 209. 长度最小的子数组 (滑动窗口)
LeetCode 209. 长度最小的子数组class Solution { public int minSubArrayLen(int s, int[] nums) { int start = 0; int sum = 0; int minLen = nums.length + 1; int mark = 0; for (int end = 0; end < nums.length; end++) {原创 2020-08-19 21:06:03 · 152 阅读 · 0 评论 -
LeetCode 340. 至多包含 K 个不同字符的最长子串
340. 至多包含 K 个不同字符的最长子串class Solution { public int lengthOfLongestSubstringKDistinct(String s, int k) { HashMap<Character, Integer> map = new HashMap<>(); int start = 0; int maxLen = 0; for (int end = 0; end原创 2020-08-19 20:10:03 · 209 阅读 · 0 评论 -
LeetCode 159. 至多包含两个不同字符的最长子串 (滑动窗口&哈希表)
159. 至多包含两个不同字符的最长子串class Solution { public static int lengthOfLongestSubstringTwoDistinct(String s) { HashMap<Character, Integer> map = new HashMap<>(); int start = 0; int maxLen = 0; for (int end = 0; end原创 2020-08-19 20:01:58 · 418 阅读 · 0 评论 -
LeetCode 3. 无重复字符的最长子串 (滑动窗口&哈希表)
3. 无重复字符的最长子串题意:找子串子串中无重复字符要求子串长度最长解法1(暴力法)思路:建立一个长度不断变小的滑动窗口用一个指针指针扫描窗口内的每个元素:如果除去指针指向的那个元素,窗口内仍有与其相同的字符则停止扫描只要上面的窗口扫描指针大于了窗口的endIndex,则说明该窗口内无相同字符返回该窗口长度即为ansclass Solution { public static int lengthOfLongestSubstring(String s) {原创 2020-08-16 16:30:23 · 250 阅读 · 0 评论 -
在有空字符串的有序字符串数组中查找(二分)
题意:给定一个按照字典顺序排序的字符串数组随意向数组中添加空串""查找字符串数组的非空串字符串返回其下标,不存在则返回-1思路:看见有序,可以考虑用二分法但是数组中有空串,mid指向的元素可能会空串,此时让mid++,直到mid指向的不为空串如果mid超过了right边界,说明最开始的mid到right这个范围内全为空串,此时让right收缩到最开始的mid - 1处即可以上为特殊处理,后面使用常规的二分法即可class Solution { public static i原创 2020-09-06 17:03:39 · 354 阅读 · 0 评论 -
LeetCode 154. 寻找旋转排序数组中的最小值 II (二分)
154. 寻找旋转排序数组中的最小值 II题意给定一个包含重复元素的升序旋转数组找出旋转数组的最小值二分法class Solution { public int findMin(int[] nums) { int left = 0; int right = nums.length - 1; while (left < right) { int mid = left + ((right - left) &g原创 2020-09-05 15:46:36 · 165 阅读 · 0 评论 -
AcWing 789. 数的范围 (整数二分)
AcWing 789. 数的范围题意:给定一个升序数组输入一个数输出这个数第一次出现的下标和最后一次出现的下标如果这个数不存在则输出-1 -1思路:用两次二分法第一次用来找到key出现的第一个位置第二次用来找到key出现的最后一个位置import java.util.*;import java.math.*;public class Main { public static void main(String[] args) { Scanner s =原创 2020-09-05 08:47:41 · 448 阅读 · 0 评论 -
LeetCode 153. 寻找旋转排序数组中的最小值(二分)
153. 寻找旋转排序数组中的最小值class Solution { public static int findMin(int[] nums) { int left = 0; int right = nums.length - 1; while (left < right) { int mid = left + ((right - left) >> 1);原创 2020-09-05 10:22:31 · 169 阅读 · 0 评论 -
小技巧 ----- 位运算的一些结论与应用
乘2与除2 (左乘右除)// 左乘10 << 1 = 20// 右除10 >> 1 = 10注意:被运算的数字始终在左边2的n次方1 << n = 2的n次方1 << 10 = 2的10次方注意:次方数始终在右边判断一个十进制数的二进制串的某一位数字是0 or 1// 判断二进制串1110的第3位(最低位为第0位)是数字1还是014 >> 3 & 1 // 运算结果为1应用:通过二进制串的位运算进原创 2020-09-20 13:12:15 · 1388 阅读 · 0 评论 -
小技巧 ----- 通过二进制串的位运算进行二维指数型枚举
二维指数型枚举题目:给定4x4矩阵(每个元素为1或0)枚举出所有情况,在矩阵元素为1的位置执行turn()方法思路:把4x4方格看作一个一维的水平长度为16的方格即现在需要枚举一个长度为16的二进制串将二进制串翻转过来,想象把其下标标记到矩阵的每一个元素上0 1 2 34 5 6 78 9 10 1112 13 14 15用(i, j)扫描上面抽象出来的矩阵,将坐标(i, j)转化为二进制串的对应的下标二进制串原创 2020-09-20 13:00:00 · 260 阅读 · 0 评论 -
小技巧 ----- 二维数组中通过(x, y)的偏移量来遍历(x, y)周围的元素
应用场景给定一个二维数组和一个点(x, y)要求遍历点(x, y)十字形范围的点,包括(x, y)结论首先把这个二维数组竖下方向看作x轴,横右方向看作y轴找到点(x, y)关于其上下左右点的偏移量放在两个数组中遍历时把x, y加上对应的偏移量就相当于遍历了(x, y)十字形范围且包括(x, y)的点// 找到(x, y)的x关于其上下左右点的偏移量int dx[] = {-1, 0, 1, 0, 0};// 找到(x, y)的y关于其上下左右点的偏移量int dy[] = {0原创 2020-09-18 19:07:09 · 869 阅读 · 0 评论
分享