“给定一个数组 求某一个连续子数组的和 ”从这里开始

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();
        }
    }
}


posted @ 2024-01-06 22:20  专心Coding的程侠  阅读(15)  评论(0编辑  收藏  举报