2019-06-22啊有宋神的鼎力相助今天的力扣刷的也是很开心呢然后现在题库到了数据结构部分真的触及到我的知识盲区了呢……我觉得有必要总结一下关于堆栈和链表的使用,毕竟这是我最薄弱的环节了嘤嘤嘤加油哇

今日份力扣,第一题,判断括号的有效性,开始理解错了题意,选择相邻组成对判断以及左右对称判断的方法,可能是双指针前几题用的太多,这次也用的双指针……然鹅没有考虑全面,错在了({})[]这种情况上,它既不属于对称情况,也不属于成组成组的方式,因此这个方法彻底失败了!

然后看了解析,发现大家都用堆栈,仔细查了查堆栈的使用,看了一些CSDN上的总结,发现堆栈的确适合这种整体无序、小区间有序的问题。然鹅,知道了用法,在思路上又出现了许多问题,比如最低几个循环?push进去然后怎么做呢?

后来跟宋神讨论了一下,找到了正确的思路,就是只用一个循环遍历string s,碰见左括号就push进去,碰见右括号就对比和stack中的top是否正确匹配,正确的话直接pop出去,完成一组的查找,否则return false。思路想的挺对,但是后期还是有些问题,比如")("这种情况,第一个是有括号,而stack里面是空的,top自然不存在,这样就会报错,因而需要加一个判断stack是否empty的判断,还有的就是一些语句的位置,至关重要,下面是代码:

class Solution 
{
public:
    bool isValid(string s) 
    {
        int l=s.length();
        int i,j;
        if(s==" ") return true;
        if(l%2!=0) return false;
        stack<char>m;
        for(i=0;i<l;i++)
        {
            if(s[i]=='('||s[i]=='['||s[i]=='{')
                m.push(s[i]);
            else if(!m.empty())
            {
            if(s[i]==')'&&m.top()=='(')
                        m.pop();
            else if(s[i]==']'&&m.top()=='[')
                        m.pop();
            else if(s[i]=='}'&&m.top()=='{')
                        m.pop();  
            }    
            else return false;
        }
        if(m.empty())
            return true;
        else return false;
    }
};

最后判断条件是stack是否为空。

然后总结一下对堆栈的认识……

原来我天真的以为,堆栈可以随便pop就像erase一样,然而这失去了它作为一个堆栈的尊严……它的最大特点就是后来居上,先进后出,隐含意思就是有序性,不可以随意pop,插队可耻!如果是随意erase这题不如用vector,stl还很多,堆栈的太少了,以至于我搜半天堆栈遍历以及对栈元素查找是没什么结果的,是的啊,这是对它最本质特征的错误认识,查找元素大概只能全pop一遍,检查top值……

新建语句和vector一样,基本stl就是size()、empty()、push()、pop()、top()……

第二道题是简单的将两个有序链表拼接为一整个有序链表,听起来很简单,思路也很简单,然而我就是写不动,因为对链表太陌生了,无从下手的感觉,幸亏大佬的答疑解惑,这道题大概是我有史以来做的最快的一道了吧……

贴代码!

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution 
{
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) 
    {
      ListNode* head=new ListNode(0);
       ListNode* ss=head;  
      while(l1!=NULL&&l2!=NULL)
      {
          if(l1->val>=l2->val)
          {
           ss->next=l2;
           ss=ss->next;
           l2=l2->next;
          }
          else 
          {
              ss->next=l1;
              l1=l1->next;
              ss=ss->next;
          }
      }
        if(l1!=NULL)
           ss->next=l1;
        else ss->next=l2;
        return head->next;
    }
};

首先新建链表,并进行一个初始化,我就不会了……

ListNode* head=new ListNode(0);
ListNode* ss=head; 

head用来固定头结点,并进行初始化,赋值为0,注意返回的是head->next;

然后我经常犯错的一点是,链表的移动问题,我习惯写成ss++,这当然是错的!正确的是让ss指向next:

ss=ss->next;

这次很庆幸,自己记得处理了指针的越界问题,瞎几把乱指造成的bug我已经见过千千万万变了,所以这句

while(ss->next!=NULL)可以说是时时刻刻记在心中,保证不越界之后,再好好考虑跳出循环的位置,进行下一步判断、拼接……

希望自己有一天对链表了如指掌……

要有梦想!!!

这只是一些自己的小tips,摘抄别人的我可能也记不住,针对自己的问题进行总结吧!

感谢今天的木头人,mua!!

 

发布了42 篇原创文章 · 获赞 16 · 访问量 2898

猜你喜欢

转载自blog.csdn.net/weixin_44412218/article/details/93341855
今日推荐