面试题15
牛客网链接
思路1:书中常规解法
class Solution {
public:
int NumberOf1(int n) {
int count=0;
int flag=1;
while(flag){
if (n & flag){
++count;
}
flag = flag<< 1;
//注意左移的时候要更新flag
//循环次数到flag不能左移为止,也就是int的长度,32位就是32次循环
}
return count;
}
};
思路2:
一个整数,减去1后再和原来的数位与,相当于把最右边的1变成0,这个方法循环次数是原整数里面1的个数
class Solution {
public:
int NumberOf1(int n) {
int count=0;
while(n){
++count;
n = n & (n-1);
}
return count;
}
};
能否把移位换成乘除:不能,移位效率高于乘除,尽可能移位代替乘除法。
位运算可以参考这个题解,位运算要考虑负数的表示。
面试题16
思路1:
暴力
class Solution {
public:
double Power(double base, int exponent) {
//base是double,exponent是int,所以要考虑exponent是负数和0的情况
if(exponent<0){
base = 1/base;
exponent = -exponent;
}
if(exponent==0){
//边界,0次方都返回1
return 1;
}
double result = 1.0;
while(exponent){
result = result * base;
exponent -= 1;
}
return result;
}
};
时间复杂度O(n),空间复杂度O(1)
参考题解
思路2:
快速幂
class Solution {
public:
double Power(double base, int exponent) {
//base是double,exponent是int,所以要考虑exponent是负数和0的情况
if(exponent<0){
base = 1/base;
exponent = -exponent;
}
if(exponent==0){
//边界,0次方都返回1
return 1;
}
double result = 1.0;
result = Power(base, exponent/2);
if(exponent & 1){
//奇数
//奇数和1位与是正数,偶数和1位与是0
result = result * result * base;
}
else{
result = result * result;
}
return result;
}
};
时间复杂度O(logn)
空间复杂度O(logn)
快速幂要背
非递归快速幂,空间复杂度O(1)
class Solution {
public:
double Power(double base, int exponent) {
//base是double,exponent是int,所以要考虑exponent是负数和0的情况
if(exponent<0){
base = 1/base;
exponent = -exponent;
}
if(exponent==0){
//边界,0次方都返回1
return 1;
}
double result = 1.0;
while(exponent){
if(exponent&1){
result*=base;
//1就乘进答案
}
base *= base;
exponent >>= 1;
}
return result;
}
};
相当于遍历n的二进制位,是1就乘进结果
面试题17
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param n int整型 最大位数
* @return int整型vector
*/
vector<int> printNumbers(int n) {
// write code here
long max = pow(10,n);
vector<int> result;
for(int i=1; i<max; ++i){
result.push_back(i);
}
return result;
}
};
面试题18
牛客网链接
牛客网此题和书上不同,这里按牛客网版本
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @param val int整型
* @return ListNode类
*/
ListNode* deleteNode(ListNode* head, int val) {
// write code here
ListNode* flag=new ListNode(-1);
//这里,新建节点的代码要记一下,不赋值的话会报错
//因为要删除的节点可能是head,所以先在head前加一个节点
flag->next = head;
if(head->val == val){
//这种单独判断head是不是等于val的方法其实不需要用一个flag
flag->next=head->next;
return flag->next;
}
while(flag->next){
if(flag->next->val==val){
flag->next=flag->next->next;
}
flag=flag->next;
}
return head;
}
};
面试题19
这题先要会递归解法,然后看懂官方题解的文字部分,再会写第一个。
dp写的最清楚的题解
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param str string字符串
* @param pattern string字符串
* @return bool布尔型
*/
bool match(string str, string pattern) {
string s=str, p=pattern;
int m=s.size(), n=p.size();
vector<vector<bool>> dp(m+1, vector<bool>(n+1, 0));
dp[0][0]=1;
for(int j=2; j<n+1; j+=2){
dp[0][j]=(dp[0][j-2] && p[j-1] == '*');
}
//初始化主要针对0行0列,0行已经处理过,0列其实p是空串的时候,s不空都是false,所以不用特别处理
//后面就从1行1列开始算了
for(int i=1;i<m+1;++i)
for(int j=1;j<n+1;++j){
if(p[j-1]=='*')
dp[i][j] = dp[i][j-2] ||
(dp[i-1][j] && s[i-1]==p[j-2]) ||
(dp[i-1][j] && p[j-2]=='.');
else
dp[i][j] = (dp[i-1][j-1] && s[i-1]==p[j-1]) ||
(dp[i-1][j-1] && p[j-1]=='.');
}
return dp[m][n];
}
};
题解链接
DP思路就是转移方程->初始条件,转移方程要不漏。
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param str string字符串
* @param pattern string字符串
* @return bool布尔型
*/
bool match(string str, string pattern) {
int n=str.size();
int m=pattern.size();
vector<vector<bool>> f(n+1, vector<bool>(m+1, 0));
//注意vector定义,初始化为全0
for(int i=0; i<=n; i++){
//0是判断空串的,实际上的字符比较是1 to n
for(int j=0; j<=m; j++){
if(j==0){
f[i][j]=(i==0);//i==0就是true,否则false
}
else{
if(pattern[j-1] != '*'){
if(i > 0 && (str[i-1] == pattern[j-1] || pattern[j-1] == '.')){
f[i][j]=f[i-1][j-1];
}
}
else{
//不看,即不是连续c
if(j>=2){
f[i][j] = f[i][j] || f[i][j-2];
}//这么写是因为可以先默认这个,再走下面流程
//f[i][j]就是str i长度,pattern j长度能否匹配上,能匹配上就是true
if(i>=1 && j>=2 && (str[i-1] == pattern[j-2] || pattern[j-2] == '.')){
f[i][j] = f[i][j] || f[i-1][j];// patter[j-2]是c,[j-1]是*
}
//看,是连续c,>=1就是不能动已经赋值的f[0][j]
}
}
}
}
return f[n][m];
}
};
递归解法
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param str string字符串
* @param pattern string字符串
* @return bool布尔型
*/
bool match(string str, string pattern) {
string s=str, p=pattern;
int m=s.size(), n=p.size();
if(n==0){
return m==0;
}
if(m==0){
if(n%2 !=1 ){
for(int i=1; i<n; i+=2){
if(p[i]!='*')
return false;
}
return true;
}
return false;
}
char c1=s[0], c2=p[0], c3='a';
if(n>1) c3=p[1];
if(c3 != '*'){
if(s[0]==p[0] || p[0]=='.')
return match(s.substr(1), p.substr(1));
else return false;
}
else{
if(match(s, p.substr(2))) return true;
else{
if(s[0]==p[0] || p[0]=='.')
return match(s.substr(1), p);
else return false;
}
}
//return false;
}
};
官方题解
官方题解里面 [&]就是匿名函数,写在外面也可以
这个match小函数,就是把’.'和==并到一起,因为这俩其实处理方法一样
面试题20
题解链接
输入输出分析:str的每一位,只能是数字,’.’,'±’两个一样,'eE’两个一样,空格,其余字符都是false,且空格必须在首尾,其余位置也是false
去掉首尾空格以后逐个扫描str,
数字:直接往后
e/E:前面不能有e/E,上一位要有数,把dotSeen置为false
. 前面不能有. 不能有e/E 后面必须是数字
± 只能0位或者e/E后面一位 且后面要是.或者数字
这个自己写的有冗余,对着返回报错逐个补逻辑改出来的。
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param str string字符串
* @return bool布尔型
*/
//输入输出分析:str的每一位,只能是数字,'.','+-'两个一样,'eE'两个一样,空格,其余字符都是false,且空格必须在首尾,其余位置也是false
//去掉首尾空格以后逐个扫描str,
//数字:直接往后
//e/E:前面不能有e/E,上一位要有数,把dotSeen置为false
//.:前面不能有. 不能有e/E 后面必须是数字
//+- 只能0位或者e/E后面一位 且后面要是.或者数字
bool isNumeric(string str) {
//先去掉首尾空格
if(str.size() == 0) return false;
str.erase(0, str.find_first_not_of(" "));
str.erase(str.find_last_not_of(" ")+1);
if(str.size() == 0) return false;
//然后遍历str
bool dotSeen = false;
bool eSeen = false;
bool numSeen = false;
for(int i=0; i<str.size(); ++i){
if(isdigit(str[i])){
numSeen=true;
}
else if(str[i]=='e' || str[i]=='E'){
dotSeen=false;
numSeen=true;
if(eSeen) return false;
if(i==0) return false;
if(i==str.size()-1) return false;
eSeen=true;
}
else if(str[i] == '.'){
if(dotSeen||eSeen) return false;
if(!numSeen && (i==str.size() || !isdigit(str[i+1]))) return false;
if(i!=str.size()-1 && !isdigit(str[i+1]) && str[i+1]!='e' && str[i+1]!='E') return false;
dotSeen=true;
}
else if(str[i]=='-'||str[i]=='+'){
if(i==str.size()-1) return false;
if(!isdigit(str[i+1]) && str[i+1]!='.') return false;
if(i!=0){
if(str[i-1]!='e' && str[i-1]!='E')
return false;
}
}
else return false;
}
return true;
}
};
面试题21
这题leetcode和书上一样,牛客和书上不一样,牛客多一个奇数偶数相对顺序不变,这里按牛客的写
牛客网链接
时间O(n) 空间O(n)
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param array int整型vector
* @return int整型vector
*/
vector<int> reOrderArray(vector<int>& array) {
// write code here
vector<int> ans(array.size(), 0);
int pos=0;
for(int i=0,j=0;i<array.size(); ++i){
if(array[i]%2){
ans[j++]=array[i];
}
pos=j;
}
for(int i=0,j=pos;i<array.size(); ++i){
if(array[i]%2==0){
ans[j++]=array[i];
}
}
return ans;
}
};
时间O(n^2) 空间O(1)
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param array int整型vector
* @return int整型vector
*/
vector<int> reOrderArray(vector<int>& array) {
// write code here
int i=0, j=0;//扫奇数,头插就可
//j是奇数位置,i是奇数插入后面的一个位置
while(j<array.size()){
if(array[j]%2){
int temp=array[j];
for(int k=j; k>i;k--){
//注意要从后往前,否则会覆盖住
array[k]=array[k-1];
}
array[i++]=temp;
}
j+=1;
}
return array;
}
};