“给定一个数组 求某一个连续子数组的和 ”从这里开始
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Test {//数组 求 某一个 连续子数组的和 nums[5] { 5,3,4,6,7} index = // 需要实际应用情况 //需要思考 :规定 index是下标 () [ ] ( ]的哪一种? 此代码约定 是其中的[] //以及相等的情况 class Program { public int[] nums; //构造函数中初始化 //类成员变量在构造函数中初始化是一种良好的实践, //因为它将初始化逻辑封装在类的实例化过程中,使代码更具可维护性和清晰性。 public Program() { nums = new int[5] { 5, 3, 4, 6, 7 }; } int Sum( int index1, int index2) { int i;// //判断index1 index2是否合法 if (index1 < 0 || index1 >= nums.Length || index2 < 0 || index2 >= nums.Length) { Console.WriteLine(" 无效的索引"); return 0; //or throw an exception } //如果index1 =index2 if (index1 > index2) //如果index1> index2 交换一下 { int temp = index2; index2 = index1; index1 = temp; } int sum = nums[index1]; //Console.WriteLine(sum+"我是for循环外的"); for (i = index1; i < index2; i++) { //Console.WriteLine(nums[i+1]); sum += nums[i + 1]; //Console.WriteLine(sum + "我是for循环里的"); } return sum; } static void Main(string[] args) { Program p = new Program(); //int nums = new int[5] { 5, 3, 4, 6, 7 }; p.nums = new int[5] { 5, 3, 4, 6, 7 }; int result = p.Sum(2,4); Console.WriteLine(result); Console.ReadKey(); } } }
//如果频繁调用同一个数组的,不同的子数组 如何优化??
可以使用字典使用字典(Dictionary)来缓存已计算的子数组和的结果是一种常见的优化方法,通常被称为"缓存"或"记忆化"。这样可以避免重复计算,提高程序的性能。
下面是一个简单的示例,展示如何使用字典进行优化:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Test {//数组 求 某一个 连续子数组的和 nums[5] { 5,3,4,6,7} index = // 实际应用情况 //规定 index是下标 () [ ] ( ] 中的[] //以及相等的情况 //如果频繁调用同一个数组的,子数组 如何优化 class Program { private int[] nums; private Dictionary<Tuple<int, int>, int> cache; public Program() { nums = new int[5] { 5, 3, 4, 6, 7 }; cache = new Dictionary<Tuple<int, int>, int>(); } int Sum( int index1, int index2) { // Check if the result is already in the cache Tuple<int, int> key = Tuple.Create(index1, index2); if(cache.ContainsKey(key)) { return cache[key]; } int i,sum; //判断index1 index2是否合法 if (index1 < 0 || index1 >= nums.Length || index2 < 0 || index2 >= nums.Length) { Console.WriteLine(" 无效的索引"); return 0; //or throw an exception } if (index1 > index2) //如果index1> index2 交换一下 { int temp = index2; index2 = index1; index1 = temp; } sum = nums[index1]; //如果index1 =index2 在for循环里直接跳过 for (i = index1; i < index2; i++) { sum += nums[i + 1]; } cache[key] = sum; return sum; } static void Main(string[] args) { Program p = new Program(); int result = p.Sum(2,4); Console.WriteLine(result); //对相同范围的后续调用将使用缓存的结果 int cachedResult = p.Sum(2, 4); Console.WriteLine(cachedResult); Console.ReadKey(); } } }
动态规划,
使用一个数组来存储中间结果,以减少重复计算和内存占用。设计和思考动态规划问题的关键在于确定状态、状态转移方程以及边界条件。
下面将解释如何设计和思考动态规划问题,以 Sum 问题为例:
确定状态: 首先,考虑问题的状态。在这个问题中,我们可以考虑定义状态 dp[i] 表示数组 nums 中前 i 个元素的和。
这样,问题的最终目标就是求解 dp[index2] 减去 dp[index1 - 1],即子数组和。
状态转移方程: 确定状态后,考虑状态之间的关系,即状态转移方程。
在这个问题中,我们可以得到状态转移方程为 dp[i] = dp[i - 1] + nums[i],表示当前状态 dp[i] 可以通过前一个状态 dp[i - 1] 加上当前元素 nums[i] 得到。
**边界条件: **考虑边界条件,即最简单的情况。
在这个问题中,dp[0] 表示数组中的第一个元素,即 dp[0] = nums[0]。
**初始化: **对于某些问题,可能需要在开始时初始化状态。
在这个问题中,我们在构造函数中初始化 dp 数组,保证了 dp[0] 的正确性。
**问题求解: **根据状态、状态转移方程和边界条件,可以编写出动态规划的代码,实现问题求解。
在代码中,通过查询 dp 数组,可以在常数时间内得到子数组和,提高了效率。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Test {//数组 求 某一个 连续子数组的和 nums[5] { 5,3,4,6,7} index = // 实际应用情况 //规定 index是下标 () [ ] ( ] 中的[] //以及相等的情况 //如果频繁调用同一个数组的,子数组 如何优化 //使用字典会占用额外的内存空间,考虑其他的优化方式 class Program { private int[] nums; private int[] dp; //定义状态 dp[i] 表示数组 nums 中前 i 个元素的和。 public Program() { nums = new int[5] { 5, 3, 4, 6, 7 }; dp = new int[nums.Length]; InitializeDP(); } private void InitializeDP() //边界问题 { dp[0] = nums[0]; //初始化 for (int i = 1; i < nums.Length; i++) { dp[i] = dp[i - 1] + nums[i]; //状态转移方程 } } int Sum(int index1, int index2) { //判断index1 index2是否合法 if (index1 < 0 || index1 >= nums.Length || index2 < 0 || index2 >= nums.Length) { Console.WriteLine(" 无效的索引"); return 0; //or throw an exception } if (index1 > index2) //如果index1> index2 交换一下 { int temp = index2; index2 = index1; index1 = temp; } if (index1 == 0) { return dp[index2]; } else //如果index1 大于等于1 那么 到后面的和 减去到前面的和 { return dp[index2] - dp[index1 - 1]; } } static void Main(string[] args) { Program p = new Program(); int result = p.Sum(2,4); Console.WriteLine(result); //对相同范围的后续调用将使用缓存的结果 int cachedResult = p.Sum(2, 4); Console.WriteLine(cachedResult); Console.ReadKey(); } } }