每日算法4/13

232. 用栈实现队列

题目

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty):

实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

说明:

  • 你 只能 使用标准的栈操作 —— 也就是只有 push to toppeek/pop from topsize, 和 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 次 pushpoppeek 和 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;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值