max(|leftmax-rightmax|)

本文介绍了一种高效算法,用于解决给定数组中左部分最大值与右部分最大值差值绝对值的最大化问题。通过巧妙地寻找数组两端的极端值来避免暴力解法的高时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

给定一个长度为N(N>1)的整形数组arr,可以划分成左右两个部分,做部分为arr[0..k],右部分为arr[k+1..N-1],k可以取值的范围是[0,N-2]。求这么多划分方案中,左部分中的最大值减去右部分的最大值的绝对值中,最大的是多少?

例如:[2,7,3,1,1]当左边部分为[2,7],右部分为[3,1,1]时,左部分中最大值减去右部分最大值的绝对值为4,当左部分为[2,7,3],右部分为[1,1]时,左部分中的最大值减去右部分最大值的绝对值为6,还有很多划分方案,但是最终返回6.


思路:确实很多划分,暴力方法也很简单,我相信我不用讲,大家都知道暴力方法(遍历出每种组合,O(n2))怎么做,但是这个是个脑筋急转弯,并不需要暴力,我们抛开表面看本质,两个问题:第一个,左边最大,右边最大,那么整个数组最大肯定出自于这两个之一,那么我们就可以用这最大值减去一个数(这个数还要是找出左边或右边最小的最大值)就是最终的答案,第二个问题(找出左边或右边最小的最大值),左边最大,必定跑不出第一个数,当从一个数向后扩时,当出现了比他大的,则大的就是左边最大值,这是我们不希望得到的,要是比第一个小,则第一个还是左边最大值,则我们左边取第一个数,右边最大,同理,取最后一个数,则最终就是整个数组最大值,减去左边右边较小的最大值

public static int maxABS3(int[] arr) {
		int max = Integer.MIN_VALUE;
		for (int i = 0; i < arr.length; i++) {
			max = Math.max(arr[i], max);
		}
		return max - Math.min(arr[0], arr[arr.length - 1]);
	}


#include<iostream> using namespace std; #include"bitree.h" int FindMax(BTNode<int>* bt) { if (bt == NULL) { return std::numeric_limits<int>::min(); // 返回最小值 } int leftMax = FindMax(bt->lchild); int rightMax = FindMax(bt->rchild); return std::max(bt->data, std::max(leftMax, rightMax)); } BTNode<int>* CopyBiTree(BTNode<int>* bt) { if(bt == NULL) { return NULL; } BTNode<int>* newRoot = new BTNode<int>(); newRoot->data = bt->data; newRoot->lchild = CopyBiTree(bt->lchild); newRoot->rchild = CopyBiTree(bt->rchild); return newRoot; } BTNode<int>* FindParent(BTNode<int>* bt, int target) { if(bt == NULL) { return NULL; } if(bt->lchild != NULL && bt->lchild->data == target) { return bt; } if(bt->rchild != NULL && bt->rchild->data == target) { return bt; } return FindParent(bt->lchild,target); } void PrintBiTree(BTNode<int>* bt) { if(bt == NULL) { return; } cout << bt->data<<" "; PrintBiTree(bt->lchild); PrintBiTree(bt->rchild); } void DeleteSubtree(BTNode<int>*& bt, int target) { if(bt == NULL) { return; } if(bt->data == target) { delete bt->lchild; delete bt->rchild; delete bt; return; } DeleteSubtree(bt->lchild, target); DeleteSubtree(bt->rchild, target); } int CountLeaves(BTNode<int>* bt) { if(bt == NULL) { return 0; } if(bt->lchild == NULL && bt->rchild == NULL) { return 1; } return CountLeaves(bt->lchild) + CountLeaves(bt->rchild); } int main() { BTNode<int>* Tree; CreateBiTree(Tree); cout << "二叉树中各结点元素的最大值:"<<FindMax(Tree); cout << "复制后的二叉树为:"; PrintBiTree(CopyBiTree(Tree)); int m; cout << "输入你想删除以值为X的结点为根的子树的X的值:"; cin >> m; DeleteSubtree(Tree,m); cout << "删除结点后的二叉树为:"; PrintBiTree(Tree); cout<<"叶子结点的个数为:"; cout<<CountLeaves(Tree); DestroyBiTree(Tree); return 0; }这段代码正确吗
最新发布
06-09
实验1-B-1:基于分治找最大值。设计一个分治算法在给定的无序整数数组,寻找输入数据中的最大值,实现该分治算法,分析算法的时间复杂度并进行测试。参考以下代码来写对应的c语言代码按照以下代码的模式来写代码:#include <stdio.h> #include <stdlib.h> #include <time.h> // 分治法寻找最大值函数 int findMax(int arr[], int start, int end) { // 基本情况:如果只有一个元素,直接返回该元素 if (start == end) { return arr[start]; } // 分解问题:找到中间位置 int mid = (start + end) / 2; // 递归求解左右两部分的最大值 int leftMax = findMax(arr, start, mid); int rightMax = findMax(arr, mid + 1, end); // 合并结果:比较左右两部分的最大值,返回较大的那个 int max = (leftMax > rightMax) ? leftMax : rightMax; return max; } // 时间复杂度分析函数 void analyzeTimeComplexity() { printf("\n=== 时间复杂度分析 ===\n"); printf("分治法寻找最大值的时间复杂度为O(n),其中n是数组的大小。\n"); printf("这是因为每次递归调用将数组分为两部分,每部分处理的时间为O(1),递归深度为O(log n),总共有O(n)次操作。\n"); } // 测试时间复杂度的函数 void testTimeComplexity() { printf("\n=== 测试时间复杂度 ===\n"); printf("正在生成不同规模的随机数组并测试运行时间...\n"); // 测试不同规模的数组,最小规模改为10000 for (int n = 10000; n <= 100000; n += 1000) { double total_time = 0.0; int max_value = -10000; // 初始化最大值 // 对每个规模运行多次,取平均时间 for (int run = 0; run < 5; run++) { // 动态分配数组内存 int* arr = (int*)malloc(n * sizeof(int)); if (arr == NULL) { printf("内存分配失败!\n"); return; } // 生成随机数组 srand(time(NULL) + run); // 每次运行使用不同的种子 for (int i = 0; i < n; i++) { arr[i] = rand() % 20001 - 10000; // 随机生成-10000到10000之间的数 } // 记录开始时间 clock_t start = clock(); // 调用分治法寻找最大值 int max = findMax(arr, 0, n - 1); // 记录结束时间 clock_t end = clock(); double time_spent = (double)(end - start) / CLOCKS_PER_SEC; // 累加时间 total_time += time_spent; // 更新最大值 if (max > max_value) { max_value = max; } // 释放动态分配的内存 free(arr);
03-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值