232. 用栈实现队列
题目
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push
、pop
、peek
、empty
):
实现 MyQueue
类:
void push(int x)
将元素 x 推到队列的末尾int pop()
从队列的开头移除并返回元素int peek()
返回队列开头的元素boolean empty()
如果队列为空,返回true
;否则,返回false
说明:
- 你 只能 使用标准的栈操作 —— 也就是只有
push to top
,peek/pop from top
,size
, 和is empty
操作是合法的。 - 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
示例 1:
输入: ["MyQueue", "push", "push", "peek", "pop", "empty"] [[], [1], [2], [], [], []] 输出: [null, null, null, 1, 1, false] 解释: MyQueue myQueue = new MyQueue(); myQueue.push(1); // queue is: [1] myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue) myQueue.peek(); // return 1 myQueue.pop(); // return 1, queue is [2] myQueue.empty(); // return false
提示:
1 <= x <= 9
- 最多调用
100
次push
、pop
、peek
和empty
- 假设所有操作都是有效的 (例如,一个空的队列不会调用
pop
或者peek
操作)
思路
通过两个栈实现队列的操作
由于栈是后进后出,而队列是先进先出,将一个栈数据从后往前复制到另一个栈,那么另一个栈的数据就是按照出队列的顺序出栈
- 创建两个栈,一个输入栈,一个输出栈,并创建好两个栈的栈顶。
- Push就是往输入栈中输入数据
- Pop就需要将输入栈的数据从后往前复制到输出栈中,为了实现队列方式的出数据,获取队列顶的数据就是后去输出栈的栈顶数据,取出并使输出栈顶-1,由于数据被去除,那么更新输入栈
- Peek直接获取输入战中的第一个数据
- Free要将两个栈的栈顶都回退到0;
代码
typedef struct {
int stackin[100];
int stackout[100];
int inTop, outTop;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue* que = (MyQueue*)malloc(sizeof(MyQueue));
que->inTop = 0;
que->outTop = 0;
return que;
}
void myQueuePush(MyQueue* obj, int x) {
// obj = myQueueCreate();不需要因为下面已经完成这个操作
obj->stackin[obj->inTop++] = x;
}
int myQueuePop(MyQueue* obj) {
int InTop = obj->inTop;
int OutTop = obj->outTop;
if(OutTop == 0) {
while(InTop > 0) {
obj->stackout[OutTop++] = obj->stackin[--InTop];
}
}
int top = obj->stackout[--OutTop];
//更新栈顶指针
while(OutTop > 0) {
obj->stackin[InTop++] = obj->stackout[--OutTop];
}
obj->inTop = InTop;
obj->outTop = OutTop;
return top;
}
int myQueuePeek(MyQueue* obj) {
return obj->stackin[0];
}
bool myQueueEmpty(MyQueue* obj) {
if(obj->inTop == 0 && obj->outTop == 0)
return true;
return false;
}
void myQueueFree(MyQueue* obj) {
obj->inTop = 0;
obj->outTop = 0;
}
/**
* Your MyQueue struct will be instantiated and called as such:
* MyQueue* obj = myQueueCreate();
* myQueuePush(obj, x);
* int param_2 = myQueuePop(obj);
* int param_3 = myQueuePeek(obj);
* bool param_4 = myQueueEmpty(obj);
* myQueueFree(obj);
*/
817. 链表组件
题目
给定链表头结点 head
,该链表上的每个结点都有一个 唯一的整型值 。同时给定列表 nums
,该列表是上述链表中整型值的一个子集。
返回列表 nums
中组件的个数,这里对组件的定义为:链表中一段最长连续结点的值(该值必须在列表 nums
中)构成的集合。
示例 1:
输入: head = [0,1,2,3], nums = [0,1,3] 输出: 2 解释: 链表中,0 和 1 是相连接的,且 nums 中不包含 2,所以 [0, 1] 是 nums 的一个组件,同理 [3] 也是一个组件,故返回 2。
示例 2:
输入: head = [0,1,2,3,4], nums = [0,3,1,4] 输出: 2 解释: 链表中,0 和 1 是相连接的,3 和 4 是相连接的,所以 [0, 1] 和 [3, 4] 是两个组件,故返回 2。
提示:
- 链表中节点数为
n
1 <= n <= 104
0 <= Node.val < n
Node.val
中所有值 不同1 <= nums.length <= n
0 <= nums[i] < n
nums
中所有值 不同
思路
- 首先创建一个足够大的数组,并初始化所有元素为0
- 以nums数组元素为索引的初始化数组元素,初始化为1,用于后面链表元素判断是否在nums数组中
- 分析知构成相邻两个组件,以其中间链表元素为索引的数组元素值为0;
- 遍历链表中的元素,将其与声明的数组元素比较,利用pre判断组件连续性
代码
int save[100001];
int numComponents(struct ListNode* head, int* nums, int numsSize){
struct ListNode* tail = head;
int n = 0;
while(tail){
tail = tail->next;
n++
}
msmset(num.1.sizeof(int)*n)// 初始化数组
for (int i = 0; i < numsSize; i++)
{
save[nums[i]] = 1; /* 将nums对应的值的下标设为1,用于后面
判断链表结点的值是否在nums中*/
}
int result = 0, pre = 0; // 用于判断组件的连续性,为0新起组件
while(head)
{
if (pre == 0 && save[head->val] == 1)
result++;
pre = save[head->val];
head = head->next;
}
return result;
}