空间复杂度:临时开辟的空间、空间是可以重复利用的
递归为O(n)
时间复杂度:程序执行次数
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
思路1:利用连续的特点求等差和然后减去所有元素得到的就是消失的数字
时间复杂度:O(n) 空间复杂度:O(1)
思路2:将给定数组的元素和连续的元素进行异或(异或与顺序无关),相同元素异或结果为0。会得到有一个落单的数字与0异或就是这个数字。
时间复杂度:O(n) 空间复杂度:O(1)
第一种方法大家自行实现,我们可以实现一下不常见的第二种方法:
- int missingNumber(int* nums, int numsSize){
- int x = 0;//0与任何数异或为该数
- for(int i = 0;i
- {
- x ^= nums[i];
- }
- for(int i = 0;i<=numsSize;i++)
- {
- x ^= i;
- }
- return x;
- }
轮转数组
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
c语言阶段曾实现了两种方法,一种是依次移动,移动M次。一种是局部逆置和整体逆置。前者时间复杂度为O(N*M),后者为O(N)
空间换时间:创建一个临时数组,前面放需要旋转的数据,后面放没有旋转的数据即可。
不完整代码:
- void rotate(int* nums, int numsSize, int k){
- int tmp[numsSize];
- k %= numsSize;//循环次数不必多于元素个数
- int i = 0;
- int j = 0;
- for(i=numsSize-k;i
- {
- tmp[j] = nums[i];
- j++;
- }
- for(i = 0;i
- {
- tmp[j] = nums[i];
- }
- for//打印
- }
有效的括号
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
思路:让左括号依次入栈,与右括号匹配。
匹配前:判断栈是否为空,为空说明无左括号。返回false。
匹配中:匹配涉及多次如 " () {} (())",记录指针位置与栈顶比较,然后出栈,不匹配返回false。
匹配结束:栈空为匹配成功,否则匹配失败。
注意返回前都需进行销毁操作。
- #include
- #include
- #include
- typedef char STDatatype;
- typedef struct Stack
- {
- STDatatype* a;
- int capacity;
- int top;
- }ST;
- void check_capacity(ST* ps)
- {
- if(ps->capacity == ps->top)
- {
- int newCapacity = 0 ? 4:ps->capacity*2;
- char* tmp;
- tmp = (STDatatype*)realloc(ps->a,sizeof(STDatatype) * newCapacity);
- if (tmp == NULL)
- {
- perror("malloc");
- exit(-1);
- }
- ps->a = tmp;
- ps->capacity = newCapacity;
- }
- }
- bool StackEmpty(ST* ps)//判空
- {
- assert(ps);
- return ps->top == 0;
- }
- STDatatype StackTop(ST* ps)
- {
- assert(ps);
- assert(!StackEmpty(ps));
- return ps->a[ps->top-1];//top为最后一个元素的下一个
- }
- void StackDestroy(ST* ps)
- {
- assert(ps);
-
- free(ps->a);
- ps->a = NULL;
- ps->top = ps->capacity = 0;
- }
- void StackInit(ST* ps)
- {
- /*ps->a = NULL;
- ps->top = 0;
- ps->capacity = 0;*/
- //初始化空间
- ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);
- if (ps->a == NULL)
- {
- perror("malloc");
- exit(-1);
- }
- ps->top = 0;
- ps->capacity = 4;
- }
- void StackPop(ST* ps)//出栈
- {
- assert(ps);
- //if(ps->top>0)
- assert(!StackEmpty(ps));
- ps->top--;
- }
- void StackPush(ST* ps, STDatatype x)
- {
- assert(ps);
- check_capacity(ps);
- ps->a[ps->top] = x;
- ps->top++;//指向下一个
- }
- bool isValid(char* s) {
- ST ps;
- StackInit(&ps);
- while(*s)
- {
- if(*s == '(' || *s == '[' ||*s == '{' )
- {
- StackPush(&ps,*s);
- s++;
- }
- else
- {
- if(StackEmpty(&ps))//如果没有左括号,栈顶没有元素
- {
- StackDestroy(&ps);//注意返回前都要手动释放空间
- return false;
- }
- char top = StackTop(&ps);
- if((*s == ')' && top != '(') || (*s == ']' && top != '[') ||
- (*s == '}' && top != '{'))//
- {
- StackDestroy(&ps);
- return false;
- }
- else
- {
- StackPop(&ps);
- s++;
- }
- }
- }
- bool ret = StackEmpty(&ps);
- StackDestroy(&ps);
- return ret;
- }
用队列实现栈
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
先导入我们实现过的队列:
- #pragma once
- #include
- #include
- #include
- #include
- typedef int QDataType;
- typedef struct QueueNode
- {
- QDataType data;
- struct QueueNode* next;
- }QNode;
- struct Queue
- {
- QNode* head;
- QNode* tail;
- int size;
- };
- void QueueInit(Queue* pq);
- void QueueDestroy(Queue* pq);
- void QueuePush(Queue* pq, QDataType x);
- void QueuePop(Queue* pq);
- QDataType QueueFront(Queue* pq);
- QDataType QueueBack(Queue* pq);
- bool QueueEmpty(Queue* pq);
- int QueueSize(Queue* pq);
-
- void QueueDestroy(Queue* pq)
- {
- assert(pq);
- QNode* cur = pq->head;
- while (cur)
- {
- QNode* Next =cur->next;
- free(cur);
- cur = Next;
- }
- pq->head = pq->tail = NULL;//避免野指针
- pq->size = 0;
- }
- void QueuePush(Queue* pq, QDataType x)
- {
- assert(pq);
-
- QNode* newnode = (QNode*)malloc(sizeof(QNode));
- if (newnode == NULL)
- {
- perror("malloc fail");
- exit(-1);
- }
- newnode->data = x;
- newnode->next = NULL;
- pq->size++;
-
- if (pq->head == NULL)
- {
- pq->head = pq->tail = newnode;
- }
- else
- {
- pq->tail->next = newnode;
- pq->tail = newnode;
- }
- }
- void QueuePop(Queue* pq)
- {
- //出队头删
- assert(pq);
- assert(pq->head);
- QNode* del = pq->head;
- pq->head = pq->head->next;
- free(del);
- if (pq->head == NULL)
- pq->tail = NULL;
- pq->size--;
-
- }
- void QueueInit(Queue* pq)
- {
- assert(pq);
- pq->head = NULL;
- pq->tail = NULL;
- pq->size = 0;
- }
- bool QueueEmpty(Queue* pq)
- {
- assert(pq);
- return pq->head == NULL && pq->tail == NULL;
- }
- int QueueSize(Queue* pq)
- {
- assert(pq);
- return pq->size;
- }
- QDataType QueueFront(Queue* pq)
- {
- assert(pq);
- assert(!QueueEmpty(pq));
- return pq->head->data;
- }
- QDataType QueueBack(Queue* pq)
- {
- assert(pq);
- assert(!QueueEmpty(pq));
-
- return pq->tail->data;
- }
两个队列
将两个队列封装在一个结构体中。
- typedef struct Queue
- {
- QNode* head;
- QNode* tail;
- int size;
- }Queue;//简写
创建并初始化链表(栈)
注意要想保证我们创建的结构体生命周期能够贯彻整个工程,必须在堆上申请空间。
- MyStack* myStackCreate() {//创建并初始化链表
- MyStack* obj = (MyStack*)malloc(sizeof(MyStack));//堆区
- QueueInit(&obj->q1);
- QueueInit(&obj->q2);
- return obj;
- }
模拟入栈
选择非空队列插入即可。
- void myStackPush(MyStack* obj, int x) {
- if(!QueueEmpty(&obj->q1))//非空队列插入
- {
- QueuePush(&obj->q1,x);
- }
- else
- QueuePush(&obj->q2,x);
- }
模拟出栈
出栈是在队尾进行出(后进先出),我们将非空队列进行出队只剩下最后一个元素即是栈顶的元素,然后将其保存后出栈避免造成内存泄露,然后返回。
- nt myStackPop(MyStack* obj) {
- //假定一方不为空
- Queue* empty = &obj->q1;
- Queue* nonempty = &obj->q2;
- if(!QueueEmpty(empty))
- {
- empty = &obj->q2;
- nonempty = &obj->q1;
- }
-
- while(QueueSize(nonempty) > 1)//O(1)导入空来链表
- {
- QueuePush(empty,QueueFront(nonempty));//非空取队头插入空
- QueuePop(nonempty);
- }
- //保证原链表返回为空
- int top = QueueFront(nonempty);
- QueuePop(nonempty);//出栈
- return top;
- }
模拟栈顶
直接返回队尾元素即可。
- int myStackTop(MyStack* obj) {
- //返回队尾
- if(!QueueEmpty(&obj->q1))
- {
- return QueueBack(&obj->q1);
- }
- else
- return QueueBack(&obj->q2);
- }
模拟栈判空
- bool myStackEmpty(MyStack* obj) {
-
- return QueueEmpty(&obj->q1) && QueueEmpty(&obj->q2);
- }
模拟栈销毁
除了释放队列指针组合的结构体外,还要将每个队列里的元素释放。
- void myStackFree(MyStack* obj) {
- QueueDestroy(&obj->q1);
- QueueDestroy(&obj->q2);
- free(obj);
- }
用栈实现队列
思路:两个栈,一个负责push数据,一个负责pop数据,在pop数据时,判断pop栈中是否有数据,没有则将push栈的数据全部导入,此时数据顺序反过来后再pop栈里出栈就可以实现先进先出这一特性了。
导入实现好的栈:
-
- #include
- #include
- #include
- #include
-
- typedef int STDatatype;
- typedef struct Stack
- {
- STDatatype* a;
- int capacity;
- int top;
- }ST;
-
- void StackInit(ST* ps);
- void StackDestroy(ST* ps);
- void StackPush(ST* ps, STDatatype x);
- void StackPop(ST* ps);//出栈
- STDatatype StackTop(ST* ps);
-
- bool StackEmpty(ST* ps);
- int StackSize(ST* ps);
-
- void StackInit(ST* ps)
- {
- /*ps->a = NULL;
- ps->top = 0;
- ps->capacity = 0;*/
- //初始化空间
- ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);
- if (ps->a == NULL)
- {
- perror("malloc");
- exit(-1);
- }
- ps->top = 0;
- ps->capacity = 4;
- }
-
- static void check_capacity(ST* ps)
- {
- if (ps->top == ps->capacity)
- {
- int newCapacity = ps->capacity * 2;
- STDatatype* tmp = (STDatatype*)realloc(ps->a, newCapacity *sizeof(STDatatype));
- if (tmp == NULL)
- {
- perror("realloc");
- exit(-1);
- }
- else
- {
- ps->a = tmp;
- ps->capacity == newCapacity;
- }
- }
- }
- void StackPush(ST* ps, STDatatype x)
- {
- assert(ps);
- check_capacity(ps);
- ps->a[ps->top] = x;
- ps->top++;//指向下一个
- }
- void StackPop(ST* ps)//出栈
- {
- assert(ps);
- //if(ps->top>0)
- assert(!StackEmpty(ps));
- ps->top--;
- }
-
- STDatatype StackTop(ST* ps)
- {
- assert(ps);
- assert(!StackEmpty(ps));
- return ps->a[ps->top-1];//top为最后一个元素的下一个
- }
- void StackDestroy(ST* ps)
- {
- assert(ps);
-
- free(ps->a);
- ps->a = NULL;
- ps->top = ps->capacity = 0;
- }
- bool StackEmpty(ST* ps)//判空
- {
- assert(ps);
- return ps->top == 0;
- }
- int StackSize(ST* ps)
- {
- assert(ps);
- return ps->top;
- }
两个栈
- typedef struct {
- ST pushst;//入队
- ST popst;//出队
- } MyQueue;
Create
-
- MyQueue* myQueueCreate() {
- //初始化+开空间
- MyQueue* st = (MyQueue*)malloc(sizeof(MyQueue));
- StackInit(&st->pushst);
- StackInit(&st->popst);
- return st;
- }
Push
- void myQueuePush(MyQueue* obj, int x) {
- assert(obj);
- StackPush(&obj->pushst,x);
- }
判空
- bool myQueueEmpty(MyQueue* obj) {
- assert(obj);
- return StackEmpty(&obj->pushst) && StackEmpty(&obj->popst);
- }
查看队头
由于popst的栈顶为队头,如果该栈为空,需要导入pushst的数据。
- int myQueuePeek(MyQueue* obj) {
- assert(obj);
- assert(!myQueueEmpty(obj)); //双栈判空
- if(StackEmpty(&obj->popst))
- {
- while(!StackEmpty(&obj->pushst))//导数据
- {
- StackPush(&obj->popst,StackTop(&obj->pushst));
- StackPop(&obj->pushst);
- }
- }
- return StackTop(&obj->popst);
- }
Pop
同样涉及判空和调用队头元素,通过调用peek函数判断并完成对数据的导入并接收其返回值,
- int myQueuePop(MyQueue* obj) {
-
- int qhead = myQueuePeek(obj);
- StackPop(&obj->popst);//出队
- return qhead;
- }
释放
- void myQueueFree(MyQueue* obj) {
- assert(obj);
- StackDestroy(&obj->pushst);
- StackDestroy(&obj->popst);
- free(obj);
- }
-
相关阅读:
MySQL--创建,删除,查找,案例
发展之路是怎么样? 防爆机器人的未来发展之路是怎么样
数字孪生产业园开发公司,VR钢铁效果怎么样?强荐广州华锐互动
Shell常用的几个正则表达式:[:alnum:], [:alpha:], [:upper:], [:lower:], [:digit:] 认知
代码随想录笔记_动态规划_139单词拆分
字符串首尾空格去除问题
redis
JMeter 逻辑控制之IF条件控制器
CLIP 论文逐段精读【论文精读】
计算机组成原理 | 输入输出系统
-
原文地址:https://blog.csdn.net/dwededewde/article/details/134082802