开宗明义:本系列基于牛客网剑指offer,刷题小白,一天两道我快乐!旨在理解和交流,重在记录,望各位大牛指点!
牛客网-剑指offer
文章目录
1、栈和队列
描述:用两个栈来实现一个队列,完成队列的push和pop操作。队列的元素为int类型。
思路:
- 栈:先进后出;队列:先进先出 ;
- Stack1负责入栈,Stack2负责出栈;
- 将Stack1的出栈入Stack2,再Stack2出栈就是先入先出了;
测试代码:
class Solution {
public:
void push(int node) {
stack1.push(node); //入栈
}
int pop() {
int temp;
if (stack2.empty()) { //如果这个栈未空
while (!stack1.empty()) {
int t=stack1.top();
stack1.pop();
stack2.push(t); //后进的入栈栈顶先入
}
}
//如果这个栈不为空
temp = stack2.top(); //这时候栈2变成了后进的先入,先进的后入
stack2.pop();
return temp;
}
private:
stack<int> stack1; //用于存储push的元素
stack<int> stack2; //用于倒转stack的元素,以生成队列
};
2、旋转数组的最小数字
描述:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。NOTE:给出所有的元素都大于0,若数组大小为0,请返回0。
思路1:直接把这个vector调用STL的sort排序函数排序,然后输出第一个元素就可以了,就是最小值。
测试代码:
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
sort(rotateArray.begin(),rotateArray.end());
return rotateArray[0];
}
};
思路2:二分查找法
- 第一点,由题意,这个数组是递增的;
- 设定 m i d = l o w + ( h i g h − l o w ) / 2 mid=low+(high-low)/2 mid=low+(high−low)/2;
- 设定两个标签,初始化的时候一个指向头 l e f t left left,一个指向尾 r i g h t right right;
- 在 l e f t < r i g h t left<right left<right 的前提下,考虑下面三种情况:
- ① r o t a t e A r r a y [ l e f t ] < r o t a t e A r r a y [ m i d ] rotateArray[left] < rotateArray[mid] rotateArray[left]<rotateArray[mid] 说明前面是递增的,那么旋转了,最小值在后面,那么 l e f t = m i d + 1 left=mid+1 left=mid+1;
- ② r o t a t e A r r a y [ m i d ] < r o t a t e A r r a y [ r i g h t ] rotateArray[mid] < rotateArray[right] rotateArray[mid]<rotateArray[right] 说明后面是递增的,那么最小值在前面,那么这时候更新 r i g h t right right;
- 这边更新 r i g h t right right ,更新 r i g h t = m i d right = mid right=mid,而不是 r i g h t = m i d − 1 right = mid -1 right=mid−1,因为如果最后只剩两个数 [ 4 , 6 ] [4,6] [4,6] ,那么 l e f t = 4 , r i g h t = 6 left=4,right =6 left=4,right=6,这时候 m i d mid mid 指向下标靠前的数字。
测试代码:
//C++ 二分法
#include <vector>
using namespace std;
class Solution {
public:
int minNumberInRotateArray(vector<int> rotateArray) {
if (rotateArray.empty())
return 0;
int left = 0;
int right = rotateArray.size() - 1;
while (left < right) {
//确认子数组是否是类似1,1,2,4,5,..,7的非递减数组
if (rotateArray[left] < rotateArray[right])
return rotateArray[left];
int mid = left + (right - left) / 2;
//如果左半数组为有序数组.说明旋转了,最小元素肯定在右边
if (rotateArray[left] < rotateArray[mid])
left = mid + 1;
//如果右半数组为有序数组
else
if (rotateArray[mid] < rotateArray[right])
right = mid;
//否则,rotateArray[left] == rotateArray[mid] == rotateArray[right]
else {
++left;
}
}
return rotateArray[left];
}
};