1. 另类加法
给定两个int A和B。编写一个函数返回A+B的值,但不得使用+或其他算数运算符。
1.1 思路
1. 拿到这个题的首先立马反应到了数电的全加器 用一个与门和一个异或门,来做全加器。
2. 进位的话用移位操作符,整体的话可以循环也可以递归来做。
1.2 代码实现
class UnusualAdd {
public:
int addAB(int A, int B) {
// write code here
// 这样子来理解就是数电里面的一位全加器
if(A == 0)
{
return B;
}
if(B == 0)
{
return A;
}
//本位和
int a = A ^ B;
//进位
int b = (A & B) << 1;
return addAB(a, b);
}
};
2. 两种排序方法
描述:考拉有n个字符串字符串,任意两个字符串长度都是不同的。考拉最近学习到有两种字符串的排序方法: 1.根据字符串的字典序排序。例如:
"car" < "carriage" < "cats" < "doggies < "koala"
2.根据字符串的长度排序。例如:
"car" < "cats" < "koala" < "doggies" < "carriage"
考拉想知道自己的这些字符串排列顺序是否满足这两种排序方法,考拉要忙着吃树叶,所以需要你来帮忙验证。
输入描述:输入第一行为字符串个数n(n ≤ 100) 接下来的n行,每行一个字符串,字符串长度均小于100,均由小写字母组成
输出描述:如果这些字符串是根据字典序排列而不是根据长度排列输出"lexicographically",
如果根据长度排列而不是字典序排列输出"lengths",
如果两种方式都符合输出"both",否则输出"none"
2.1 思路
1. 这就是纯纯的翻译题,你把他的整个的过程搞清楚,加上判断条件就可以做出来了。
2.2 代码实现
#include<iostream>
#include<string>
#include<vector>
using namespace std;
bool len (const vector<string> &v)
{
for(size_t i = 1;i < v.size();++i)
{
if(v[i - 1].size() >= v[i].size())
{
return false;
}
}
return true;
}
bool lex (const vector<string> &v)
{
for(size_t i = 1;i < v.size();++i)
{
if(v[i - 1] >= v[i])
{
return false;
}
}
return true;
}
int main()
{
int n = 0;
cin >> n;
vector<string> v;
v.resize(n);
for(auto &e : v)
{
cin >> e;
}
if(len(v) && !lex(v))
{
cout << "lengths" << endl;
}
else if(!len(v) && lex(v))
{
cout << "lexicographically" << endl;
}
else if(len(v) && lex(v))
{
cout << "both" << endl;
}
else if(!len(v) && !lex(v))
{
cout << "none" << endl;
}
}
3. 走方格的格数
描述:请计算n*m的棋盘格子(n为横向的格子数,m为竖向的格子数)从棋盘左上角出发沿着边缘线从左上角走到右下角,总共有多少种走法,要求不能走回头路,即:只能往右和往下走,不能往左和往上走。注:沿棋盘格之间的边缘线行走
数据范围: 1 \le n,m \le 8 \1≤n,m≤8
输入描述:输入两个正整数n和m,用空格隔开。(1≤n,m≤8)
输出描述:输出一行结果
3.1 思路
1. 这个题就很经典,一看就是dp ,把一次次结果记下来放在dp表里面就好了。
2. 牛客这个题就很简单你看他的给的数字的范围m小于8,用递归来做就好了。
3. leetcode那个题给的测试样例还是很大的,用这个递归肯定是超时的。
递归:用递归的首先就是两件事情
1. 你得想清楚递归出口,啥时候结束,比如这个题的话就是当行和列就剩一行的时候肯定也就是只剩一种走的方法了直接走就好了,开始把这个方法return 回去。
2. 还有就是我们是怎么拆分子问题的。这个题就是要知道我走到本格的时候只要知道走到我的上 和 左有几种方法两个一加和就可以了,顺着这个思路我们来翻译一下。
3.2 代码实现
int uniquePaths1(int m, int n){
if(m == 0 || n == 0){
return 1;
}
return uniquePaths1(m - 1,n) + uniquePaths1(m,n - 1);
}
int main()
{
int m,n;
cin >> m >> n;
cout << uniquePaths1(m,n) << endl;
}
4. 不同路径
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。问总共有多少条不同的路径?
4.1 思路
1. 首先这个题就是永不了暴力递归了我们怎么将暴力递归改成动态规划呢
2.为啥刚刚开始给边上那一行或者列是1呢 你想想 就一行或者一列 你从头到尾走下去那不就是一种走法,你的dp[ i ][ j ] 依靠的是 dp[ i - 1 ][ j ] + dp[ i ][ j - 1 ] ,写dp表的时候一加就好了
4.2 代码实现
class Solution {
public:
int uniquePaths(int m, int n) {
int dp[m][n];
for(int i = 0;i < m;i++)
{
dp[i][0] = 1;
}
for(int j = 0;j < n;j++)
{
dp[0][j] = 1;
}
for(int i = 1;i < m;i++)
{
for(int j = 1;j < n;j++)
{
dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[m - 1][n - 1];
}
};
5. 井字棋
描述:给定一个二维数组board,代表棋盘,其中元素为1的代表是当前玩家的棋子,0表示没有棋子,-1代表是对方玩家的棋子。当一方棋子在横竖斜方向上有连成排的及获胜(及井字棋规则),返回当前玩家是否胜出。测试样例:[[1,0,1],[1,-1,-1],[1,-1,0]] 返回:true
5.1 思路
1. 穷举出两个对角线加上三行三列,加以判断即可。
5.2 代码实现
class Board {
public:
bool checkWon(vector<vector<int> > board) {
// write code here
if(board[0][0] + board[1][1] + board[2][2] == 3)
{
return true;
}
if(board[0][2] + board[1][1] + board[2][0] == 3)
{
return true;
}
for(int i = 0;i < 3; i++)
{
if(board[i][0] + board[i][1] + board[i][2] == 3)
{
return true;
}
if(board[0][i] + board[1][i] + board[2][i] == 3)
{
return true;
}
}
return false;
}
};
那要是这个题变成不是3 * 3的格子呢咋办嘞?
这就是一下的方法
class Board{
public:
bool checkWon(vector<vector<int> > board) {
int row = board.size();
int sum = 0;
int i,j;
for(i = 0; i < row;i++)
{
sum = 0;
for(j = 0; j < row;j++)
{
sum += board[i][j];
}
if(sum == row)
{
return true;
}
}
for(i = 0; i < row;i++)
{
sum = 0;
for(j = 0; j < row;j++)
{
sum += board[j][i];
}
if(sum == row)
{
return true;
}
}
sum = 0;
for(i = 0;i < row;i++)
{
sum += board[i][i];
if(sum == row)
{
return true;
}
}
sum = 0;
for(i = 0;i < row;i++)
{
sum += board[i][row - 1 - i];
if(sum == row)
{
return true;
}
}
return false;
}
};
6. 求最大连续bit数
描述:求一个int类型数字对应的二进制数字中1的最大连续数,例如3的二进制为00000011,最大连续2个1数据范围:数据组数:1\le t\le 5\1≤t≤5 ,1\le n\le 500000\1≤n≤500000 进阶:时间复杂度:O(logn)\O(logn) ,空间复杂度:O(1)\O(1)
输入描述:输入一个int类型数字
输出描述:输出转成二进制之后连续1的个数
6.1 思路
1. 把二进制每一位取出来,设置一个count计数器来看有几个1.
2. 用max函数来进行迭代。
6.2 代码实现
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int n,count,temp,maxcount;
cin >> n;
for(int i = 31;i >= 0;--i)
{
if((n >> i) & 1)
{
++count;
maxcount = max(count,maxcount);
}
else
{
count = 0;
}
}
cout << maxcount << endl;
}
7. 最近公共祖先
描述:将一棵无穷大满二叉树的结点按根结点一层一层地从左往右编号,根结点编号为1。现给定a,b为两个结点。设计一个算法,返回a、b最近的公共祖先的编号。注意其祖先也可能是结点本身。
7.1 思路
1. 本题是一个满二叉树 根节点等于左孩子除于2的。
2. 所以如果a != b,就让其中的较大数除以2, 如此循环直到a == b 即是原来两个数的最近公共祖先 比如: 2和7的最近公共祖先:7/2 = 3 ---> 3/2 = 1, 2/2 = 1, 得到1为它们的公共祖先。
7.2 代码实现
class LCA {
public:
int getLCA(int a, int b) {
while (a != b)
{
if (a > b)
{
a >>= 1;
}
else
{
b >>= 1;
}
}
return a;
}
};