剑指offer刷题数据结构
Posted 非晚非晚
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指offer刷题数据结构相关的知识,希望对你有一定的参考价值。
记录在Leetcode刷《剑指offer》的笔记,希望提高自己的算法基础和编程水平。这一篇文章刷的是数据结构的题目集合,在CSDN做一下记录,随时更新,一起学习吧。
刷题链接:https://leetcode-cn.com/leetbook/read/illustration-of-algorithm/55187i/
1. 剑指 Offer 05. 替换空格
- 题目
- 提交答案:
思路:定义一个空字符串myStr,遍历输入字符串s,遇到空格就把"%20"加入新字符串myStr,否则就添加s[i]。
class Solution {
public:
string replaceSpace(string s) {
string str = "%20";
string myStr;
for(int i = 0; i < s.size(); i++)
{
if(s[i] == ' ')
{
myStr += str;
}
else
{
myStr += s[i];
}
}
return myStr;
}
};
- 原题解答:
思路:先计算空格数,对原string扩容,然后倒序遍历空格,依次加入’%’, ‘2’, ‘0’。
class Solution {
public:
string replaceSpace(string s) {
int count = 0, len = s.size();
// 统计空格数量
for (char c : s) {
if (c == ' ') count++;
}
// 修改 s 长度
s.resize(len + 2 * count);
// 倒序遍历修改
for(int i = len - 1, j = s.size() - 1; i < j; i--, j--) {
if (s[i] != ' ')
s[j] = s[i];
else {
s[j - 2] = '%';
s[j - 1] = '2';
s[j] = '0';
j -= 2;
}
}
return s;
}
};
2. 剑指 Offer 06. 从尾到头打印链表
-
题目
-
提交答案
思路:遍历list,依次赋值给vector,然后利用reverse函数对vector反转。
这里用的reverse属于算法的函数,其实也可以直接对list使用,不过这里只给了头指针。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
vector<int> reversePrint(ListNode* head) {
vector<int> vec;
auto p = head;
while(p != NULL)
{
vec.push_back(p->val);
p = p->next;
}
reverse(vec.begin(), vec.end());
return vec;
}
};
- 原题解答
思路:递归法,递归原本就属于一种逆序运行的算法。
class Solution {
public:
vector<int> reversePrint(ListNode* head) {
recur(head);
return res;
}
private:
vector<int> res;
void recur(ListNode* head) {
if(head == nullptr) return;
recur(head->next);
res.push_back(head->val);
}
};
3. 剑指 Offer 09. 用两个栈实现队列
- 题目
- 提交答案
思路:使用A stack存储队列,使用B stack用于删除。由于每次都要清空B,提交的答案耗时间太长。。
class CQueue {
private:
stack<int> A;//存储队列
stack<int> B;//用作删除元素
public:
CQueue() {
}
void appendTail(int value) {
A.push(value);
}
int deleteHead() {
if(A.size() == 0)
return -1;
while(A.size() !=0)
{
int x = A.top();
A.pop();//删除
B.push(x);
}
int temp = B.top();
B.pop();
while(B.size() != 0)
{
int x = B.top();
B.pop();
A.push(x);
}
return temp;
}
};
/**
* Your CQueue object will be instantiated and called as such:
* CQueue* obj = new CQueue();
* obj->appendTail(value);
* int param_2 = obj->deleteHead();
*/
- 解题思路
思路:同样是使用A和B,A用于保存,B用于删除,不过B不清空,只要有就可以删除。
class CQueue {
public:
stack<int> A, B;
CQueue() {}
void appendTail(int value) {
A.push(value);
}
int deleteHead() {
if(!B.empty()) {
int tmp = B.top();
B.pop();
return tmp;
}
if(A.empty()) return -1;
while(!A.empty()) {
int tmp = A.top();
A.pop();
B.push(tmp);
}
int tmp = B.top();
B.pop();
return tmp;
}
};
4. 剑指 Offer 20. 表示数值的字符串
- 题目
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、“5e2”、"-123"、“3.1416”、"-1E-16"、“0123"都表示数值,但"12e”、“1a3.14”、“1.2.3”、"±5"及"12e+5.4"都不是。
- 提交答案
思路太繁琐
- 题目解析
用哈希表来表示。状态是按照string从左只右依次定义的,输入数据后,状态会跳转。
代码示例:
说明:
- states是个数组,表示9中状态。数组的元素为unordered_map类型。
- d表示数字
- s表示正负号
- c表示dot或者空格
find(key);//查找键key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
class Solution {
private:
unordered_map<char,int> states[9]={
{{' ',0}, {'s',1}, {'d',2}, {'.',4}}, //! 0.
{{'d',2}, {'.',4}}, //! 1.
{{'d',2}, {'.',3}, {'e',5}, {' ',8}}, //! 2.
{{'d',3}, {'e',5}, {' ',8}}, //! 3.
{{'d',3}}, //! 4.
{{'s',6}, {'d',7}}, //! 5.
{{'d',7}}, //! 6.
{{'d',7}, {' ',8}}, //! 7.
{{' ',8}} //! 8.
};
public:
bool isNumber(string s) {
int p=0;
char t;
for(auto c:s){
if(c>='0'&&c<='9') t='d';
else if(c=='+'||c=='-') t='s';
else if(c=='e'||c=='E') t='e';
else if(c=='.'||c==' ') t=c;
else t='?';
auto it=states[p].find(t);
if(it==states[p].end()) return false;//没有找到
p=(int)it->second;//提取下一个状态
}//遍历结束后,查看p的状态
return p==2||p==3||p==7||p==8;
}
};
5. 剑指 Offer 24. 反转链表
- 提交答案
思路:分3种情况,1个元素,2个元素,3个元素。最主要的是3个元素,断开链接进行移动。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head == NULL)
return NULL;
auto p1 = head;
p1 = p1->next;
if(p1 == NULL)//只有一个
{
return head;
}
else if(p1->next == NULL)//2个
{
head->next = NULL;//补null
p1->next = head;
return p1;
}
else//3个以上
{
head->next = NULL;//补null
auto p2 = p1->next;
while(p2 != NULL)
{
//head和p1交换
p1->next = head;
//移动
head = p1;
p1 = p2;
p2 = p2->next;
}
p1->next = head;
return p1;
}
}
};
- 题目解析
思路:只需要两个指针遍历,只需要定义一个暂时的指针,保存下一个地址。代码量少耗内存较多。
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *cur = head, *pre = nullptr;
while(cur != nullptr) {
ListNode* tmp = cur->next; // 暂存后继节点 cur.next
cur->next = pre; // 修改 next 引用指向
pre = cur; // pre 暂存 cur
cur = tmp; // cur 访问下一节点
}
return pre;
}
};
6. 剑指 Offer 30. 包含 min 函数的栈
- 题目
- 题目解析
思路:A是正常栈,B为非严格排序栈。只需要A和B的栈顶元素相同时,才弹出B。
class MinStack {
public:
stack<int> A, B;
MinStack() {}
void push(int x) {
A.push(x);
if(B.empty() || B.top() >= x)//递减排序
B.push(x);
}
void pop() {
if(A.top() == B.top())
B.pop();
A.pop();
}
int top() {
return A.top();
}
int min() {
return B.top();
}
};
8. 剑指 Offer 58 - II. 左旋转字符串
- 提交代码
思路:这题主要是考察string各种方法的熟练程度。截取字符串,然后删除提取部分,赋值末尾即可。
class Solution {
public:
string reverseLeftWords(string s, int n) {
string str;
str.assign(s, 0, n);//从0开始的n个字符,也可以用string的substr方法
s.erase(0, n);//删除0到n
for(int i = 0; i < n; i++)
{
s += str[i];
}
return s;
}
};
- 题目解析
思路:方法更简单明了。
class Solution {
public:
string reverseLeftWords(string s, int n) {
return s.substr(n, s.size()) + s.substr(0, n);
}
};
9. 剑指 Offer 59 - I. 滑动窗口的最大值
提交答案
思路:先写一个滑动窗口k最大值函数,然后在滑动时每次调用该函数。时间复杂度比较高,属于暴力方法。
class Solution {
public:
int find_max(vector<int>& nums)
{
int max_num = nums[0];
for(int i = 1; i < nums.size(); i++)//找出最大值
{
if(nums[i] > max_num)
max_num = nums[i];
}
return max_num;
}
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
if(nums.size() == 0)
{
return nums;
}
vector<int>temp;
for(int i = 0; i < nums.size() - k + 1; i++)
{
vector<int>temp_nums;
for(int j = 0; j < k; j++)
{
temp_nums.push_back(nums[i + j]);
}
temp.push_back(find_max(temp_nums));
}
return temp;
}
};
- 题目解析
思路:双端队列(还没研究)
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
//判断特殊情况
int n = nums.size();
if(n < k || k <= 0) return 以上是关于剑指offer刷题数据结构的主要内容,如果未能解决你的问题,请参考以下文章