10.18--一下午连肝20道leetcode题(纯C实现)
Posted C_YCBX Py_YYDS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了10.18--一下午连肝20道leetcode题(纯C实现)相关的知识,希望对你有一定的参考价值。
题目
20.有效的括号
155.最小栈
225.用队列实现栈
232.用栈实现队列
234.回文链表
844.比较含退格的字符
682.棒球比赛
1047. 删除字符串中的所有相邻重复项
1441.用栈构建数组
1475.商品折扣后的最终价格
1544.整理字符串
1598. 文件夹操作日志搜集器
1614. 括号的最大嵌套深度
150. 逆波兰表达式求值
735. 行星碰撞
1.两数之和
167. 两数之和 II - 输入有序数组
806. 写字符串需要的行数
821. 字符的最短距离
832. 翻转图像
解题代码与分析
20.有效的括号
很简单的栈的运用题,通过左右括号的限制栈的入和出。
bool checkL(char x){
return x=='('||x=='{'||x=='[';
}
bool checkR(char x){
return x==')'||x=='}'||x==']';
}
bool isMatch(char a,char b){
switch(a){
case '(':
return b==')';
case '{':
return b=='}';
case '[':
return b==']';
}
return false;
}
bool isValid(char * s){
int n = strlen(s);
int top = 0;//这里top指向stack的长度
char stack[10005];
for(int i=0;i<n;i++){
if(checkL(s[i])){
stack[top++] = s[i];
}else if(checkR(s[i])){
if(top==0)
return false;
if(isMatch(stack[top-1],s[i]))
top--;
else return false;
}
}
return top==0;
}
155.最小栈
我的做法很朴素,保持最小元素在栈顶即可,只需要对每次入栈操作特殊处理,当栈为空的时候只需要入一个元素,如果栈不为空,则对当前要入的元素进行判断,得出更小的一个元素,然后多入一个元素到栈顶,也就是这个更小的元素,这样也就相当于除了最开始情况下是入一个,其余情况都是两个两个的入栈,所以每次出栈除了最开始的一个情况外都需要
-= 2
。
#define SIZE 15000
typedef struct {
int nums[SIZE];
int top;
} MinStack;
/** initialize your data structure here. */
MinStack* minStackCreate() {
MinStack* obj = malloc(sizeof(MinStack));
obj->top = -1;
return obj;
}
//重点就在于push和pop的处理
void minStackPush(MinStack* obj, int val) {
//当栈空时只入一个,其他情况将栈顶与入栈元素进行比较,保持最小的元素在栈顶,入栈元素在栈顶的下一个。
if(obj->top==-1)
obj->nums[++(obj->top)] = val;
else{
int min = obj->nums[obj->top]>val?val:obj->nums[obj->top];
obj->nums[++(obj->top)] = val;
obj->nums[++(obj->top)] = min;
}
}
void minStackPop(MinStack* obj) {
//若到了最后一个元素,则底下没有其他东西垫底需要特殊处理。
//当栈为空则top不动。
if(obj->top==-1){
return;
}
//确保top指向最小值
if(obj->top==0){
obj->top=-1;
return;
}
obj->top-=2;
}
//关键就在于能改变top指针的操作的设计,而下面两个不能影响top指针,所以很是简单。。
int minStackTop(MinStack* obj) {
if(obj->top==0){
return obj->nums[obj->top];
}
return obj->nums[obj->top-1];
}
int minStackGetMin(MinStack* obj) {
return obj->nums[obj->top];
}
void minStackFree(MinStack* obj) {
free(obj);
}
225.用队列实现栈
用C语言的话,只要对队列的实现较为熟悉应该都好做,我们需要两个队列实现一个栈的话,需要能够熟练的运用好这两个队列,其中一个队列我们作为中转站,也就是,每次如果要执行栈的pop得到栈顶,则我们需要不断的对队列进行pop,然后转移到另一个中转站,直到只剩一个元素,则这个就是栈顶元素,返回这个元素即可。上面这些描述是对栈的pop和top操作中都需要做的操作,以下就是有一些不一样了:
对于pop操作:进行上述操作后,我们需要再把中转站变成要操作的队列(指针交换),注意还需要把这剩下的最后一个元素pop。
对于top操作:进行上述操作后,需要再执行一次push操作,然后再指针交换。
- 结合代码进行观看体验更佳。
#define MAXLEN 20
typedef struct{
int* date;
int front;
int rear;
}queue;
typedef struct {
queue* Q1;
queue* Q2;
} MyStack;
MyStack* myStackCreate() {
MyStack* res = (MyStack*)malloc(sizeof(MyStack));
res->Q1 = (queue*) malloc(sizeof(queue));
res->Q2 = (queue*) malloc(sizeof(queue));
res->Q1->date = (int*)malloc(sizeof(int)*MAXLEN);
res->Q2->date = (int*)malloc(sizeof(int)*MAXLEN);
res->Q1->front = res-> Q1->rear = res->Q2->front = res->Q2->rear = 0;
return res;
}
void myStackPush(MyStack* obj, int x) {
obj->Q1->date[obj->Q1->rear%MAXLEN] = x;//一个栈负责入
obj->Q1->rear++;
}
int myStackPop(MyStack* obj) {
while((obj->Q1->front+1)%MAXLEN != (obj->Q1->rear)%MAXLEN){//把队列push到另外一个队列,只剩下一个元素为止
obj->Q2->date[obj->Q2->rear%MAXLEN] = obj->Q1->date[obj->Q1->front%MAXLEN];
obj->Q2->rear++,obj->Q1->front++;
}
//交换指针内容
queue* t = obj->Q1;
obj->Q1 = obj->Q2;
obj->Q2 = t;
return obj->Q2->date[obj->Q2->front++];
}
int myStackTop(MyStack* obj) {
while((obj->Q1->front+1)%MAXLEN != (obj->Q1->rear)%MAXLEN){//把队列push到另外一个队列,只剩下一个元素为止
obj->Q2->date[obj->Q2->rear%MAXLEN] = obj->Q1->date[obj->Q1->front%MAXLEN];
obj->Q2->rear++,obj->Q1->front++;
}
int res = obj->Q1->date[obj->Q1->front];
obj->Q2->date[obj->Q2->rear%MAXLEN] = obj->Q1->date[obj->Q1->front%MAXLEN];
obj->Q2->rear++,obj->Q1->front++;
//交换指针内容
queue* t = obj->Q1;
obj->Q1 = obj->Q2;
obj->Q2 = t;
return res;
}
bool myStackEmpty(MyStack* obj) {
return obj->Q1->front == obj->Q1->rear;
}
void myStackFree(MyStack* obj) {
free(obj->Q1->date);
obj->Q1->date = NULL;
free(obj->Q2->date);
obj->Q2->date = NULL;
free(obj->Q1);
obj->Q1 = NULL;
free(obj->Q2);
obj->Q2 = NULL;
free(obj);
obj = NULL;
}
232.用栈实现队列
用栈实现队列,单纯的是利用另外一个栈来实现倒序的功能,使得末端变首端,需要注意的是我们只需要一个队列用于push,另一个队列用于 pop 和 front 即可,完全不需要中转站这种操作,需要注意只有当用于 pop 和 front的栈空了,才需要重新补给!
/* 两个栈实现队列, S1,S2 */
/* 入队操作: push元素进入S1 */
/* 出队操作: S2非空时, 从S2弹出元素, S2为空, S1数据导入S2再弹出 */
#define MAXLEN 20
typedef struct{
int* date;
int top;
}stack;
typedef struct {
stack* S1;
stack* S2;
} MyQueue;
MyQueue* myQueueCreate() {
MyQueue* Q = (MyQueue*)malloc(sizeof(MyQueue));
Q->S1 = (stack*)malloc(sizeof(stack));Q->S2 = (stack*)malloc(sizeof(stack));
Q->S1->date = (int*)malloc(sizeof(int)*MAXLEN);
Q->S2->date = (int*)malloc(sizeof(int)*MAXLEN);
Q->S1->top = Q->S2->top = 0;
return Q;
}
/* push元素时, 只往S1中push */
void myQueuePush(MyQueue* obj, int x) {
obj->S1->date[obj->S1->top++] = x;
}
/* pop元素时, S2非空时, 弹出; S2为空, S1数据导入S2中, 继续从S2弹出数据 */
int myQueuePop(MyQueue* obj) {
if((obj->S2->top)>0)
return obj->S2->date[--(obj->S2->top)];
while(obj->S1->top > 0){
obj->S2->date[obj->S2->top] = obj->S1->date[--(obj->S1->top)];
obj->S2->top++;
}
return obj->S2->date[--(obj->S2->top)];
}
int myQueuePeek(MyQueue* obj) {
if((obj->S2->top)>0)
return obj->S2->date[(obj->S2->top)-1];
while(obj->S1->top > 0){
obj->S2->date[obj->S2->top] = obj->S1->date[--(obj->S1->top)];
obj->S2->top++;
}
return obj->S2->date[obj->S2->top-1];
}
bool myQueueEmpty(MyQueue* obj) {
return obj->S1->top == 0&&obj->S2->top==0;
}
/* 释放申请的空间 */
void myQueueFree(MyQueue* obj) {
free(obj->S1->date);
obj->S1->date = NULL;
free(obj->S2->date);
obj->S2->date = NULL;
free(obj->S1);
obj->S1 = NULL;
free(obj->S2);
obj->S2 = NULL;
free(obj);
obj = NULL;
}
234.回文链表
链表题乱入😀
typedef struct ListNode ListNode;
ListNode* getHalf(ListNode* head) {
ListNode* fast = head;
ListNode* slow = head;
while (fast->next != NULL && fast->next->next != NULL) {
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
ListNode* reverseList(ListNode* head) {
ListNode* prev = NULL;
ListNode* curr = head;
while (curr != NULL) { //不断的切断再重组的方式不断迭代形成反转
ListNode* nextTemp = curr->next;
curr->next = prev;
prev = curr;
curr = nextTemp;
}
return prev; //返回逆序后的头指针
}
bool isPalindrome(struct ListNode* head) {
if (head == NULL) {
return true;
}
// 找到前半部分链表的尾节点并反转后半部分链表
ListNode* half = getHalf(head);
ListNode* secondHalfStart = reverseList(half->next);
// 判断是否回文
ListNode* p1 = head;
ListNode* p2 = secondHalfStart;
bool result = true;
while (result && p2 != NULL) {
if (p1->val != p2->val) {
result = false;
}
p1 = p1以上是关于10.18--一下午连肝20道leetcode题(纯C实现)的主要内容,如果未能解决你的问题,请参考以下文章
漫话算法[二分查找](上):一首诗解决5道LeetCode题