LeetCode: Burst Balloons C#
Some things come to mind when I read your code. 

There is a nice feature on arrays in C# called CopyTo(). It gives you the possibility to copy an array without using a loop. Like so:

int[] newNums = new int[n];
nums.CopyTo(newNums, 1); 
newNums[0] = newNums[n-1] = 1; //This line I really like. 


There is also something called a multidimensional Array which basically does the same thing as int[][]. This gives you the possibility to do this:

int[,] memo = new int[n,n];


Use them together and you can remove all your loops from int maxcoins. 

Regarding your actual work method Burst I would say that you make things rather confusing. When debugging, the first thing that happens is that you cache a number series which is not allowed until 3 balloons are popped. It adds [0][1][5] to the cache. A more reasonable approach would have been [0][1][2] then [0][1][3] up to [0][1][5]. After that switch to [0][2][3] etc.  When you reach [0][4][5] you start over at [1][2][3].

To do that you would have to create nested loops in your Burst method:

        for (int i = left+1; i &lt; right; ++i)
        {
            for(int j = i+1; j&lt;= right; ++j)
                ans = Math.Max(ans, numbers[left] * numbers[i] * numbers[j]
                                + Burst(memo, numbers, left, i)
                                + Burst(memo, numbers, i, j));
        }


However, there is an even more simple approach to this problem and that is to actually pop the balloons in the array. This can be done easiest with a list instead of an array. But both are possible. So what you would do is to create a new set of balloons after each pop. So here caching is out of the question because you never really know what range you processed before. And to be honest I guess it would most likely slow down the process and make the code harder to read. I use the same variable names as you but in reality I would name nums and numbers as balloons and newNumbers would be named remainingBalloons. I did however change the variable i to baloonToPop to make it easier to understand what it represents. I left the adding of the ones in the code because it simplifies the Burst method. 

    public void MaxCoins(List&lt;int&gt; nums)
    {
        nums.Insert(0, 1); //Add the ones to the array
        nums.Add(1);
        int result = Burst(nums);
    }

    private int Burst(List&lt;int&gt; numbers)
    {
        int result = 0;
        for (int baloonToPop = 1; baloonToPop &lt; numbers.Count-1; baloonToPop++)
        {
            List&lt;int&gt; newNumbers = new List&lt;int&gt;();
            newNumbers.AddRange(numbers);
            newNumbers.RemoveAt(baloonToPop);
            int sumFromBaloonPop = numbers[baloonToPop - 1] * numbers[baloonToPop] * numbers[baloonToPop + 1];
            result = Math.Max(result, Burst(newNumbers) + sumFromBaloonPop);
        }
        return result;
    }


To do it with an array (in case there is a library restriction) you would have to create a new Array and then copy Subranges from the initial one instead of creating a copy of the List using AddRange + RemoveAt as above: 

int[] newNumbers = new int[numbers.Length-1];
Array.ConstrainedCopy(numbers, 0, newNumbers, 0, baloonToPop);
Array.ConstrainedCopy(numbers, baloonToPop + 1, newNumbers, baloonToPop, numbers.Length - (baloonToPop + 1));