Fibonacci数列
题目地址: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数"
题目解析
题目为基础的fibonacci数列的应用,其后续数组皆可推导出来,推导公式为:F[i] = F[i-1] + F[i-2]。
我们也可以直接定义常数来模拟其推导过程。
代码及解释展示
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
//a代表f[0],b代表f[1],c代表f[0]+f[1]
int a=0,b=1,c=1;
//后续a代表f[i-2],b代表f[i-1],c代表f[i-2]+f[i-1]
while(n > c)
{
a = b;//a向后挪一位
b = c;//b向后挪一位
c = a + b;//f[i-1] + f[i-2]
}
//当脱离while时,c已经大于n,并且满足条件f[i-1] <= n <= f[i]
//接下来我们要找n距离f[i-1]与f[i]之间的最小距离
cout << min(c - n,n - b) << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
单词搜索
题目地址:单词搜索
描述
给出一个二维字符数组和一个单词,判断单词是否在数组中出现,
单词由相邻单元格的字母连接而成,相邻单元指的是上下左右相邻。同一单元格的字母不能多次使用。
数据范围:
0 < 行长度 <= 100
0 < 列长度 <= 100
0 < 单词长度 <= 1000
例如:
给出的数组为["XYZE","SFZS","XDEE"]时,对应的二维字符数组为:
若单词为"XYZZED"时,应该返回 true,也即:
若单词为"SEE"时,应该返回 true,也即:
若单词为"XYZY"时,应该返回 false。
解题思路
本题为搜索问题,通过对周围的搜索进行条件验证,可用深度优先搜索(DFS),或广度优先搜索(BFS)进行搜索。
代码及解释展示
dfs代码
#include <vector>
class Solution {
public:
int m,n;
bool exist(vector<string>& board, string word) {
// write code here
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])
{
if(dfs(board,i,j,word,1))return true;
}
}
}
return false;
}
//走过的路就标记为true,防止反复走同一个位置
bool vis[105][105];
//dx和dy用于控制方向
int dx[5] = { 0, 0,-1, 1};
int dy[5] = { 1,-1, 0, 0};
//设置dfs函数
//i和j代表位置,word表示当前的字符,pos代表有多少个符合答案字符串的字符数量
bool dfs(vector<string>& board,int i,int j, string& word,int pos)
{
//dfs出口,当pos满足字数,即返回true
if(pos == word.size())return true;
//当前位置设置为true,防止后续再次重复走当前位置
vis[i][j] = true;
for(int k=0;k<4;k++)
{
//让i,j分别加上dx,dy对应的值即可控制下一个位置的上下左右
int a = i + dx[k],b = j + dy[k];
//开始进行判断
//a,b的判断是防止越出边界
//vis[a][b]是为了判断该位置是否走过
//board的判断是为了判断a,b位置的字母是否符合条件
if(a >= 0 && a < m && b >= 0 && b < n && !vis[a][b] && board[a][b] == word[pos])
{
//dfs开始递推
if(dfs(board,a,b,word,pos+1))return true;
}
}
//复原当前位置,在未出答案前,防止影响下一位置代码运行
vis[i][j] = false;
return false;
}
};
bfs代码
#include <vector>
#include <queue>
#include <tuple>
using namespace std;
class Solution {
public:
int m, n;
bool exist(vector<string>& board, string word) {
if (word.empty()) return true;
m = board.size();
if (m == 0) return false;
n = board[0].size();
//用于控制上下左右
int dx[4] = {0, 0, -1, 1};
int dy[4] = {1, -1, 0, 0};
// BFS队列,存储内容为:行, 列, 当前匹配位置, 访问状态
queue<tuple<int, int, int, vector<vector<bool>>>> q;
// 初始化队列,找到所有单词首字母的位置
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (board[i][j] == word[0]) {
vector<vector<bool>> visited(m, vector<bool>(n, false));
visited[i][j] = true;
q.push({i, j, 1, visited});
// 如果单词只有一个字符
if (word.size() == 1) {
return true;
}
}
}
}
// BFS主循环
while (!q.empty()) {
auto [i, j, pos, visited] = q.front();
q.pop();
// 探索四个方向
for (int k = 0; k < 4; k++) {
int a = i + dx[k];
int b = j + dy[k];
// 检查边界、访问状态和字符匹配
if (a >= 0 && a < m && b >= 0 && b < n && !visited[a][b] && board[a][b] == word[pos]) {
// 如果已经匹配完所有字符
if (pos + 1 == word.size()) {
return true;
}
// 创建新的访问状态
vector<vector<bool>> new_visited = visited;
new_visited[a][b] = true;
// 加入队列
q.push({a, b, pos + 1, new_visited});
}
}
}
return false;
}
};
杨辉三角
题目地址:杨辉三角
描述
杨辉三角形,又称帕斯卡三角形,第 i+1 行是二项式展开
的系数。
三角形中任意元素等于上一行同列元素与上一行前一列元素之和。
下面给出杨辉三角形的前 4 行:
1
1 1
1 2 1
1 3 3 1
给定正整数n,请输出杨辉三角形的前n行。
输入描述
在一行输入一个整数 n(1≦n≦34)。
输出描述
输出杨辉三角形的前 n 行。每一行从该行第一个元素开始,依次输出;每两个数之间用一个空格分隔。请不要在行末输出多余的空格。
题目解析
如果我们把第二行第二列我们可以看作dp[1][1],剩余的对应其该对应的位置,可以看到,未存在实数的值全用0代替:
0 0 0 0 0 0
0 1 0 0 0 0
0 1 1 0 0 0
0 1 2 1 0 0
0 1 3 3 1 0
仔细观察我们可以使用公式:dp[ i ][ j ] = dp[ i-1 ][ j ] + dp[ i-1][ j-1],即使是杨辉三角的边界也变成1+0=1。
代码及解释展示
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
//用long long是为了防止过大报错
long long dp[40][40] = {0};
//直接赋值给dp[1][1] = 1即可
//后续使用dp[i][j] = dp[i-1][j] + dp[i-1][j-1]都可推导出
dp[1][1] = 1;
for(int i=2;i<=n;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++)
{
cout<<dp[i][j];
if(j!=i)
cout<<" ";
}
cout<<endl;
}
return 0;
}
// 64 位输出请用 printf("%lld")
今天的学习到此结束\\\\٩( 'ω' )و ////


