变态跳台阶
题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
class Solution {
public:
int jumpFloorII(int number) {
vector<int>cur(number + 1, 0);
vector<vector<int> > dp(number + 1, cur);
int sum = 0;
for (int i = 1; i <=number; i++)
{
dp[1][i] = 1;
}
for (int time = 2; time <= number; time++) {
for (int step = time; step <= number; step++) {
if (time == step)
dp[time][step] = dp[time - 1][step - 1];
else {
dp[time][step] = dp[time - 1][step - 1] + dp[time][step - 1];
}
}
}
for (int i = 1; i <= number; i++) {
sum += dp[i][number];
}
return sum;
}
};
矩形覆盖
题目描述
我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
#include<iostream>
using namespace std;
class Solution {
public:
int rectCover(int number) {
if (number == 0)
return 0;
if (number == 1)
return 1;
else if (number == 2) {
return 2;
}
/*else
return rectCover(number - 1) + rectCover(number - 2);*/
int k = 2, a = 1, b = 2, res;
while (k < number) {
res = a + b;
a = b;
b = res;
k++;
}
return res;
}
};
int main() {
Solution *sol = new Solution();
cout << sol->rectCover(3);
std::cin.get();
return 0;
}
可以先横着放,也可以先竖着放
二进制中1的个数
题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
#include<iostream>
#include<string>
#include<bitset>
using namespace std;
class Solution {
public:
int NumberOf1(int n) {
return bitset<32>(n).count();
}
};
bitset用法:
https://www.cnblogs.com/magisk/p/8809922.html
bitset<8> foo ("10011011"); cout << foo.count() << endl; //5 (count函数用来求bitset中1的位数,foo中共有5个1 cout << foo.size() << endl; //8 (size函数用来求bitset的大小,一共有8位 cout << foo.test(0) << endl; //true (test函数用来查下标处的元素是0还是1,并返回false或true,此处foo[0]为1,返回true cout << foo.test(2) << endl; //false (同理,foo[2]为0,返回false cout << foo.any() << endl; //true (any函数检查bitset中是否有1 cout << foo.none() << endl; //false (none函数检查bitset中是否没有1 cout << foo.all() << endl; //false (all函数检查bitset中是全部为1
树的子结构
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<map>
using namespace std;
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
class Solution {
public:
bool dfs(TreeNode* pRoot1, TreeNode* pRoot2, bool flag) {
if (pRoot1 != NULL && pRoot2 == NULL)
return false;
if (pRoot1 == NULL &&pRoot2!=NULL)
return false;
if (pRoot1 == NULL && pRoot2 == NULL)
return true;
if (pRoot1->val == pRoot2->val) {
if (pRoot2->left == NULL && pRoot2->right == NULL)
return true;
flag = true;
if (dfs(pRoot1->left, pRoot2->left, flag) && dfs(pRoot1->right, pRoot2->right, flag))
return true;
else {
flag = false;
return dfs(pRoot1->left, pRoot2, flag) || dfs(pRoot1->right, pRoot2,flag);
}
}
else {
if (flag)
return false;
else
return dfs(pRoot1->left, pRoot2, flag) || dfs(pRoot1->right, pRoot2, flag);
}
}
bool HasSubtree(TreeNode* pRoot1, TreeNode* pRoot2)
{
bool flag = false;
return dfs(pRoot1, pRoot2, false);
}
};
二叉树中和为某一值的路径
输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)
class Solution {
public:
vector<vector<int> >res;
//bool cmp(const vector<int> &a, const vector<int> &b) {
// int as = a.size();
// int bs = b.size();
// return as > bs;
//}
void dfs(TreeNode *root,vector<int> stack,int sum,int expectNumber) {
if (root == NULL)return;
stack.push_back(root->val);
sum += root->val;
if (sum > expectNumber)
return;
else if(root->left ==NULL && root->right==NULL && sum == expectNumber)
{
res.push_back(stack);
return;
}
dfs(root->left, stack, sum, expectNumber);
dfs(root->right, stack, sum, expectNumber);
sum -= root->val;
stack.pop_back();
}
vector<vector<int> > FindPath(TreeNode* root, int expectNumber) {
vector<int> stack;
int sum = 0;
dfs(root, stack, sum, expectNumber);
sort(res.begin(), res.end(), [](const vector<int> &a, const vector<int> &b) {return a.size() > b.size(); });
return res;
}
};
最小的K个数 - trick
题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
最小k个数-->建立大小为k的大根堆
最大k个数-->建立大小为k的小根堆
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
class Solution {
public:
void swap(vector<int> &v, int a, int b) {
int tmp = v[a];
v[a] = v[b];
v[b] = tmp;
}
void downAdjust(int i, vector<int> &v, int len) { //建最大堆,遍历v[k]~v[v.size()-1],只要小于堆顶就把堆顶(top[0])替换掉
int largest, left, right;
while (i < len) {
largest = i;
left = 2 * i + 1;
right = 2 * i + 2;
if (right >= len && left >= len)break;
if (left<len && v[left]>v[i]) {
largest = left;
}
if (right<len &&v[right]>v[largest]) {
largest = right;
}
if (largest != i) {
swap(v, largest, i);
i = largest;
}
else
break;
}
}
void buildHeap(vector<int> &v) {
int len = v.size();
for (int i = len / 2 - 1; i >= 0; i--) {
downAdjust(i, v, len);
}
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> res;
int len = input.size();
if (len == 0 || k > len || k == 0)return res;
vector<int> top(k, 0);
for (int i = 0; i < k; i++)
{
top[i] = input[i];
}
buildHeap(top);
for (int i = k; i < input.size(); i++)
{
if (input[i] < top[0]) {
top[0] = input[i];
downAdjust(0, top, k);
}
}
return top;
}
};
int main() {
Solution *sol = new Solution();
vector<int> input = { 3 };
vector<int> top = sol->GetLeastNumbers_Solution(input, 0);
for (int i = 0; i < top.size(); i++)
{
cout << top[i] << endl;
}
std::cin.get();
return 0;
}
丑数 - trick
题目描述
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
超时代码:
class Solution {
public:
bool judge(int x) {
//if (x == 1)return true;
while (x % 2 == 0)
x /= 2;
while (x % 3 == 0)
x /= 3;
while (x % 5 == 0)
x /= 5;
if (x == 1)return true;
else
return false;
}
int GetUglyNumber_Solution(int index) {
int k = 0;
int i = 0;
while (k<index)
{
i++;
if (judge(i)) {
k++;
}
}
return i ;
}
};
AC代码:
class Solution {
public:
int GetUglyNumber_Solution(int index) {
if (index < 7)return index;
vector<int>res(index, 0);
res[0] = 1;
int t2 = 0, t3 = 0, t5 = 0;
for (int i = 1; i < index; i++) {
res[i] = min(res[t2] * 2, min(res[t3] * 3, res[t5] * 5));
if (res[i] == res[t2] * 2)t2++;
if (res[i] == res[t3] * 3)t3++;
if (res[i] == res[t5] * 5)t5++;
}
return res[index - 1];
}
};
参考:https://www.nowcoder.com/questionTerminal/6aa9e04fc3794f68acf8778237ba065b
把数组排成最小的数 - trick
题目描述
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
using namespace std;
class Solution {
public:
string PrintMinNumber(vector<int> numbers) {
vector<string> res;
for (int i = 0; i < numbers.size(); i++)
{
res.push_back(to_string(numbers[i]));
}
sort(res.begin(), res.end(), [](string a, string b) {return a + b < b + a; });
string str;
for (int i = 0; i < res.size(); i++)
{
str += res[i];
}
return str;
}
};
int main() {
Solution sol;
vector<int> v = { 3,32,321 };
cout << sol.PrintMinNumber(v) << endl;
cin.get();
}
整数中1出现的次数(从1到n整数中1出现的次数)--trick
暴力解法:
class Solution {
public:
int num1(int x) {
string str = to_string(x);
int cnt = 0;
for (int i = 0; i < str.size(); i++)
{
if (str[i] == '1')
cnt++;
}
return cnt;
}
int NumberOf1Between1AndN_Solution(int n)
{
int sum = 0;
for (int i = 1; i <= n; i++)
{
sum += num1(i);
}
return sum;
}
};
找规律:
class Solution {
public:
int getLenOfNum(int n) {
int len = 0;
while (n != 0) {
len++;
n /= 10;
}
return len;
}
int NumberOf1Between1AndN_Solution(int n)
{
if (n < 1)
return 0;
int len = getLenOfNum(n);
if (len == 1)
return 1;
int tmp = (int)pow(10, len - 1);
int first = n / tmp;
int firstOneNum = first == 1 ? n % tmp + 1 : tmp;
int otherOneNUm = first * (len - 1) * (tmp / 10);
return firstOneNum + otherOneNUm + NumberOf1Between1AndN_Solution(n % tmp);
}
};
二叉搜索树与双向链表 -- trick
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
通过一个pre指针来记录上一个节点,然后中序遍历
参考代码:https://www.nowcoder.com/questionTerminal/947f6eb80d944a84850b0538bf0ec3a5
链接:https://www.nowcoder.com/questionTerminal/947f6eb80d944a84850b0538bf0ec3a5
来源:牛客网
class Solution {
public:
TreeNode* Convert(TreeNode* pRootOfTree)
{
if(pRootOfTree == nullptr) return nullptr;
TreeNode* pre = nullptr;
convertHelper(pRootOfTree, pre);
TreeNode* res = pRootOfTree;
while(res ->left)
res = res ->left;
return res;
}
void convertHelper(TreeNode* cur, TreeNode*& pre)
{
if(cur == nullptr) return;
convertHelper(cur ->left, pre);
cur ->left = pre;
if(pre) pre ->right = cur;
pre = cur;
convertHelper(cur ->right, pre);
}
};
我的代码,记录左右标记
class Solution {
public:
TreeNode *link(TreeNode *root, bool is_left) {
if (root == NULL)return root;
if (root->left == NULL && root->right == NULL) return root;
root->left = link(root->left, true);
if (root->left != NULL)
root->left->right = root;
root->right = link(root->right, false);
if (root->right != NULL)
root->right->left = root;
TreeNode *cur = root;
if (!is_left) {
while (cur->left != NULL)
cur = cur->left;
}
else {
while (cur->right != NULL)
cur = cur->right;
}
return cur;
}
TreeNode* Convert(TreeNode* pRootOfTree)
{
bool is_left = true;
if (pRootOfTree == NULL)return NULL;
pRootOfTree->left = link(pRootOfTree->left, is_left);
if (pRootOfTree->left != NULL)
pRootOfTree->left->right = pRootOfTree;
pRootOfTree->right = link(pRootOfTree->right, !is_left);
if (pRootOfTree->right != NULL)
pRootOfTree->right->left = pRootOfTree;
while (pRootOfTree->left != NULL) {
pRootOfTree = pRootOfTree->left;
}
return pRootOfTree;
}
};
按之字形顺序打印二叉树 -- trick
两个stack分别记录奇数层和偶数层
请实现一个函数按照之字形打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右至左的顺序打印,第三行按照从左到右的顺序打印,其他行以此类推。
class Solution{
public:
vector<vector<int> > Print(TreeNode* pRoot) {
vector<vector<int> > res;
if (!pRoot)return res;
stack<TreeNode*> s1;
stack<TreeNode*> s2;
s1.push(pRoot);
while (!s1.empty() || !s2.empty()) {
vector<int>cur;
while(!s1.empty()) {
TreeNode *w = s1.top();
cur.push_back(w->val);
s1.pop();
if (w->left) {
s2.push(w->left);
}
if (w->right) {
s2.push(w->right);
}
}
if (!cur.empty()) {
res.push_back(cur);
cur.clear();
}
while (!s2.empty()) {
TreeNode *w = s2.top();
cur.push_back(w->val);
s2.pop();
if (w->right) {
s1.push(w->right);
}
if (w->left) {
s1.push(w->left);
}
}
if (!cur.empty()) {
res.push_back(cur);
cur.clear();
}
}
return res;
}
};