目录
面试题 04.05. 合法二叉搜索树
二叉搜索树 https://blog.csdn.net/nameofcsdn/article/details/114281344
面试题 05.04. 下一个数
下一个数。给定一个正整数,找出与其二进制表达式中1的个数相同且大小最接近的那两个数(一个略大,一个略小)。
示例1:
输入:num = 2(或者0b10)
输出:[4, 1] 或者([0b100, 0b1])
示例2:
输入:num = 1
输出:[2, -1]
提示:
num的范围在[1, 2147483647]之间;
如果找不到前一个或者后一个满足条件的正数,那么输出 -1。
itoa和atoi都是直接百度复制的,nextGreaterElement函数是从我另外一个题目代码复制过来略改的
https://blog.csdn.net/nameofcsdn/article/details/106915634
只需要改2个地方,一个是整数转化为二进制字符串,一个是二进制字符串转化为整数。
nextLesserElement函数是nextGreaterElement函数直接修改得到,代码逻辑是一样的。
char* itoa(int num,char* str,int radix) //copy from 百度百科
{/*索引表*/
char index[]="0123456789ABCDEF";
unsigned unum;/*中间变量*/
int i=0,j,k;
/*确定unum的值*/
if(radix==10&&num<0)/*十进制负数*/
{
unum=(unsigned)-num;
str[i++]='-';
}
else unum=(unsigned)num;/*其他情况*/
/*转换*/
do{
str[i++]=index[unum%(unsigned)radix];
unum/=radix;
}while(unum);
str[i]='\0';
/*逆序*/
if(str[0]=='-')
k=1;/*十进制负数*/
else
k=0;
for(j=k;j<=(i-1)/2;j++)
{ char temp;
temp=str[j];
str[j]=str[i-1+k-j];
str[i-1+k-j]=temp;
}
return str;
}
int atoi2(const char *nptr)
{
int c; /* current char */
int total; /* current total */
int sign; /* if '-', then negative, otherwise positive */
/* skip whitespace */
while ( isspace((int)(unsigned char)*nptr) )
++nptr;
c = (int)(unsigned char)*nptr++;
sign = c; /* save sign indication */
if (c == '-' || c == '+')
c = (int)(unsigned char)*nptr++; /* skip sign */
total = 0;
while (isdigit(c)) {
total = 2 * total + (c - '0'); /* accumulate digit */
c = (int)(unsigned char)*nptr++; /* get next char */
}
if (sign == '-')
return -total;
else
return total; /* return result, negated if necessary */
}
int nextGreaterElement(int n) {
char sn[40];
for(int i=0;i<32;i++)sn[i]=((n&(1<<31-i))?'1':'0');
sn[32]='\0';
int len=strlen(sn);
for(int i=len-2;i>=0;i--)
{
if(sn[i]>=sn[i+1])continue;
for(int j=len-1;j>i;j--)
{
if(sn[i]>=sn[j])continue;
sn[j]^=sn[i]^=sn[j]^=sn[i];
sort(sn+i+1,sn+len);
long long res = atoi2(sn);
if(res==int(res))return res;
return -1;
}
}
return -1;
}
int nextLesserElement(int n) {
char sn[40];
for(int i=0;i<32;i++)sn[i]=((n&(1<<31-i))?'1':'0');
sn[32]='\0';
int len=strlen(sn);
for(int i=len-2;i>=0;i--)
{
if(sn[i]<=sn[i+1])continue;
for(int j=len-1;j>i;j--)
{
if(sn[i]<=sn[j])continue;
sn[j]^=sn[i]^=sn[j]^=sn[i];
sort(sn+i+1,sn+len,greater<char>());
long long res = atoi2(sn);
if(res==int(res))return res;
return -1;
}
}
return -1;
}
class Solution {
public:
vector<int> findClosedNumbers(int num) {
vector<int> ans(2);
ans[1]=nextLesserElement(num);
ans[0]=nextGreaterElement(num);
return ans;
}
};
后来发现可以用c++的库函数获取上一个下一个全排列,就更简单了
//把整数转化为字符串
char* itoa(int num,char* str,int radix) //copy from 百度百科
{/*索引表*/
char index[]="0123456789ABCDEF";
unsigned unum;/*中间变量*/
int i=0,j,k;
/*确定unum的值*/
if(radix==10&&num<0)/*十进制负数*/
{
unum=(unsigned)-num;
str[i++]='-';
}
else unum=(unsigned)num;/*其他情况*/
/*转换*/
do{
str[i++]=index[unum%(unsigned)radix];
unum/=radix;
}while(unum);
str[i]='\0';
/*逆序*/
if(str[0]=='-') k=1;/*十进制负数*/
else k=0;
for(j=k;j<=(i-1)/2;j++)
{
char temp;
temp=str[j];
str[j]=str[i-1+k-j];
str[i-1+k-j]=temp;
}
return str;
}
//把字符串转化为整数
long long atoi(const char *nptr,int radix) //copy from somebody
{
while ( isspace((int)(unsigned char)*nptr) ) ++nptr;/* skip whitespace */
int c = (int)(unsigned char)*nptr++;
int sign = c; /* save sign indication */
if (c == '-' || c == '+') c = (int)(unsigned char)*nptr++; /* skip sign */
long long total = 0;
while (isdigit(c)) {
total = radix * total + (c - '0'); /* accumulate digit */
c = (int)(unsigned char)*nptr++; /* get next char */
}
if (sign == '-') return -total;
else return total; /* return result, negated if necessary */
}
int nextGreaterElement(int n) {
char sn[40];
for(int i=0;i<32;i++)sn[i]=((n&(1<<31-i))?'1':'0');
sn[32]='\0';
next_permutation(sn,sn+32);
long long res = atoi(sn,2);
if(res==int(res))return res;
return -1;
}
int nextLesserElement(int n) {
char sn[40];
for(int i=0;i<32;i++)sn[i]=((n&(1<<31-i))?'1':'0');
sn[32]='\0';
prev_permutation(sn,sn+32);
long long res = atoi(sn,2);
if(res==int(res))return res;
return -1;
}
class Solution {
public:
vector<int> findClosedNumbers(int num) {
vector<int> ans(2);
ans[1]=nextLesserElement(num);
ans[0]=nextGreaterElement(num);
return ans;
}
};
面试题 05.08. 绘制直线
题目:
绘制直线。有个单色屏幕存储在一个一维数组中,使得32个连续像素可以存放在一个 int 里。屏幕宽度为w,且w可被32整除(即一个 int 不会分布在两行上),屏幕高度可由数组长度及屏幕宽度推算得出。请实现一个函数,绘制从点(x1, y)到点(x2, y)的水平线。
给出数组的长度 length,宽度 w(以比特为单位)、直线开始位置 x1(比特为单位)、直线结束位置 x2(比特为单位)、直线所在行数 y。返回绘制过后的数组。
示例1:
输入:length = 1, w = 32, x1 = 30, x2 = 31, y = 0
输出:[3]
说明:在第0行的第30位到第31为画一条直线,屏幕表示为[0b000000000000000000000000000000011]
示例2:
输入:length = 3, w = 96, x1 = 0, x2 = 95, y = 0
输出:[-1, -1, -1]
代码:
class Solution {
public:
vector<int> drawLine(int length, int w, int x1, int x2, int y) {
vector<int>ans;
int s=x1/32+w/32*y,e=x2/32+w/32*y;
for(int i=0;i<s;i++)ans.insert(ans.end(),0);
for(int i=s;i<=e;i++)ans.insert(ans.end(),-1);
for(int i=e+1;i<length;i++)ans.insert(ans.end(),0);
x1=32-x1%32,x2=31-x2%32;
long long a=1;
ans[s]&=int((a<<x1)-1),ans[e]&=(-(1<<x2));
return ans;
}
};
面试题 30. 包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)。
示例:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.min(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.min(); --> 返回 -2.
提示:
各函数的调用总次数不超过 20000 次
class MinStack {
public:
stack<int>s;//主栈
stack<int>m;//单调栈
MinStack() {
}
void push(int x) {
s.push(x);
if(m.empty()||m.top()>=x)m.push(x);
}
void pop() {
if(m.top()==s.top())m.pop();
s.pop();
}
int top() {
return s.top();
}
int min() {
return m.top();
}
};
面试题 34. 二叉树中和为某一值的路径
题目:
给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径。
说明: 叶子节点是指没有子节点的节点。
示例:
给定如下二叉树,以及目标和 sum = 22,
5
/ \
4 8
/ / \
11 13 4
/ \ / \
7 2 5 1
返回:
[
[5,4,11,2],
[5,8,4,5]
]
代码:
class Solution {
public:
vector<vector<int>> pathSum(TreeNode* root, int sum) {
vector<int>tmp;
vector<vector<int>>ans;
if (!root)return ans;
if (!root->left && !root->right)
{
if (sum == root->val)
{
tmp.insert(tmp.end(), sum);
ans.insert(ans.end(), tmp);
}
return ans;
}
ans = pathSum(root->left, sum - root->val);
vector<vector<int>>ans2 = pathSum(root->right, sum - root->val);
for (int i = 0; i < ans2.size(); i++)
{
ans.insert(ans.end(), ans2[i]);
}
for (int i = 0; i < ans.size(); i++)
{
ans[i].insert(ans[i].begin(), root->val);
}
return ans;
}
};