如果我们有n个步骤并且我们一次可以上升1个或2个步骤,则步数和爬行方式之间存在斐波纳契关系。 IF和ONLY,如果我们不计算2 + 1和1 + 2不同。
然而,这不再是这种情况,并且必须添加我们添加第三个选项,采取3个步骤。我该怎么做?
我有什么:
1 step = 1 way
2 steps = 2 ways: 1+1, 2
3 steps = 4 ways: 1+1+1, 2+1, 1+2, 3
我不知道从哪里可以找到n阶梯的路数
我得到7表示n = 4,14表示n = 5我得到14 + 7 + 4 + 2 + 1通过做之前所有组合的总和。所以n步的方式= n-1种方式+ n-2种方式+ .... 1种方式假设我保留了所有的值。 DYNAMIC编程。 1 2和3步将是正确的基础案例?
答案 0 :(得分:33)
我会说公式将以下列方式看待:
K(1) = 1
K(2) = 2
k(3) = 4
K(n) = K(n-3) + K(n-2) + K(n - 1)
公式说,为了达到第n步,我们必须首先达到:
K(4)= 7,K(5)= 13等。
您可以使用递归公式或使用动态编程。
答案 1 :(得分:11)
Python解决方案:
这是基于answer by Michael。这需要O(n)CPU和O(n)内存。
import functools
@functools.lru_cache(maxsize=None)
def recursive(n):
if n < 4:
initial = [1, 2, 4]
return initial[n-1]
else:
return recursive(n-1) + recursive(n-2) + recursive(n-3)
这是对这个答案的评论。这个tribonacci - 倍增解决方案类似于Nayuki solution中的双重algorithms斐波那契。请注意,乘法具有比常数更高的复杂度。这并不需要或从缓存中受益。
def recursive_doubling(n):
def recursive_tribonacci_tuple(n):
"""Return the n, n+1, and n+2 tribonacci numbers for n>=0.
Tribonacci forward doubling identities:
T(2n) = T(n+1)^2 + T(n)*(2*T(n+2) - 2*T(n+1) - T(n))
T(2n+1) = T(n)^2 + T(n+1)*(2*T(n+2) - T(n+1))
T(2n+2) = T(n+2)^2 + T(n+1)*(2*T(n) + T(n+1))
"""
assert n >= 0
if n == 0:
return 0, 0, 1 # T(0), T(1), T(2)
a, b, c = recursive_tribonacci_tuple(n // 2)
x = b*b + a*(2*(c - b) - a)
y = a*a + b*(2*c - b)
z = c*c + b*(2*a + b)
return (x, y, z) if n % 2 == 0 else (y, z, x+y+z)
return recursive_tribonacci_tuple(n)[2] # Is offset by 2 for the steps problem.
这是由answer by 太極者無極而生推动的。它是iterative fibonacci solution的修改后的tribonacci扩展。它是从tribonacci修改的,因为它返回c
,而不是a
。
def iterative(n):
a, b, c = 0, 0, 1
for _ in range(n):
a, b, c = b, c, a+b+c
return c
这是对这个答案的评论。这种修改的迭代tribonacci-by-doubleling解决方案来自相应的递归解决方案。有些背景,请参阅here和here。它是从tribonacci修改的,因为它返回c
,而不是a
。请注意,乘法的复杂度高于常数。
def iterative_doubling_l2r(n):
"""Return the n+2 tribonacci number for n>=0.
Tribonacci forward doubling identities:
T(2n) = T(n+1)^2 + T(n)*(2*T(n+2) - 2*T(n+1) - T(n))
T(2n+1) = T(n)^2 + T(n+1)*(2*T(n+2) - T(n+1))
T(2n+2) = T(n+2)^2 + T(n+1)*(2*T(n) + T(n+1))
"""
assert n >= 0
a, b, c = 0, 0, 1 # T(0), T(1), T(2)
for i in range(n.bit_length() - 1, -1, -1): # Left (MSB) to right (LSB).
x = b*b + a*(2*(c - b) - a)
y = a*a + b*(2*c - b)
z = c*c + b*(2*a + b)
bit = (n >> i) & 1
a, b, c = (y, z, x+y+z) if bit else (x, y, z)
return c
注意:
list(range(m - 1, -1, -1)) == list(reversed(range(m)))
这是对这个答案的评论。 n
的比特从右到左迭代,即LSB到MSB。这种方法可能不是规定性的。
def iterative_doubling_r2l(n):
"""Return the n+2 tribonacci number for n>=0.
Tribonacci forward doubling identities:
T(2n) = T(n+1)^2 + T(n)*(2*T(n+2) - 2*T(n+1) - T(n))
T(2n+1) = T(n)^2 + T(n+1)*(2*T(n+2) - T(n+1))
T(2n+2) = T(n+2)^2 + T(n+1)*(2*T(n) + T(n+1))
Given Tribonacci tuples (T(n), T(n+1), T(n+2)) and (T(k), T(k+1), T(k+2)),
we can "add" them together to get (T(n+k), T(n+k+1), T(n+k+2)).
Tribonacci addition formulas:
T(n+k) = T(n)*(T(k+2) - T(k+1) - T(k)) + T(n+1)*(T(k+1) - T(k)) + T(n+2)*T(k)
T(n+k+1) = T(n)*T(k) + T(n+1)*(T(k+2) - T(k+1)) + T(n+2)*T(k+1)
T(n+k+2) = T(n)*T(k+1) + T(n+1)*(T(k) + T(k+1)) + T(n+2)*T(k+2)
When n == k, these are equivalent to the doubling formulas.
"""
assert n >= 0
a, b, c = 0, 0, 1 # T(0), T(1), T(2)
d, e, f = 0, 1, 1 # T(1), T(2), T(3)
for i in range(n.bit_length()): # Right (LSB) to left (MSB).
bit = (n >> i) & 1
if bit:
# a, b, c += d, e, f
x = a*(f - e - d) + b*(e - d) + c*d
y = a*d + b*(f - e) + c*e
z = a*e + b*(d + e) + c*f
a, b, c = x, y, z
# d, e, f += d, e, f
x = e*e + d*(2*(f - e) - d)
y = d*d + e*(2*f - e)
z = f*f + e*(2*d + e)
d, e, f = x, y, z
return c
近似当然主要用于非常大的n
。使用取幂操作。注意,取幂的复杂性高于常数。
def approx1(n):
a_pos = (19 + 3*(33**.5))**(1./3)
a_neg = (19 - 3*(33**.5))**(1./3)
b = (586 + 102*(33**.5))**(1./3)
return round(3*b * ((1./3) * (a_pos+a_neg+1))**(n+1) / (b**2 - 2*b + 4))
上面的approximation被测试是正确的,直到n = 53,之后它不同。使用更高精度的浮点运算可能会在实践中产生更好的近似值。
def approx2(n):
return round((0.618363 * 1.8392**n + \
(0.029252 + 0.014515j) * (-0.41964 - 0.60629j)**n + \
(0.029252 - 0.014515j) * (-0.41964 - 0.60629j)**n).real)
上面的approximation被测试是正确的,直到n = 11,之后它不同。
答案 2 :(得分:3)
# recursion requirement: it returns the number of way up
# a staircase of n steps, given that the number of steps
# can be 1, 2, 3
def how_many_ways(n)
# this is a bit Zen like, if 0 steps, then there is 1 way
# and we don't even need to specify f(1), because f(1) = summing them up
# and so f(1) = f(0) = 1
# Similarly, f(2) is summing them up = f(1) + f(0) = 1 + 1 = 2
# and so we have all base cases covered
return 1 if n == 0
how_many_ways_total = 0
(1..3).each do |n_steps|
if n >= n_steps
how_many_ways_total += how_many_ways(n - n_steps)
end
end
return how_many_ways_total
end
0.upto(20) {|n| puts "how_many_ways(#{n}) => #{how_many_ways(n)}"}
def how_many_ways(n)
# this is a bit Zen like, if 0 steps, then there is 1 way
# if n is negative, there is no way and therefore returns 0
return 1 if n == 0
return 0 if n < 0
return how_many_ways(n - 1) + how_many_ways(n - 2) + how_many_ways(n - 3)
end
0.upto(20) {|n| puts "how_many_ways(#{n}) => #{how_many_ways(n)}"}
#
# from 0 to 27: recursive: 4.72 second
# iterative: 0.03 second
#
def how_many_ways(n)
arr = [0, 0, 1]
n.times do
new_sum = arr.inject(:+) # sum them up
arr.push(new_sum).shift()
end
return arr[-1]
end
0.upto(27) {|n| puts "how_many_ways(#{n}) => #{how_many_ways(n)}"}
how_many_ways(0) => 1
how_many_ways(1) => 1
how_many_ways(2) => 2
how_many_ways(3) => 4
how_many_ways(4) => 7
how_many_ways(5) => 13
how_many_ways(6) => 24
how_many_ways(7) => 44
how_many_ways(8) => 81
how_many_ways(9) => 149
how_many_ways(10) => 274
how_many_ways(11) => 504
how_many_ways(12) => 927
how_many_ways(13) => 1705
.
.
how_many_ways(22) => 410744
how_many_ways(23) => 755476
how_many_ways(24) => 1389537
how_many_ways(25) => 2555757
how_many_ways(26) => 4700770
how_many_ways(27) => 8646064
我喜欢@MichałKomorowski的解释和@rici的评论。我认为如果它取决于知道K(3) = 4
,那么它涉及手动计数。
答案 3 :(得分:2)
轻松获得问题的直觉:
认为你正在爬楼梯,你可以采取的步骤是1 & 2
总数没有。到达第4步的方法=总数没有。达到第3步的方法+达不到第2步的方法
如何?
基本上,只有两个可能的步骤,您可以从中到达第4步。
这两个是您进入第4步的唯一可能性
同样,只有两种可能的方式来达到第2步
F(n)= F(n-1)+ F(n-2)
F(0)= 0且F(1)= 1是基本情况。从这里开始建造F(2),F(3)等等。这类似于 Fibonacci系列。
如果增加了可能的步数,比如说[1,2,3],现在每一步都有一个选项,即你可以直接从它前面的三个步骤跳过
因此公式将成为
F(n)= F(n-1)+ F(n-2)+ F(n-3)
答案 4 :(得分:1)
计算使用步骤1,2,3到达n th 楼梯的方法。
我们可以使用简单的递归方法进行计数。
// Header File
#include<stdio.h>
// Function prototype for recursive Approch
int findStep(int);
int main(){
int n;
int ways=0;
ways = findStep(4);
printf("%d\n", ways);
return 0;
}
// Function Definition
int findStep(int n){
int t1, t2, t3;
if(n==1 || n==0){
return 1;
}else if(n==2){
return 2;
}
else{
t3 = findStep(n-3);
t2 = findStep(n-2);
t1 = findStep(n-1);
return t1+t2+t3;
}
}
答案 5 :(得分:1)
def count(steps):
sol = []
sol.append(1)
sol.append(1 + sol[0])
sol.append(1 + sol[1] + sol[0])
if(steps > 3):
for x in range(4, steps+1):
sol[(x-1)%3] = sum(sol)
return sol[(steps-1)%3]
答案 6 :(得分:0)
我的解决方案是在java中。 我决定自下而上解决这个问题。
我从一个空数组的当前路径开始[]
每个步骤我将添加所有可能的步长{1,2,3}
第一步[] - &gt; [[1],[2],[3]]
第二步[[1],[2],[3]] - &gt; [[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1] [3,2],[3 ,3]]
迭代0:[]
迭代1:[[1],[2],[3]]
迭代2:[[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2] ],[3,3]] 迭代3 [[1,1,1],[1,1,2],[1,1,3] ....]
序列长度如下 1 2 3 五 8 13 21
我的步骤功能称为构建
public class App {
public static boolean isClimedTooHigh(List<Integer> path, int maxSteps){
int sum = 0;
for (Integer i : path){
sum+=i;
}
return sum>=maxSteps;
}
public static void modify(Integer x){
x++;
return;
}
/// 1 2 3
/// 11 12 13
/// 21 22 23
/// 31 32 33
///111 121
public static boolean build(List<List<Integer>> paths, List<Integer> steps, int maxSteps){
List<List<Integer>> next = new ArrayList<List<Integer>>();
for (List<Integer> path : paths){
if (isClimedTooHigh(path, maxSteps)){
next.add(path);
}
for (Integer step : steps){
List<Integer> p = new ArrayList<Integer>(path);
p.add(step);
next.add(p);
}
}
paths.clear();
boolean completed = true;
for (List<Integer> n : next){
if (completed && !isClimedTooHigh(n, maxSteps))
completed = false;
paths.add(n);
}
return completed;
}
public static boolean isPathEqualToMax(List<Integer> path, int maxSteps){
int sum = 0;
for (Integer i : path){
sum+=i;
}
return sum==maxSteps;
}
public static void calculate( int stepSize, int maxSteps ){
List<List<Integer>> paths = new ArrayList<List<Integer>>();
List<Integer> steps = new ArrayList<Integer>();
for (int i =1; i < stepSize; i++){
List<Integer> s = new ArrayList<Integer>(1);
s.add(i);
steps.add(i);
paths.add(s);
}
while (!build(paths,steps,maxSteps));
List<List<Integer>> finalPaths = new ArrayList<List<Integer>>();
for (List<Integer> p : paths){
if (isPathEqualToMax(p, maxSteps)){
finalPaths.add(p);
}
}
System.out.println(finalPaths.size());
}
public static void main(String[] args){
calculate(3,1);
calculate(3,2);
calculate(3,3);
calculate(3,4);
calculate(3,5);
calculate(3,6);
calculate(3,7);
return;
}
}
答案 7 :(得分:0)
这是使用动态编程的 O ( N k )Java实现:
N (4) (4,3) (4,3,2) (4,3,2,1)
1 0 0 0 1
2 0 0 1 2
3 0 1 1 3
4 1 1 2 5
5 0 0 1 6
6 0 1 3 9
7 0 1 2 11
8 1 1 4 15
9 0 1 3 18
10 0 1 5 23
11 0 1 4 27
12 1 2 7 34
13 0 1 5 39
..
..
99 0 9 217 7803
100 8037
这个想法是从左到右一次填写下表1列:
#banner {
background-image: url(../images/2000%20x%20150_Bubble_Final_Crop.jpg);
height: 150px;
}
body {
width: 1200px;
}
h1 {
color: #FFFFFF;
padding-top: 25px;
font-family: Cambria, "Hoefler Text", "Liberation Serif",
Times, "Times New Roman", serif;
font-size: 58pt;
text-shadow: 2px 2px 24px #D7DC23;
text-align: center;
}
.container-fluid {
margin: 0 auto;
}
答案 8 :(得分:0)
通过1,2和3步计算覆盖距离的总方式。
递归解时间复杂度是指数的,即O(3n)。
由于再次解决了相同的子问题,因此该问题具有重叠的子问题属性。因此,最小平方和问题具有动态规划问题的两个属性。
List<EffectList> contactList;
Context context;
private LayoutInflater mInflater;
// Constructors
public MyContactAdapter1(Context context, List<EffectList> objects) {
super(context, 0, objects);
this.context = context;
this.mInflater = LayoutInflater.from(context);
contactList = objects;
}
@Override
public EffectList getItem(int position) {
return contactList.get(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final MyContactAdapter1.ViewHolder1 vh;
if (convertView == null) {
View view = mInflater.inflate(R.layout.get_layout_row_view, parent, false);
vh = MyContactAdapter1.ViewHolder1.create((RelativeLayout) view);
view.setTag(vh);
} else {
vh = (MyContactAdapter1.ViewHolder1) convertView.getTag();
}
EffectList item = getItem(position);
// vh.textViewName.setText(item.getEffectsId());
vh.textViewName.setText(item.getEffectsName());
vh.textViewEmail.setText(item.getEffectsId());
// Picasso.with(context).load(item.getProfilePic()).placeholder(R.mipmap.ic_launcher).error(R.mipmap.ic_launcher).into(vh.imageView);
return vh.rootView;
}
private static class ViewHolder1 {
public final RelativeLayout rootView;
public final ImageView imageView;
public final TextView textViewName;
public final TextView textViewEmail;
private ViewHolder1(RelativeLayout rootView, ImageView imageView, TextView textViewName, TextView textViewEmail) {
this.rootView = rootView;
this.imageView = imageView;
this.textViewName = textViewName;
this.textViewEmail = textViewEmail;
}
public static MyContactAdapter1.ViewHolder1 create(RelativeLayout rootView) {
ImageView imageView = (ImageView) rootView.findViewById(R.id.imageView);
TextView textViewName = (TextView) rootView.findViewById(R.id.textViewName);
TextView textViewEmail = (TextView) rootView.findViewById(R.id.textViewEmail);
return new MyContactAdapter1.ViewHolder1(rootView, imageView, textViewName, textViewEmail);
}
}
我的博客文章:
http://javaexplorer03.blogspot.in/2016/10/count-number-of-ways-to-cover-distance.html
答案 9 :(得分:0)
基于递归memoization的C ++解决方案: 你问一个楼梯我们有多少方法可以登顶?如果它不是最顶层的楼梯,它会询问所有邻居并总结并返回结果。如果它是最顶层的楼梯,它会说1。
vector<int> getAllStairsFromHere(vector<int>& numSteps, int& numStairs, int currentStair)
{
vector<int> res;
for(auto it : numSteps)
if(it + currentStair <= numStairs)
res.push_back(it + currentStair);
return res;
}
int numWaysToClimbUtil(vector<int>& numSteps, int& numStairs, int currentStair, map<int,int>& memT)
{
auto it = memT.find(currentStair);
if(it != memT.end())
return it->second;
if(currentStair >= numStairs)
return 1;
int numWaysToClimb = 0;
auto choices = getAllStairsFromHere(numSteps, numStairs, currentStair);
for(auto it : choices)
numWaysToClimb += numWaysToClimbUtil(numSteps, numStairs, it, memT);
memT.insert(make_pair(currentStair, numWaysToClimb));
return memT[currentStair];
}
int numWaysToClimb(vector<int>numSteps, int numStairs)
{
map<int,int> memT;
int currentStair = 0;
return numWaysToClimbUtil(numSteps, numStairs, currentStair, memT);
}
答案 10 :(得分:0)
以下是使用1,2和3步骤的几种方法
1: 1
2: 11 2
3: 111 12 21 3
4: 1111 121 211 112 22 13 31
5: 11111 1112 1121 1211 2111 122 212 221 113 131 311 23 32
6: 111111 11112 11121 11211 12111 21111 1113 1131 1311 3111 123 132 312 321 213 231 33 222 1122 1221 2211 1212 2121 2112
所以根据上面的组合,soln应该是:
K(n) = K(n-3) + K(n-2) + K(n - 1)
k(6) = 24 which is k(5)+k(4)+k(3) = 13+7+4
答案 11 :(得分:0)
基于Michał's answer的Java递归实现:
public class Tribonacci {
// k(0) = 1
// k(1) = 1
// k(2) = 2
// k(3) = 4
// ...
// k(n) = k(n-3) + k(n-2) + k(n - 1)
static int get(int n) {
if (n == 0) {
return 1;
} if (n == 1) {
return 1;
} else if (n == 2) {
return 2;
//} else if (n == 3) {
// return 4;
} else {
return get(n - 3) + get(n - 2) + get(n - 1);
}
}
public static void main(String[] args) {
System.out.println("Tribonacci sequence");
System.out.println(Tribonacci.get(1));
System.out.println(Tribonacci.get(2));
System.out.println(Tribonacci.get(3));
System.out.println(Tribonacci.get(4));
System.out.println(Tribonacci.get(5));
System.out.println(Tribonacci.get(6));
}
}
答案 12 :(得分:-4)
也许它只是2 ^(n-1),其中n是步数?
这对我来说很有意义,因为有4个步骤,你有8种可能性:
4,
3+1,
1+3,
2+2,
2+1+1,
1+2+1,
1+1+2,
1+1+1+1,
我猜这是模式