zoukankan      html  css  js  c++  java
  • 力扣_中级算法_数组_5~6题_和链表_1~2题

    一位C++小白的力扣刷题_成长记录_welcome to visit  ^_^  

     

    数组_第5题:最长回文子串

    题目描述:

    给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

    举例

    示例 1:

    输入: "babad"
    输出: "bab"
    注意: "aba" 也是一个有效答案。
    

    示例 2:

    输入: "cbbd"
    输出: "bb"

    解题思路:采用类似于哈希表的 标记法。在一个二维的 “ vector 容器 ” 里面做标记。 这里其实有一个动态规划的思想。在力扣的 官方解题思路里有,结合了数学公式,很详细。

    学习心得:做了这道题后,再一次让我感受到了 “数学思维”的重要性。 看官方解题思路,让我豁然开朗,

    虽然,看了答案后,在之后自己独立敲地过程中还是遇到了很多问题。但最后还是解决了,深入分析,真正

    弄懂了,小有成就。 嘿,等我第二遍来刷你时,我可不会手下留情的!

    实现:(C++)

    class Solution {
      public:
        string longestPalindrome(string s) {
        int n=s.size();
        vector<vector<int>> dp( n,vector<int>(n) );      //"()"里的n不能省去呀....
        string res;
        if ( n==1 ) return s;          //特殊情况,特殊处理
        int i,t;
        for( t=0;t<n;t++ )             //字符串s的有效长度为多少,就循环多少次
          for( i=0;i+t<n&&i+1<n;i++ )
          {
           if( t==0 )               //使“vector”二维容器里的对角线 上的数组值为1。即最短字符串
               dp[i][i+t]=1;
           else if( t==1 )         //如果 s[i]==s[i+t] ,注意 ,这里的t=1,即字符串里相邻的两个元素值相同时,对应“vector”二维容器里的元素 值赋为1
            dp[i][i+t] = ( s[i]==s[i+t] );
           else
              {
                 dp[i][i+t] = ( s[i]==s[i+t]&&dp[i+1][i+t-1] );     //首尾字符相同,字符串里面的 字符串是回文字符串 。前面两个条件满足,才能给“vector”二维容器里 相应的元素赋值为1
            }
            if( dp[i][i+t]&&t+1>res.size() )          //只有遇到“vector”二维容器里 标记为1的元素,说明才有 回文字符串。 注: t+1 其实是 (i+t)-i+1
                res=s.substr( i,t+1 );

         }
      return res;
      }
    };

    运行结果: 

    代码执行结果:
    我的输入
    "babad"
    我的答案
    "bab"
    预期答案
    "bab"

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    数组_第6题: 递增的三元子序列

    题目描述:

    给定一个未排序的数组,判断这个数组中是否存在长度为 3 的递增子序列。

    数学表达式如下:

    如果存在这样的 i, j, k,  且满足 0 ≤ i < j < k ≤ n-1,
    使得 arr[i] < arr[j] < arr[k] ,返回 true ; 否则返回 false 。

    说明: 要求算法的时间复杂度为 O(n),空间复杂度为 O(1) 。

    举例:

    示例 1:

    输入: [1,2,3,4,5]
    输出: true
    

    示例 2:

    输入: [5,4,3,2,1]
    输出: false

    解题思路:先找前两者 min 和 mid( middle 的意思),然后找第三者(即 max),这里需要注意的是,当遇到一个数,值在 min 和 mid 之间时,要把这个数值 赋给 mid。当遇到

    一个数,值小于 min 时,要把这个值 赋给min 。虽然可能遇到 这种情况 [ 1,2,0,3 ]  ,但你细品品,对于结果的 正确性,也是没问题的呦。

    学习心得:做这道题,主要在 min 和 mid 的初始化上,摔了很多坑。 mid不能由 数组中的某个元素赋值。

    应当 给他赋 INT_MAX。 具体原因,看看代码,想一想就懂了。这道题不难,刚开始我还满怀信心,以为

    我能凭一己之力,轻轻松松地将其解决。可是提交五六次都失败,害。原来呀,许多细节没做好。 渐渐醒悟,

    敲代码,是个细针手活呀~

    实现:(C++) 

    class Solution {
     public:
      bool increasingTriplet(vector<int>& nums) {
      if( nums.size()<=2 ) return false;
      int i,min=nums[0],mid=INT_MAX; // mid 得赋int类型的最大值:INT_MAX。 这样可以保证,只有执行过第一个 “else if” ,才有可能执行 第二个 “else if”,不然,

                                                                //可能还没执行第一个,直接执行第二个“else if”。
      for( i=1;i<nums.size();i++ )
        {
            if( nums[i]<min )
                  min=nums[i];
         else if( nums[i]<mid&&nums[i]>min )
             mid=nums[i];
         else if( nums[i]>mid )
             return true;
        }
      return false;
     }
    };

    运行结果:

    代码执行结果:
    我的输入
    [1,2,3,4,5]
    我的答案
    true
    预期答案
    true

    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    链表_第1题:两数相加

    题目描述:

    给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

    如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

    您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

    举例:

    示例:

    输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
    输出:7 -> 0 -> 8
    原因:342 + 465 = 807

    解题思路:我的解题思路是,先使两个链表对位对齐,没有的 用 “0” 来补上(申请动态空间来补)。然后进行逐位相加,并把进制问题认真处理。

    学习心得:练习了这道题后,我仿佛看到了一些更深远的东西。 int型、double型 始终只能分别表示32位、64位。

    但这链表可长着了! 这让我明白了为什么 π (圆周率)可以写到小数点后 一亿位。 所得斯勒!I got it!做了这

    道题,也让我再次熟悉了一下链表操作,以及 申请动态空间的操作。

    实现:(C++)

    /**
    * Definition for singly-linked list.
    * struct ListNode {
    * int val;
    * ListNode *next;
    * ListNode(int x) : val(x), next(NULL) {}
    * };
    */
    class Solution {
      public:
        ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        ListNode *head=new ListNode(-1);      //哑结点
        ListNode *fp=head;        //用来移动的指针
        ListNode *p=l1;          //l1是指向链表头的头指针,一般不动它,另外建立一个指针来使用
        ListNode *q=l2;
        int flag=0,sum=0;        //flag 用来判断是否进位,其值要么是1,要么是0
        int len_1=0,len_2=0;
        if( l1==NULL ) return l2;
        if( l2==NULL ) return l1;
        while ( p->next!=NULL ) { len_1++; p=p->next; }      //注意,这里有个细节,while() 循环的括号里是“ p->next!=NULL ”,而不是 “ p!=NULL ”。如果不这样,在后面 就不能在 l1的链表末尾

                                  //新生成一个结点。因为如果不这样,p就指向了 “空”,生成的结点 并没有和 l1的链表末尾连接起来。
        while ( q->next!=NULL ) { len_2++; q=q->next; }
        if( len_1>len_2 )
            while( len_1>len_2 )
               { q->next=new ListNode (0); q=q->next; len_2++; }
        else if( len_1<len_2)
             while( len_1<len_2 )
                 { p->next=new ListNode (0); p=p->next; len_1++; }
        while( l1!=NULL&&l2!=NULL )
        {
           sum+=l1->val+l2->val;       //sum用来记录相加结果
           l1=l1->next;
           l2=l2->next;
           fp->next=new ListNode( (sum+flag)%10 );  //sum要加上 上两位数相加后的 进位标记flag的值
           fp=fp->next;
          if( (sum+flag)>=10 )
              flag=1;
          else
              flag=0;
          sum=0;
        }
        if( flag==1 )      //如果最后,flag值还为1,就再申请一个 结点
            fp->next=new ListNode( 1 );
        return head->next;      //返回 哑结点的下一位结点的地址
          }
    };

    运行结果:

    代码执行结果:
    我的输入
    [2,4,3]
    [5,6,4]
    我的答案
    [7,0,8]
    预期答案
    [7,0,8]

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    链表_第2题: 奇偶链表

    题目描述

    给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。

    请尝试使用原地算法完成。你的算法的空间复杂度应为 O(1),时间复杂度应为 O(nodes),nodes 为节点总数。

    举例:

    示例 1:

    输入: 1->2->3->4->5->NULL
    输出: 1->3->5->2->4->NULL
    

    示例 2:

    输入: 2->1->3->5->6->4->7->NULL 
    输出: 2->3->6->7->1->5->4->NULL

    说明:

    • 应当保持奇数节点和偶数节点的相对顺序。
    • 链表的第一个节点视为奇数节点,第二个节点视为偶数节点,以此类推。

    解题思路:我的思路就是,在构造一个链表,两次遍历,分别储存 目标链表的 奇位数的 、偶位数的 结点。

    学习心得:原地算法,害,我的小脑瓜想不出来呀。 现在,我能独立完成一道中等难度的题就有点小满足了。

    虽然心里还是力求更高,但少年,别慌,咱们慢慢磨刀。第二遍时,优化,优化。

    实现:(C++)

    /**
    * Definition for singly-linked list.
    * struct ListNode {
    * int val;
    * ListNode *next;
    * ListNode() : val(0), next(nullptr) {}
    * ListNode(int x) : val(x), next(nullptr) {}
    * ListNode(int x, ListNode *next) : val(x), next(next) {}
    * };
    */
    class Solution {
      public:
        ListNode* oddEvenList(ListNode* head) {
        ListNode* res=new ListNode(-1);     //哑结点
        ListNode* fp=res;
        ListNode* h=head;
        int i=1;
        while( h!=NULL )
          {
             if( i%2==1 )       //先储存奇位数的 结点
          {
            fp->next=new ListNode( h->val);
            fp=fp->next;
            h=h->next;
               }
           else
                 h=h->next;
           i++;
           }
        i=1;
        h=head;                 //准备好第二次遍历
        while( h!=NULL)
         {
             if( i%2==0)      //在储存偶位数的 结点
          {
             fp->next=new ListNode( h->val);
             fp=fp->next;
             h=h->next;
            }
          else
             h=h->next;
          i++;
         }
      return res->next;
     }
    };

    运行结果:

    代码执行结果:
    我的输入
    [1,2,3,4,5]
    我的答案
    [1,3,5,2,4]
    预期答案
    [1,3,5,2,4]


  • 相关阅读:
    链表补充及链表和数组的区别
    单链表(不带头结点)
    动态数组
    【笔记】SQL语言的设计与编写
    netty 学习笔记一:感受 IO编程 NIO编程 与 Netty 编程
    分享系列——Thread#join() 在 Java 源码中并没有 notify ,被阻塞线程是如何唤醒的?答案在 JVM
    RabbitMQ 安装 图笔记版
    RabbitMQ 安装——RPM 和 TAR 两种方式
    学原理脱坑 之 centos 6/7 更新 UTC 以及 设置系统时区
    数据结构和算法篇——散列表
  • 原文地址:https://www.cnblogs.com/Wang-dou-dou/p/13311253.html
Copyright © 2011-2022 走看看