剑指offer习题集

时间:2023-03-09 03:27:37
剑指offer习题集

1.重载赋值运算符函数:(具体见代码)

//普通做法
CMyString& CMyString::operator=(const CMyString& str)
{
if (this == &str)
return *this; delete[] m_Pdata;
m_Pdata = new char[strlen(str.m_Pdata)+];
strcpy(m_Pdata,str.m_Pdata); return *this;
} //更加安全的做法,普通做法在new内存不足情况下,已经将原值delete
CMyString& CMyString::operator=(const CMyString& str)
{
if (this != &str)
{
CMyString strTemp(str); char* temp = str.m_Pdata;
//通过strTemp的析构函数delete掉原值
strTemp.m_Pdata = m_Pdata;
m_Pdata = temp;
} return *this;
}

2.替换字符串中的空白字符

瞎了,做了一遍结果还是出错。。。确实要多练练

class Solution {
public:
//length为数组容量
void replaceSpace(char *str,int length) { if(length<=||str==NULL) return; int i=,n_blank=,n_str=,n_strlength=;
while(str[i]!='\0'){
++n_str; if(' '==str[i])
++n_blank; ++i;
} n_strlength=n_str+n_blank*;
if(n_strlength>length) return; int n1=n_str,n2=n_strlength;
while(n1>=&&n2>n1){
if(str[n1]==' '){
str[n2--]='';
str[n2--]='';
str[n2--]='%';
}else{
str[n2--]=str[n1];
} --n1;
}
}
};

3.使用两个栈模仿队列

class Solution
{
public:
void push(int node) {
stack1.push(node);
} int pop() {
int temp; if(stack2.size()<=){
while(stack1.size()>){
temp=stack1.top();
stack2.push(temp);
stack1.pop();
}
} if(stack2.size()<=)
return ; temp=stack2.top();
stack2.pop();
return temp;
} private:
stack<int> stack1;
stack<int> stack2;
};

4.改进的斐波那契数列

class Solution {
public:
int Fibonacci(int n) { if(n<=) return ; if(==n||==n) return ; long long n1=,n2=,n3=;
for(int i=;i<n;i++){
n3=n1+n2;
n1=n2;
n2=n3;
}
return n3;
}
};

5.实数的整数次方

class Solution {
public:
double Power(double base, int exponent) { //防止0作为底数
if(equal(base,0.0)){
if(==exponent) return 1.0;
else return 0.0;
} //针对0次方做的特殊处理
if(==exponent) return 1.0;
else if(==exponent) return base; double res;
bool sign=exponent<?true:false; if(sign){
return 1.0/PowerD(base,-*exponent);
}else{
return PowerD(base,exponent);
}
} bool equal(const double &a,const double &b){
if(fabs(a-b)<1e-)
return true;
return false;
} double PowerD(double base,int exponent){ if(==exponent) return base;
else if(==exponent) return 1.0; double res=PowerD(base,exponent/);
res*=res;
if(exponent&0x01==){ //判断是否是奇数次方
res*=base;
}
return res;
}
};

6.求链表的倒数第k个节点

/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) { if(NULL==pListHead||k==) return NULL; int i=k;
ListNode *t1=pListHead,*t2=pListHead; while(i!=&&t1!=NULL){
--i;
t1=t1->next;
} if(i!=) return NULL; while(t1!=NULL){
t1=t1->next;
t2=t2->next;
}
return t2;
}
};

7.包含min函数的栈

class Solution {
public:
void push(int value) { m_data.push(value); if(m_min.size()==){
m_min.push(value);
}else{
if(value<m_min.top())
m_min.push(value);
else m_min.push(m_min.top());
}
}
void pop() {
if(m_data.size()>){
m_data.pop();
m_min.pop();
}
}
int top() {
if(m_data.size()>)
return m_data.top();
}
int min() {
if(m_min.size()>)
return m_min.top();
} private:
stack<int> m_data;
stack<int> m_min;
};

8.给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法。

vector<int> multiply(const vector<int>& A) {

        int i,len=A.size(),temp=;
vector<int> res;
if(len<=) return res; res.push_back();
for(i=;i<len;i++){
res.push_back(res[i-]*A[i-]);
} for(i=len-;i>=;i--){
temp*=A[i+];
res[i]*=temp;
} return res;
}

此题没怎么注意代码的鲁棒性,后续可以补充。

9.一个链表中包含环,请找出该链表的环的入口结点。

ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(pHead==NULL) return NULL; //找到环中节点
ListNode *p1=MeetListNode(pHead),*p2;
if(p1==NULL) return NULL; //计算链表中环的节点个数
int i,n=;
p2=p1->next;
while(p2!=p1){
++n;
p2=p2->next;
} //寻找链表中环的入口节点
p1=pHead;p2=pHead;
for(i=;i<n;i++){
p1=p1->next;
}
while(p1!=p2){
p1=p1->next;
p2=p2->next;
}
return p1;
} ListNode* MeetListNode(ListNode* pHead){ ListNode *p1=pHead->next,*p2=pHead;
if(pHead==NULL||p1==NULL||p1->next==NULL) return NULL; p1=p1->next;
while(p1!=p2){ p2=p2->next; p1=p1->next;
if(p1->next==NULL){
return NULL;
}else{
p1=p1->next;
}
}
return p1;
}

这道题有更加快捷优化的做法,后续做更新。这里只是将书本上的思路进行阐述。

10.在一个长度为n的数组里的所有数字都在0到n-1的范围内。

数组中某些数字是重复的,但不知道有几个数字是重复的。

也不知道每个数字重复几次。请找出数组中任意一个重复的数字。

例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3。

bool duplicate(int numbers[], int length, int* duplication) {

        if(NULL==numbers||length<=) return NULL;

        int i,temp;
for(i=;i<length;i++){ //对数据的正确性进行检测
if(numbers[i]<||numbers[i]>length-)
return NULL;
} for(i=;i<length;i++){
while(numbers[i]!=i){
if(numbers[i]==numbers[numbers[i]]){
*duplication=numbers[i];
return true;
} //进行数值交换
temp=numbers[i];
numbers[i]=numbers[temp];
numbers[temp]=temp;
}
} return false;
}

这道题还是比较绕,不能熟练掌握。

11.第一个只出现一次的字符

此题其实比较简单,但是要知道ASCII码共有256个。其实不知道也无妨,将hashtable设置较大即可。

期望于一个循环解决问题,是可以的,但是在面试的过程中,最重要的是解决题目,进而进行优化。

class Solution {
public:
int FirstNotRepeatingChar(string str) { int len=str.length();
if(==len)
return -;
else if(==len){
return ;
} const int size=;
unsigned int i,hashtable[size]={}; for(i=;i<len;++i){
++hashtable[str[i]];
} for(i=;i<len;++i){
if(==hashtable[str[i]])
return i;
} return -;
}
};

12.数组中只出现一次的数字

此题可以扩展范围,比如字符之类的,总之方法如果不是看书,蛮难想到的

class Solution {
public:
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) { int len=data.size();
if(len<)
return;
else if(==len&&data[]!=data[]){
*num1=data[];
*num2=data[];
return;
} int i,n=,temp=data[],res;
for(i=;i<len;i++){
temp=temp^data[i];
} //寻找二进制中初始为1数字
while(!(temp&0x01)&&(n<*sizeof(int))){
++n;
temp=temp>>;
} *num1=;*num2=;
for(i=;i<len;++i){ res=(data[i]>>n)&0x01; if(res){
*num1^=data[i];
}else{
*num2^=data[i];
}
} return;
}
};