代码随想录训练营-10day:栈和队列2

一、20.有效的括号

该题是栈的思想的体现,在解决过程中,利用栈的特性,把括号对一对一对消除。在解决问题过程中,遇到几个问题

1 如果len不能被2整除,那么永远消除不完,直接false;

2 括号对匹配,把数组index向前移动,可能还剩下其他字符,因此消除了可以消除的括号对,如果还有“)” 、“] ”、“}”这三个类型的在前面,那么一定不能消除!

下面我写了2种写法:

#if 0
bool isValid(char* s) {
    char* str = (char*)malloc(strlen(s));
    char* dumpstr = (char*)malloc(strlen(s));
    int index = -1;
    int dumidx = -1;
    if(strlen(s) % 2)
    {
        return false;
    }

    for(int i = 0; i < strlen(s); i++)
    {
        if(s[i] == '(' || s[i] == '{' || s[i] == '[')
        {
            str[++index] = s[i];
        }
        else
        {
            dumpstr[++dumidx] = s[i];
        }
        /**如果index 不为-1,那么之前填入了字符**/
        if(index >= 0 && dumidx >=0)
        {
            if(s[i] == ')' || s[i] == '}' || s[i] == ']')
            {
                //printf("12 index = %d char = %c %c\n", index, s[i], str[index]);
                if(dumpstr[dumidx] == ')' && str[index] == '(')
                {
                    index--;
                    dumidx--;
                }
                else if(dumpstr[dumidx] == '}' && str[index] == '{')
                {
                    index--;
                    dumidx--;
                }
                else if(dumpstr[dumidx] == ']' && str[index] == '[')
                {
                    index--;
                    dumidx--;
                }
                else
                {
                    return false;
                }
            }
        }
        //printf("2 index = %d\n", index);
    }
    //printf("last index = %d\n", index);
    if(index < 0 && dumidx < 0)
      return true;
    else
      return false;
}
#else
//优化思路:malloc数组2个,可以减少1个,
bool isValid(char* s) {
    char* str = (char*)malloc(strlen(s));
    //char* dumpstr = (char*)malloc(strlen(s));
    int index = -1;
    //int dumidx = -1;
    if(strlen(s) % 2)
    {
        return false;
    }

    for(int i = 0; i < strlen(s); i++)
    {
        if(s[i] == '(' || s[i] == '{' || s[i] == '[')
        {
            str[++index] = s[i];
        }
        /**如果index 不为-1,那么之前填入了字符**/
        if(index >= 0)
        {
            if(s[i] == ')' || s[i] == '}' || s[i] == ']')
            {
                //printf("12 index = %d char = %c %c\n", index, s[i], str[index]);
                if(s[i] == ')' && str[index] == '(')
                {
                    index--;
                   
                }
                else if(s[i] == '}' && str[index] == '{')
                {
                    index--;
                    
                }
                else if(s[i] == ']' && str[index] == '[')
                {
                    index--;
                    
                }
                else
                {
                    return false;
                }
            }
        }
        else
        {
            if(s[i] == ')' || s[i] == '}' || s[i] == ']')
            {
                return false;
            } 
        }
        //printf("2 index = %d\n", index);
    }
    //printf("last index = %d\n", index);
    if(index < 0)
      return true;
    else
      return false;
}
#endif

二、1047 删除字符串相邻的字符

利用栈的思想,把首个字符写入字符数组str,然后遍历字符s,从i = 1开始,如果遇到了相等的字符,那么str index减1,这里有一个点,就是index会减到-1,需要另外判断,重新开始赋值,从下一个字符开始,s的i也对应加1(注意不要越界),完成所有的字符遍历,然后字符串str最后加\0

代码如下:

char* removeDuplicates(char* s) {
    char* str = (char*)malloc(strlen(s));
    if(s == NULL) return NULL;
    str[0] = s[0];
    int idx = 0;
    /**indx**/
    for(int i = 1; i < strlen(s); i++)
    {
        if(idx == -1)
        {
          str[++idx] = s[i];
          if(i < strlen - 1) i++;

          //printf("f str%d = %c i= %d\n",idx, str[idx], i);
        }
        if(str[idx] == s[i])
        {
            /**遇到可以消除的字符对**/
            // printf("str = %c\n", str[idx]);
            idx--;
           // printf("idx = %d\n", idx);
        }
        else
        {
            idx++;
            str[idx] = s[i];
        }
    }
    str[++idx] = '\0';
    return str;
}

