算法数据结构(三十五)----子数组达到累加和的最大长度系列

本文主要是介绍算法数据结构(三十五)----子数组达到累加和的最大长度系列,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目一

给定一个正整数组成的无序数组arr,给定一个正整数值K

找到arr的所有子数组里,哪个子数组的累加和等于K,并且是长度最大的

返回其长度

//滑动窗口
public static int getMaxLength(int[] arr, int K) {if (arr == null || arr.length == 0 || K <= 0) {return 0;}int left = 0;int right = 0;int sum = arr[0];int len = 0;while (right < arr.length) {if (sum == K) {len = Math.max(len, right - left + 1);sum -= arr[left++];} else if (sum < K) {right++;if (right == arr.length) {break;}sum += arr[right];} else {sum -= arr[left++];}}return len;}

题目二

 给定一个整数组成的无序数组arr,值可能正、可能负、可能0

给定一个整数值K

找到arr的所有子数组里,哪个子数组的累加和等于K,并且是长度最大的

返回其长度

//使用前缀和预处理数据
public static int maxLength(int[] arr, int k) {if (arr == null || arr.length == 0) {return 0;}// key:前缀和// value : 0~value这个前缀和是最早出现key这个值的HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();map.put(0, -1); // importantint len = 0;int sum = 0;for (int i = 0; i < arr.length; i++) {sum += arr[i];if (map.containsKey(sum - k)) {len = Math.max(i - map.get(sum - k), len);}if (!map.containsKey(sum)) {map.put(sum, i);}}return len;}

题目三

 给定一个整数组成的无序数组arr,值可能正、可能负、可能0

给定一个整数值K

找到arr的所有子数组里,哪个子数组的累加和<=K,并且是长度最大的

返回其长度

public static int maxLengthAwesome(int[] arr, int k) {if (arr == null || arr.length == 0) {return 0;}int[] minSums = new int[arr.length];int[] minSumEnds = new int[arr.length];minSums[arr.length - 1] = arr[arr.length - 1];minSumEnds[arr.length - 1] = arr.length - 1;for (int i = arr.length - 2; i >= 0; i--) {if (minSums[i + 1] < 0) {minSums[i] = arr[i] + minSums[i + 1];minSumEnds[i] = minSumEnds[i + 1];} else {minSums[i] = arr[i];minSumEnds[i] = i;}}// 迟迟扩不进来那一块儿的开头位置int end = 0;int sum = 0;int ans = 0;for (int i = 0; i < arr.length; i++) {// while循环结束之后:// 1) 如果以i开头的情况下,累加和<=k的最长子数组是arr[i..end-1],看看这个子数组长度能不能更新res;// 2) 如果以i开头的情况下,累加和<=k的最长子数组比arr[i..end-1]短,更新还是不更新res都不会影响最终结果;while (end < arr.length && sum + minSums[end] <= k) {sum += minSums[end];end = minSumEnds[end] + 1;}ans = Math.max(ans, end - i);if (end > i) { // 还有窗口,哪怕窗口没有数字 [i~end) [4,4)sum -= arr[i];} else { // i == end,  即将 i++, i > end, 此时窗口概念维持不住了,所以end跟着i一起走end = i + 1;}}return ans;}

题目四

 给定一个数组arr,给定一个值v

求子数组平均值小于等于v的最长子数组长度

// 暴力解,时间复杂度O(N^3),用于做对数器public static int ways1(int[] arr, int v) {int ans = 0;for (int L = 0; L < arr.length; L++) {for (int R = L; R < arr.length; R++) {int sum = 0;int k = R - L + 1;for (int i = L; i <= R; i++) {sum += arr[i];}double avg = (double) sum / (double) k;if (avg <= v) {ans = Math.max(ans, k);}}}return ans;}
// 想实现的解法2,时间复杂度O(N*logN)public static int ways2(int[] arr, int v) {if (arr == null || arr.length == 0) {return 0;}TreeMap<Integer, Integer> origins = new TreeMap<>();int ans = 0;int modify = 0;for (int i = 0; i < arr.length; i++) {int p1 = arr[i] <= v ? 1 : 0;int p2 = 0;int querry = -arr[i] - modify;if (origins.floorKey(querry) != null) {p2 = i - origins.get(origins.floorKey(querry)) + 1;}ans = Math.max(ans, Math.max(p1, p2));int curOrigin = -modify - v;if (origins.floorKey(curOrigin) == null) {origins.put(curOrigin, i);}modify += arr[i] - v;}return ans;}

 解法三:每个数字都减V,然后算这个数组中累加和小于等于0的子数组哪个最长

// 想实现的解法3,时间复杂度O(N)public static int ways3(int[] arr, int v) {if (arr == null || arr.length == 0) {return 0;}for (int i = 0; i < arr.length; i++) {arr[i] -= v;}return maxLengthAwesome(arr, 0);}// 找到数组中累加和<=k的最长子数组public static int maxLengthAwesome(int[] arr, int k) {int N = arr.length;int[] sums = new int[N];int[] ends = new int[N];sums[N - 1] = arr[N - 1];ends[N - 1] = N - 1;for (int i = N - 2; i >= 0; i--) {if (sums[i + 1] < 0) {sums[i] = arr[i] + sums[i + 1];ends[i] = ends[i + 1];} else {sums[i] = arr[i];ends[i] = i;}}int end = 0;int sum = 0;int res = 0;for (int i = 0; i < N; i++) {while (end < N && sum + sums[end] <= k) {sum += sums[end];end = ends[end] + 1;}res = Math.max(res, end - i);if (end > i) {sum -= arr[i];} else {end = i + 1;}}return res;}

 总结

题目一主要技巧:利用单调性优化

题目二主要技巧:利用预处理结构优化 + 讨论开头结尾

题目三主要技巧:假设答案法+淘汰可能性(很难,以后还会见到)


 题目五

给定一个正方形矩阵matrix,原地调整成顺时针90度转动的样子

a  b  c          g  d  a

d  e  f           h  e   b

g  h  i            i    f   c

 

public static void spiralOrderPrint(int[][] matrix) {int tR = 0;int tC = 0;int dR = matrix.length - 1;int dC = matrix[0].length - 1;while (tR <= dR && tC <= dC) {printEdge(matrix, tR++, tC++, dR--, dC--);}}public static void printEdge(int[][] m, int tR, int tC, int dR, int dC) {if (tR == dR) {for (int i = tC; i <= dC; i++) {System.out.print(m[tR][i] + " ");}} else if (tC == dC) {for (int i = tR; i <= dR; i++) {System.out.print(m[i][tC] + " ");}} else {int curC = tC;int curR = tR;while (curC != dC) {System.out.print(m[tR][curC] + " ");curC++;}while (curR != dR) {System.out.print(m[curR][dC] + " ");curR++;}while (curC != tC) {System.out.print(m[dR][curC] + " ");curC--;}while (curR != tR) {System.out.print(m[curR][tC] + " ");curR--;}}}

 题目六

给定一个长方形矩阵matrix,实现转圈打印

a  b  c  d

e  f   g  h

i   j   k   L

打印顺序:a b c d h L k j I e f g

public static void rotate(int[][] matrix) {int a = 0;int b = 0;int c = matrix.length - 1;int d = matrix[0].length - 1;while (a < c) {rotateEdge(matrix, a++, b++, c--, d--);}}public static void rotateEdge(int[][] m, int a, int b, int c, int d) {int tmp = 0;for (int i = 0; i < d - b; i++) {tmp = m[a][b + i];m[a][b + i] = m[c - i][b];m[c - i][b] = m[c][d - i];m[c][d - i] = m[a + i][d];m[a + i][d] = tmp;}}

 题目七

给定一个正方形或者长方形矩阵matrix,实现zigzag打印

0 1 2

3 4 5

6 7 8

打印: 0 1 3 6 4 2 5 7 8

public static void printMatrixZigZag(int[][] matrix) {int tR = 0;int tC = 0;int dR = 0;int dC = 0;int endR = matrix.length - 1;int endC = matrix[0].length - 1;boolean fromUp = false;while (tR != endR + 1) {printLevel(matrix, tR, tC, dR, dC, fromUp);tR = tC == endC ? tR + 1 : tR;tC = tC == endC ? tC : tC + 1;dC = dR == endR ? dC + 1 : dC;dR = dR == endR ? dR : dR + 1;fromUp = !fromUp;}System.out.println();}public static void printLevel(int[][] m, int tR, int tC, int dR, int dC, boolean f) {if (f) {while (tR != dR + 1) {System.out.print(m[tR++][tC--] + " ");}} else {while (dR != tR - 1) {System.out.print(m[dR--][dC++] + " ");}}}

 

这篇关于算法数据结构(三十五)----子数组达到累加和的最大长度系列的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1057274

相关文章

如何提高Redis服务器的最大打开文件数限制

《如何提高Redis服务器的最大打开文件数限制》文章讨论了如何提高Redis服务器的最大打开文件数限制,以支持高并发服务,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录如何提高Redis服务器的最大打开文件数限制问题诊断解决步骤1. 修改系统级别的限制2. 为Redis进程特别设置限制

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO