Fibonacci数列
描述
Fibonacci数列是这样定义的:
F[0] = 0
F[1] = 1
for each i ≥ 2: F[i] = F[i-1] + F[i-2]
因此,Fibonacci数列就形如:0, 1, 1, 2, 3, 5, 8, 13, ...,在Fibonacci数列中的数我们称为Fibonacci数。给你一个N,你想让其变为一个Fibonacci数,每一步你可以把当前数字X变为X-1或者X+1,现在给你一个数N求最少需要多少步可以变为Fibonacci数。
输入描述:
输入为一个正整数N(1 ≤ N ≤ 1,000,000)
输出描述:
输出一个最小的步数变为Fibonacci数"
示例1
输入:15
输出:2
解题思路:题目说最少多少步可以让目标值变成一个fibonacci数列,这个时候就要明确一个问题了,那就是把这个数变成fib数一定是通过一直加1或者一直减1来完成的,因为如果是加一部分,在减一部分那么就相当于在做来回的循环过程,这个是没有意义的。当明确了一定是通过一直加1或者一直减1的方法让他变成fib数列之后,那么只需要知道给出的这个值在哪两个数之间即可。所以可以定义一个数组,然后把1-1000000之间的fib数全部记录在数组中,然后用两端的值减掉输入的值,取最小就可以得出最终结果。由于这个地方只需要知道前两个值然后就可以知道第三个值,那么可以使用滚动不记录的方式,来得出输入的值在哪两个数之间。
下面是具体代码:
#include <iostream>
using namespace std;
int n;
int main()
{
cin >> n;
int a = 0, b = 1, c = 1;
//当最右侧的值大于输入的值的时候,就需要接着往下找
while(n > c)
{
//滚动数组的形式
a = b;
b = c;
c = a + b;
}
cout << min(c - n, n - b) << endl;
return 0;
}
单词搜索
描述
给出一个二维字符数组和一个单词,判断单词是否在数组中出现,
单词由相邻单元格的字母连接而成,相邻单元指的是上下左右相邻。同一单元格的字母不能多次使用。
数据范围:
0 < 行长度 <= 100
0 < 列长度 <= 100
0 < 单词长度 <= 1000
例如:
给出的数组为["XYZE","SFZS","XDEE"]时,
对应的二维字符数组为:
若单词为"XYZZED"时,应该返回 true,
也即:
若单词为"SEE"时,应该返回 true,
也即:
若单词为"XYZY"时,应该返回 false。
解题思路:分析题目上下左右可以用两个数组来实现 int dx[4]={0,0,1,-1};int dy[4]={1,-1,0,0};又因为同一单元格的字母不能够多次使用,所以要用一个数组来记录已经遍历过的值,当遍历了之后如果发现这个位置不是想要的结果值,那么就要把这个位置重新设置为没有被遍历过,这样可以方便以后其他位置来进行遍历。
下面是具体实现的代码
class Solution
{
int m, n;
bool vis[101][101] = { 0 };
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
public:
bool exist(vector<string>& board, string word)
{
m = board.size(), n = board[0].size();
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
if(board[i][j] == word[0])
{
//这个地方为什么要判断呢?是因为判断当前这个位置的值是否可以遍历完word这个单词
//如果可以,就返回true.这个位置不可以,就接着看board里面的其他位置
if(dfs(board, i, j, word, 0)) return true;
}
}
}
//当所有的位置都不能找到的时候,就返回false;
return false;
}
bool dfs(vector<string>& board, int i, int j, string& word, int pos)
{
if(pos == word.size() - 1)
{
//递归出口,已经遍历到最后一个相等的单词了,那么就可以找到
return true;
}
//记录已经遍历过的值
vis[i][j] = true;
for(int k = 0; k < 4; k++)
{
int a = i + dx[k], b = j + dy[k];
if(a >= 0 && a < m && b >= 0 && b < n && !vis[a][b] && board[a][b] == word[pos+1])
{
if(dfs(board, a, b, word, pos + 1)) return true;
}
}
//如果把i,j位置的上下左右都遍历完了之后,还没有返回true,那就表明这个位置进行dfs找不到word
//那这次遍历就是无效的,所以把当前遍历过的值改为没有被遍历,方便后续其他位置根据上下左右来
//访问这个值
vis[i][j] = false;
return false;
}
};
杨辉三角
描述
KiKi知道什么叫杨辉三角之后对杨辉三角产生了浓厚的兴趣,他想知道杨辉三角的前n行,请编程帮他解答。杨辉三角,本质上是二项式(a+b)的n次方展开后各项的系数排成的三角形。其性质包括:每行的端点数为1, 一个数也为1;每个数等于它左上方和上方的两数之和。
输入描述:
第一行包含一个整数数n。 (1≤n≤30)
输出描述:
包含n行,为杨辉三角的前n行,每个数输出域宽为5。
示例1
输入:6
输出:
1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 1 5 10 10 5 1
解题思路:通过观察可知,除了每行的第一个和最后一个是1之外,那么其他位置的值都是
通过公式v[i][j]=v[i-1][j]+v[i-1][j-1]而来,那么我们只需要设置一个二维数组,在进行二维数组填写的时候,只需要填写下三角就可以了。然后打印也是同样如此,打印出下三角就能够满足结果。
下面是具体代码:
#include <iostream>
using namespace std;
//用一个数组来记录,这里用的是下标为0的位置来隐射成下标为1的位置
//全局的数组直接自动全部填写的是0
int dp[31][31];
int main()
{
int n;
cin >> n;
dp[1][1] = 1;
for(int i = 2; i <= n; i++)
{
//j<=i是用来控制只填写下三角的值
for(int j = 1; j <= i; j++)
{
dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1];
}
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= i; j++)
{
//题目要求每个值之间是5个域的间隔,所以用%sd
printf("%5d", dp[i][j]);
}
printf("\n");
}
return 0;
}