三、150. 逆波兰表达式求值

栈的经典应用,c语言中没有栈相关的直接函数,思路一就是创建一个栈,并例化栈的操作,然后利用栈的操作来解决该题目;其二就是利用栈的思想,用数组作为栈,来解决该题,以下是利用数组方式解决的方案:

解决过程遇到的问题:

1 需要考虑不满足的情况:1)因为加减乘除是双目运算符,因此至少要2个数字才能组成一个计算式,如果第一个字符串或者第二个字符串不是数字,那么不可能算对;2)如果只有一个数字,那么返回原数字;3)如果长度为0 ,即没字符串,那么返回-1;

2 字符转换函数需要判断是正数还是负数,一开始并没有判断正负数,导致计算失误;

3 判断是否是数字串,这里需要注意负数和减法的符号是一样的,因此,需要做判断,如果字符串len有且仅有1个,那么就是减法,否则是负数,那么就是数字,需要保存到数组。

4 判断运算符后,加减乘除,除法和减法,需要理清楚被除数和被减数,另外拿出来2个数字,计算回一个数字,index指向下一个;

/**字符转换函数**/
int transNum(char* s)
{
   int num = 0;
   int index = 0;
   if(s[0] == '-')
   {
      //负数处理
        for(int i = strlen(s) -1; i > 0; i--)
        {
            if(s[i] <= '9' && s[i] >= '0')//0 ~9
            {
                num += (s[i] - '0') * pow(10 , index);
                index++;
            }
        }
        num = 0 - num;
   }
   else
   {
        for(int i = strlen(s) -1; i >= 0; i--)
        {
            if(s[i] <= '9' && s[i] >= '0')//0 ~9
            {
                num += (s[i] - '0') * pow(10 , index);
                index++;
            }
        }
   }

   return num;
}
bool judgeNum(char* s)
{
    /**考虑负数**/
    if(s[0] == '-')
    {
        //后面有数字
        for(int i = 1; i < strlen(s); i++)
        {
            if(s[i] > '9' || s[i] < '0')//0 ~9
            {
                return false;
            }
        }
        if(strlen(s) == 1)
          return false;//考虑到'-'字符一个的情况
    }
    else
    {
        for(int i = 0; i < strlen(s); i++)
        {
            if(s[i] > '9' || s[i] < '0')//0 ~9
            {
                return false;
            }
        }
    }
    return true;
}
int evalRPN(char** tokens, int tokensSize) {
    //char* arr = (char*)malloc(tokensSize);
    int* nums = (int*)malloc(sizeof(int) * tokensSize);
    //int nums[1000] = {0};
    int index = 0;
    //int cal_value = 0;
    /**判断不合规的结构:如果一开头不是数字,那么表达式结构有误; 或者只有一个数字**/
    if(tokensSize == 1)
    {
        return transNum(tokens[0]);
    }
    if(tokensSize == 0 || judgeNum(tokens[0]) == false || judgeNum(tokens[1]) == false)
    {
        //不是数字,+ - * /都是双目运算符
        return -1;
    }
    //printf("size = %d\n", tokensSize);
    for(int i = 0; i < tokensSize; i++)
    {
        if(judgeNum(tokens[i]))
        {
           nums[index] = transNum(tokens[i]);
           //printf("num%d = %d\n",index, nums[index]);
           index++;
        }
        else
        {
           index--;//回到上一次位置,拿到数字
           char p = tokens[i][0];
           //printf("p is %c, index = %d\n", p, index);
           int a = 0;
           int b = 0;
           switch(p)
           {
              case '+':
               /**计算结果重新填进去**/
               a = nums[index--];
               b = nums[index];
               nums[index] = a + b;//覆盖掉之前的数据
              break;
              case '-':
               a = nums[index--];
               b = nums[index];
               nums[index] = b - a;
              break;
              case '*':
               a = nums[index--];
               b = nums[index];
               nums[index] = b * a;
              break;
              case '/':
               a = nums[index--];
               b = nums[index];
               nums[index] = b / a;
              break;
           }
           //跳一个位置,保存数字,继续进行计算
           index++;
           //printf("switch index = %d\n", index);
        }
    }
    return nums[0];
}

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值