当前位置: 首页 > news >正文

做网站公众号百度开发者平台

做网站公众号,百度开发者平台,建网是什么,.net网站开发怎么发布给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 输入:height [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图&#xf…

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 
输入:height = [4,2,0,3,2,5]
输出:9

自己写的

 public class Solution

 {

     public int Trap(int[] height)

     {

         int[] Theleft=new int[height.Length];

         int[] Therightside=new int[height.Length];

         int[] res=new int[height.Length];

         int result = 0;

         int left=Theleft[0];

         int right = Therightside[Therightside.Length - 1];

         for (int i = 0; i < height.Length; i++)

         {

             if (left <= height[i])

             {

                 Theleft[i] = 0;

                 left = height[i];

             }

             else

             {

                 Theleft[i] = left - height[i] ;

                 

             }

         }

         for (int i = height.Length-1; i >= 0; i--)

         {

             if (right <= height[i])

             {

                 Therightside[i] = 0;

                 right = height[i];

             }

             else

             {

                 Therightside[i] = right - height[i];

                 

             }

         }

         for (int i = 0; i < height.Length; i++)

         {

             res[i]= Math.Min(Theleft[i], Therightside[i]);

         }

         for (int i = 0; i < res.Length; i++)

         {

             result=result + res[i];

         }

         return result;

     }

 }

空间复杂度比较高 和官方的第一个题解一样

方法一:动态规划
对于下标 i,下雨后水能到达的最大高度等于下标 i 两边的最大高度的最小值,下标 i 处能接的雨水量等于下标 i 处的水能到达的最大高度减去 height[i]。

朴素的做法是对于数组 height 中的每个元素,分别向左和向右扫描并记录左边和右边的最大高度,然后计算每个下标位置能接的雨水量。假设数组 height 的长度为 n,该做法需要对每个下标位置使用 O(n) 的时间向两边扫描并得到最大高度,因此总时间复杂度是 O(n 
2
 )。

上述做法的时间复杂度较高是因为需要对每个下标位置都向两边扫描。如果已经知道每个位置两边的最大高度,则可以在 O(n) 的时间内得到能接的雨水总量。使用动态规划的方法,可以在 O(n) 的时间内预处理得到每个位置两边的最大高度。

创建两个长度为 n 的数组 leftMax 和 rightMax。对于 0≤i<n,leftMax[i] 表示下标 i 及其左边的位置中,height 的最大高度,rightMax[i] 表示下标 i 及其右边的位置中,height 的最大高度。

显然,leftMax[0]=height[0],rightMax[n−1]=height[n−1]。两个数组的其余元素的计算如下:

当 1≤i≤n−1 时,leftMax[i]=max(leftMax[i−1],height[i]);

当 0≤i≤n−2 时,rightMax[i]=max(rightMax[i+1],height[i])。

因此可以正向遍历数组 height 得到数组 leftMax 的每个元素值,反向遍历数组 height 得到数组 rightMax 的每个元素值。

在得到数组 leftMax 和 rightMax 的每个元素值之后,对于 0≤i<n,下标 i 处能接的雨水量等于 min(leftMax[i],rightMax[i])−height[i]。遍历每个下标位置即可得到能接的雨水总量。

 但是官方的双指针更优化

方法三:双指针
动态规划的做法中,需要维护两个数组 leftMax 和 rightMax,因此空间复杂度是 O(n)。是否可以将空间复杂度降到 O(1)?

注意到下标 i 处能接的雨水量由 leftMax[i] 和 rightMax[i] 中的最小值决定。由于数组 leftMax 是从左往右计算,数组 rightMax 是从右往左计算,因此可以使用双指针和两个变量代替两个数组。

维护两个指针 left 和 right,以及两个变量 leftMax 和 rightMax,初始时 left=0,right=n−1,leftMax=0,rightMax=0。指针 left 只会向右移动,指针 right 只会向左移动,在移动指针的过程中维护两个变量 leftMax 和 rightMax 的值。

当两个指针没有相遇时,进行如下操作:

使用 height[left] 和 height[right] 的值更新 leftMax 和 rightMax 的值;

如果 height[left]<height[right],则必有 leftMax<rightMax,下标 left 处能接的雨水量等于 leftMax−height[left],将下标 left 处能接的雨水量加到能接的雨水总量,然后将 left 加 1(即向右移动一位);

如果 height[left]≥height[right],则必有 leftMax≥rightMax,下标 right 处能接的雨水量等于 rightMax−height[right],将下标 right 处能接的雨水量加到能接的雨水总量,然后将 right 减 1(即向左移动一位)。

当两个指针相遇时,即可得到能接的雨水总量。

下面用一个例子 height=[0,1,0,2,1,0,1,3,2,1,2,1] 来帮助读者理解双指针的做法。

 

class Solution {public int trap(int[] height) {int ans = 0;int left = 0, right = height.length - 1;int leftMax = 0, rightMax = 0;while (left < right) {leftMax = Math.max(leftMax, height[left]);rightMax = Math.max(rightMax, height[right]);if (height[left] < height[right]) {ans += leftMax - height[left];++left;} else {ans += rightMax - height[right];--right;}}return ans;}
}

关于动态规划的介绍

动态规划(Dynamic Programming,简称DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学等领域中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。

动态规划经常用于求解具有重叠子问题和最优子结构性质的问题。这里的“重叠子问题”是指在递归算法中反复出现的问题,而“最优子结构”是指问题的最优解包含其子问题的最优解。

动态规划的关键步骤:

  1. 识别子问题:将问题分解为小的子问题,这些子问题往往是原问题的规模较小的版本。

  2. 确定状态:定义问题的解状态,通常用变量表示,例如 dp[i]

  3. 确定状态转移方程:找出状态之间的关系,即当前状态是如何由之前的一个或多个状态推导出来的。

  4. 确定初始状态和边界条件:确定状态转移的起点,即基本情况或边界条件。

  5. 确定求解策略:是自底向上(从最小的子问题开始解决)还是自顶向下(递归地解决)。

  6. 构造最优解:根据子问题的解构造原问题的解。

动态规划的常见应用:

  • 斐波那契数列:计算第n个斐波那契数。
  • 背包问题:在不超过背包容量的前提下,选择物品以最大化价值。
  • 最长公共子序列:找出两个序列的最长公共子序列。
  • 最短路径问题:如贝尔曼-福特算法解决带负权边的最短路径问题。
  • 矩阵链乘问题:计算矩阵乘法的最少操作次数。
  • 编辑距离问题:计算两个字符串之间的最小编辑距离。

示例:斐波那契数列的动态规划解法

斐波那契数列是一个典型的动态规划问题,其递归解法存在大量重复计算。动态规划解法如下:

  1. 状态定义dp[i] 表示斐波那契数列的第 i 个数。
  2. 状态转移方程dp[i] = dp[i-1] + dp[i-2]
  3. 初始状态dp[0] = 0dp[1] = 1
  4. 循环计算:从 2 到 n,依次计算 dp[i]
using System;class Program
{// 动态规划计算斐波那契数列的第n项static long Fibonacci(int n){if (n <= 1)return n;long[] dp = new long[n + 1];dp[0] = 0;dp[1] = 1;for (int i = 2; i <= n; i++){dp[i] = dp[i - 1] + dp[i - 2];}return dp[n];}static void Main(){int n = 10; // 计算斐波那契数列的第10项long result = Fibonacci(n);Console.WriteLine($"Fibonacci of {n} is {result}");}
}

动态规划是一种非常强大的方法,可以显著提高算法的效率,特别是在解决具有重复子问题和最优子结构的问题时。

http://www.wangmingla.cn/news/108935.html

相关文章:

  • opkg 做网站的包叫什么名字关键字广告
  • 建筑材料网站建设如何进行网络推广
  • 网站 子域名网站制作论文
  • 深圳 公司网站建设搜索引擎的优化方法有哪些
  • 青岛网站建设有限公司网站收录软件
  • 广州市网站建设网络营销策划方案怎么做
  • 旅游网站建设的背景长沙靠谱的关键词优化
  • 厦门网站建设公司排行榜seo关键字优化技巧
  • 什么网站做批发凉席电脑优化软件推荐
  • 好学校平台网站模板下载不了郑州网站顾问
  • 淘宝客网站怎么建设中国去中心化搜索引擎
  • 如何建立购物网站沈阳seo排名优化推广
  • 作图网站做课程表搜索优化引擎
  • 帮忙做简历的网站怎么在百度上推广产品
  • 国际网站卖东西怎么做可以推广的软件有哪些
  • 杭州营销型网站怎么做已矣seo排名点击软件
  • 如何做网站编辑代码seo诊断分析工具
  • 商务网站设计方案陕西网络营销优化公司
  • 做视频网站成本高吗如何进行搜索引擎的优化
  • 企业网站提交站长之家源码
  • 如何查看一个网站是什么程序做的黄山网站seo
  • 天津建设银行招聘网站班级优化大师网页版
  • 做网站会员金字塔系统爱站网长尾关键词挖掘
  • 自适应网站一般用什么框架做竞价托管哪家便宜
  • 一般网站用什么技术做的网站推广服务
  • vue做移动端网站与pc端有什么区别seo三人行网站
  • 怎么用手机做抖音上最火的表白网站今日头条收录入口
  • 上海seo服务南京seo培训
  • 广州外贸网站建设开发免费网站的平台
  • 第三方经营的b2b网站学历提升