2.3数据结构
2.3.1-数组
//Offer_03 剑指offer面试题3:数组中重复的数字
class Offer_03 {
// 剑指offer面试题3:数组中重复的数字
// 使用位置交换的算法,时间复杂度O(n),空间复杂度O(1)
std::vector<int> nums={
2, 3, 1, 0, 2, 5, 3};
public:
int findRepeatNumber(vector<int>& nums) {
int n=nums.size();
int i=0;
while(i<n)
{
if(i==nums[i])
i++;
else
{
if(nums[i]==nums[nums[i]])
return nums[i];
else
{
int temp=nums[i];
nums[i]=nums[temp];
nums[temp]=temp;
}
}
}
return 0;
}
};
//Offer_04 剑指offer面试题4:二维数组中的查找
class Offer_04 {
// 剑指offer面试题4:二维数组中的查找
public:
bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
int n=matrix.size();
if(n==0)
return false;
int m=matrix[0].size();
int i=0,j=m-1;
while(i<n&&j>=0)
{
if(matrix[i][j]==target)
return true;
else if(matrix[i][j]>target)
{
j--;
}
else{
i++;
}
}
return false;
}
};
2.3.2-字符串
//Offer_05 剑指offer面试题5:替换空格
class Offer_05 {
// 剑指offer面试题5:替换空格
// char s1[]="we are happy.";
public:
void replaceSpace(char s[],int len) {
int count=0;
for(int i=0;i<len;i++)
{
if(s[i]==' ')
count++;
}
int len_after=len+count*2;
int left=len-1;
int right=len_after-1;
s[len_after]=s[len];
s[len]=' ';
while(left>=0)
{
if(s[left]!=' ')
{
s[right--]=s[left];
}
else{
s[right--]='0';
s[right--]='2';
s[right--]='%';
}
left--;
}
cout<<s<<endl;
}
};
此处注意区分字符string和字符数组的区别char* [];
字符串以‘\0’为结束符,对其进行长度修改时可以使用string.resize();
2.3.3-链表
链表结构
struct ListNode
{
int value;
ListNode* next;
ListNode():value(0),next(nullptr){
}
ListNode(int x): value(x),next(nullptr){
}
ListNode(int x, ListNode *next):value(x),next(next){
}
};
//leetcode_02:两数相加
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {
}
ListNode(int x) : val(x), next(nullptr) {
}
ListNode(int x, ListNode *next) : val(x), next(next) {
}
};
class leetcode_02 {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
// if(l1->val==0&&l2->val==0&&l1->next==nullptr&&l2->next==nullptr)
// return l1;
// else if(l1->val==0&&l2->val!=0&&l1->next==nullptr)
// return l2;
// else if(l1->val!=0&&l2->val==0&&l2->next==nullptr)
// return l1;
//以先处理第一个节点的方法,可以避免对数字为0的值的判断;避免上面的各种判断语句的写法
ListNode *newNode=new ListNode();
newNode->val=(l1->val+l2->val)%10;
int flag=(l1->val+l2->val)/10;
ListNode *head=new ListNode(0,newNode);
ListNode *curNode=newNode;
l1=l1->next;
l2=l2->next;
while(l1!=nullptr&&l2!=nullptr)
{
ListNode *newNode=new ListNode();
newNode->val=(l1->val+l2->val+flag)%10;
flag=(l1->val+l2->val+flag)/10;
curNode->next=newNode;
curNode=newNode;
l1=l1->next;
l2=l2->next;
}
while(l1!=nullptr)
{
ListNode *newNode=new ListNode();
newNode->val=(l1->val+flag)%10;
flag=(l1->val+flag)/10;
curNode->next=newNode;
curNode=newNode;
l1=l1->next;
}
while(l2!=nullptr)
{
ListNode *newNode=new ListNode();
newNode->val=(l2->val+flag)%10;
flag=(l2->val+flag)/10;
curNode->next=newNode;
curNode=newNode;
l2=l2->next;
}
if(flag==1)
{
ListNode *newNode=new ListNode(1);
curNode->next=newNode;
curNode=newNode;
}
return head->next;
}
};
//Offer_06 剑指offer面试题6:从尾到头打印链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Offer_06 {
public:
vector<int> reversePrint(ListNode* head) {
stack<int> s1;
while(head!=nullptr)
{
s1.push(head->val);
head=head->next;
}
vector<int> res;
while(!s1.empty())
{
int x=s1.top();
res.push_back(x);
s1.pop();
}
return res;
}
};
2.3.4-树
二叉树的结构
struct TreeNode{
int value;
TreeNode *left;
TreeNode *right;
TreeNode():value(0),left(nullptr),right(nullptr){
}
};
//Offer_07 剑指offer面试题7:重建二叉树
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Offer_07 {
unordered_map<int,int> index;
public:
//传入前序遍历序列,中序遍历序列,前序遍历的起点和终点,中序遍历的起点和终点;
TreeNode* buildMytree(vector<int>& preorder, vector<int>& inorder, int preorder_left, int preorder_right,
int inorder_left, int inorder_right) {
//若前序遍历起点大于终点,结束递归
if(preorder_left>preorder_right)
return nullptr;
//前序遍历的第一个节点就是根节点;
int preorder_root=preorder_left;
//根据前序遍历找到的根节点的值,在索引中寻找中序遍历中的位置;
int inorder_root=index[preorder[preorder_root]];
//中序遍历找到根节点的位置到中序遍历起点的位置,即为左子树的节点数量;
int tree_size=inorder_root-inorder_left;
//创建一个根节点,值为前序遍历的第一个节点;
TreeNode* root=new TreeNode(preorder[preorder_root]);
//创建左子树,范围为:前序遍历:起点~左子树的数量 中序遍历:起点~中序遍历根节点的左侧;
root->left=buildMytree(preorder,inorder,preorder_left+1,preorder_left+tree_size,inorder_left,inorder_root-1);
//创建右子树,范围为:前序遍历:起点+左子树的数量+1~前序遍历的终点 中序遍历:中序遍历根节点的右侧~中序遍历的终点;
root->right=buildMytree(preorder,inorder,preorder_left+tree_size+1,preorder_right,inorder_root+1,inorder_right);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
int n=preorder.size(); //统计节点个数
for(int i=0;i<n;i++)
index[inorder[i]]=i; //为中序遍历构建索引,方便根据前序值定位中序位置
return buildMytree(preorder,inorder,0,n-1,0,n-1);
}
};
2.3.5-栈
//初始化栈: stack<int> s1;
//入栈: s1.push(x);
//出栈: s1.pop();
//访问栈顶元素: x=s1.top();
//栈是否为空: s1.empty();
//栈的大小: s1.size();
//Offer_09 剑指offer面试题9:用两个栈实现队列
class CQueue {
stack<int> s1,s2;
public:
CQueue() {
while(!s1.empty())
s1.pop();
while(!s2.empty())
s2.pop();
}
void appendTail(int value) {
s1.push(value);
}
int deleteHead() {
if(!s2.empty())
{
int x=s2.top();
s2.pop();
return x;
}
else{
if(!s1.empty())
{
while(!s1.empty())
{
int y=s1.top();
s2.push(y);
s1.pop();
}
return deleteHead();
}
else{
return -1;
}
}
}
};
2.3.5-队列
队列基本操作
queue<int> q1;
q1.empty(); //判断队列是否为空
q1.front(); //返回第一个元素
q1.back(); //返回最后一个元素
q1.push(10); //在队列末尾加入一个元素
q1.pop(); //删除第一个元素
q1.size(); //返回队列中元素的个数
//Offer_09 剑指offer面试题:两个队列实现一个栈
class MyStack {
queue<int> q1,q2;
public:
MyStack() {
// 初始化,清空两个队列
while(!q1.empty())
q1.pop();
while(!q2.empty())
q2.pop();
}
void push(int x) {
//在两个队列里面寻找非空的队列,在其尾部追加元素,若均空,则添加到第一个队列
if(!q1.empty())
q1.push(x);
else if(!q2.empty())
q2.push(x);
else
q1.push(x);
}
int pop() {
//若第一队列非空,则从第一个队列依次出队添加到第二个队列中,最后一个元素则为出栈元素;
if(!q1.empty()&&q2.empty())
{
while(q1.size()>1)
{
int x=q1.front();
q2.push(x);
q1.pop();
}
int x=q1.front();
q1.pop();
return x;
}
//若第二个队列非空,则从第二个队列依次出队添加到第一个队列中,最后一个元素则为出栈元素;
else if(!q2.empty()&&q1.empty())
{
while(q2.size()>1)
{
int x=q2.front();
q1.push(x);
q2.pop();
}
int x=q2.front();
q2.pop();
return x;
}
//两个队列均空,返回-1;
else
{
return -1;
}
}
int top() {
//两个队列中非空一个返回最后一个元素;
if(!q1.empty()&&q2.empty())
return q1.back();
else if(q1.empty()&&!q2.empty())
return q2.back();
else
return -1;
}
bool empty() {
if(q1.empty()&&q2.empty())
return true;
else
return false;
}
};