4.24总结

先做了道力扣的题目

分隔数组以得到最大和

题目描述


给你一个整数数组 arr,请你将该数组分隔为长度 最多 为 k 的一些(连续)子数组。分隔完成后,每个子数组的中的所有值都会变为该子数组中的最大值。

返回将数组分隔变换后能够得到的元素最大和。本题所用到的测试用例会确保答案是一个 32 位整数。

示例一

输入:arr = [1,15,7,9,2,5,10], k = 3
输出:84
解释:数组变为 [15,15,15,9,10,10,10] 

示例 2:

输入:arr = [1,4,1,5,7,3,6,1,9,9,3], k = 4
输出:83

示例 3:

输入:arr = [1], k = 1
输出:1

分析:

这题递推出来,可以找出题目相应的状态转移方程然后求解,但是这里有一个弊端就是递归没有结束状态那么我们可以

在 f 数组的最左边插入一个状态,那么其余状态全部向右偏移一位,也就是 f[i]f[i] 改为 f[i+1]f[i+1],f[j-1]f[j−1] 改为 f[j]f[j]。

修改后 f[i+1]f[i+1] 表示把 \textit{arr}[0]arr[0] 到 \textit{arr}[i]arr[i] 这段做分隔变换后能够得到的元素最大和。此时 f[0]f[0] 就对应递归边界了。 

力扣代码

class Solution {
public:
    int maxSumAfterPartitioning(vector<int>& arr, int k) {
int n=arr.size(),f[k];
f[0]=0;
for(int i=0;i<n;i++)
{
	int b=0;
	int mx=0;
	for(int j=i;j>i-k&&j>=0;j--)
	{
		mx=max(mx,arr[j]);
		b=max(b,f[j%k]+(i-j+1)*mx);
	}
	f[(i+1)%k]=b;
 } 
 return f[n%k];
    }
};

 复习:二叉树搜索树

一、概念:

二叉搜索树又称二叉排序树,它有可能是一颗空树,也有可能具有以下性质

  • 若它的左子树不为空,则左子树上所有结点的值都小于空结点的值
  • 若它的右子树不为空,则右子树上所有结点的值都大于空结点的值
  • 它的左右子树也分别为二叉搜索树

二、二叉搜索树的构建

构建的过程其实就是插入的过程

void insert(int a)
{
	Node *temp=root;
	Node *pre=NULL;
	while(temp!=NULL)
	{
		pre=temp;
		if(a<temp->data)
		{
			temp=temp->left;
		}
		else if(a>temp->data)
		{
			temp=temp->right;
		}
		else
		{
			return ;
		}
	 }
	 if(a<pre->data)
	 {
	 	pre->left=(Node *)malloc(sizeof(Node));
	 	pre->left->data=a;
	 	pre->left->left=NULL;
	 	pre->left->right=NULL;
	  } 
	  else
	  {
	  	pre->right=(Node *)malloc(sizeof(Node));
	 	pre->right->data=a;
	 	pre->right->left=NULL;
	 	pre->right->right=NULL;
	  }
 } 

三、二叉搜索树的查找

它比无序查找遍历二叉树快很多

int search(Node *root,int a)
{
	while(root!=NULL)
	{
		if(a==root->data)
		{
			return 1;
		 } 
		else if(a<root->data)
		{
			root=root->left;
		}
		else
		{
			root=root->right;
		}
	}
	return 2;
}

四、删除

删除比插入和查找要复杂一点,需要分类讨论

  • 被删除节点为叶子节点
  • 被删除节点仅有一个孩子
  • 被删除节点左右孩子都在

代码如下

int deleta_tree(Node *node,int a)
{
	if(node==NULL)
	{
		return -1;
	}
	else
	{
		if(node->data==a)
		{
			//执行删除操作时,要先定位到被删除结点的前一个位置 
			Node *tempNode=pre_node(root,node,a);
			Node *temp=NULL;
			//若右子树为空,只需要重新连接结点,直接删除 
			if(node->right==NULL)
			{
				temp=node;
				node=node->left;
				if(tempNode->left->data==temp->data)
				{
					Node *free_node=temp;
					tempNode->left=node;
					free(free_node);
					free_node=NULL; 
				 } 
			}
			else
			{
				Node *free_node=temp;
				tempNode->right=node;
				free(free_node);
				free_noe=NULL;
			}
		}
		else//左右子树均不为空 
		{
			temp=node;
			Node *left_max=node;//找最大的的临时指针 
			left_max=left_max->left;//先找到左孩子节点
			while(left_max->right!=NULL)
			{
				temp=left_max;
				left_max=left_max->right;
			 } 
			 node->data=left_max->data;
			 if(temp!=node)
			 {
			 	temp->right=left_max->left;
			 	free(left_max);
			 	left_max=NULL;
			 }
			 else
			 {
			 	temp->left=left_max->left;
			 	free(left_max);
			 	left_max=NULL;
			 }
		}
	}
	else if(a<node->data)
	{
		delete_node(node->left,a);
	}
	else if(a>node->data)
	{
		delete_node(node->right,a);
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值