题目: 假设有N阶楼梯,每次可以从一个集合里面选择一种方法来爬楼梯,求爬楼梯的方法数目.
采用递归算法时,当楼梯总数为100时,就容易堆栈溢出,采用动态规划,不过还是极少的测试用例无法通过.
输入:int[] oneStep,每次可以选择的楼梯数,int stepsCount,楼梯总数.
输出:int 总共有多少种办法.
经历了大约5次的修改后,代码如下,因环境需要采用C#写的.
public int climbStairs(int[] oneStep, int stepsCount)
{
if (oneStep == null || oneStep.Length == 0 || stepsCount == 0)
{
return 0;
}
oneStep = Available(oneStep,stepsCount);
oneStep = Distinct(oneStep);
if (oneStep.Length == 0)
{
return 0;
}
if (oneStep.Length == 1 && (stepsCount % oneStep[0] == 0))
{
return 1;
}
else if (oneStep.Length == 1 && (stepsCount % oneStep[0] != 0))
{
return 0;
}
return getCount(oneStep, stepsCount);
}
public int getCount(int[] oneStep, int stepsCount)
{
int[] table = new int[stepsCount + 1];
for (int i = 0; i < oneStep.Length; i++)
{
table[oneStep[i]] = 1;
}
for (int i = 1; i < stepsCount + 1; i++)
{
int sum = 0;
for (int j = 0; j < oneStep.Length; j++)
{
if (i > oneStep[j])
{
sum += table[i - oneStep[j]];
}
if (i == oneStep[j])
{
sum += table[i];
}
}
table[i] = sum;
}
return table[stepsCount];
}
//计算出可用的台阶数
private int[] Available(int[] m,int n)
{
if (m == null || m.Length == 0)
{
return new int[0];
}
int size = 0 ;
foreach (int var in m)
{
if (var > 0 && var <= n)
size++;
}
int[] tem = new int[size];
int index=0;
foreach (int var in m)
{
if (var > 0 && var <= n)
tem[index++] = var;
}
return tem;
}
//对可选台阶去掉重复,排序
private int[] Distinct(int[] m)
{
if (m == null || m.Length == 0)
{
return new int[0];
}
Array.Sort(m);
int size = 1;
int index = 0;
for (int i = 1; i < m.Length; i++)
{
if (m[i - 1] != m[i])
size++;
}
int [] rd = new int[size];
rd[index++] = m[0];
for (int i = 1; i < m.Length; i++)
{
if (m[i - 1] != m[i])
rd[index++] = m[i];
}
return rd;
}