zoukankan      html  css  js  c++  java
  • 力扣_中级算法_数组_1~4题

    一位C++小白的力扣刷题_成长记录_欢迎 visit  ^_^  ( 终于刷完初级啦~ 欧耶!)

     

    数组_第1题:三数之和

    题目描述:

    给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。

    注意:答案中不可以包含重复的三元组。  

    举例

    示例:

    给定数组 nums = [-1, 0, 1, 2, -1, -4],
    
    满足要求的三元组集合为:
    [
      [-1, 0, 1],
      [-1, -1, 2]
    ]

    解题思路: 先提示一点, “不包含重复的三元组” 的意思是,我举个栗子: 答案不能是 " [ -1,0,1 ] , [ -1,-1, 2 ] , [ -1 ,0 , 1 ] "。先排序,然后主要是解题工具就是——双指针。

    其实有三个指针,习惯说成双指针。就是三个指针在 给定的数组上 移动。 符合要求则 放入 “vector容器”的一层。

    学习心得:新学到sort()这个排序函数,可以减少我的记忆负担(即冒泡排序那些算法)。然后,主要一个难点

    就是“去重”(即去掉重复的答案),这一点利用 指针的移动和continue的结合 得以解决。

    实现:(C++)

    class Solution {
      public:
        vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> v;
        int size=nums.size();
        int left,right,mid;           //left:左指针。right:右指针。mid:中间指针
        if( size<=2 ) return v;          //特殊情况,特殊处理
        sort( nums.begin(),nums.end() );    //①新学到 List库 里的 sort( 起始指向,终点指向 ) 函数
        for( left=0;left<size;left++ )
          {
          if( left>0&&nums[left]==nums[left-1] )   //去重,也就是说,例如左指针只会在含有重复元素的 [ 1,2,2,2,-1 ] 中检索第一个2,后面的2都跳过
             continue;
          right=size-1;
          for( mid=left+1;mid<size;mid++ )
            {
               if( mid>left+1&&nums[mid]==nums[mid-1] )        //保证中间指针在左指针的右边,并且 “ 去重 ”
              continue;
            while( mid<right&&nums[left]+nums[mid]+nums[right]>0 )   //保证中间指针在右指针的左边,并且调整 右指针
              right--;
           if( mid==right ) break;              //如果 中间指针都和右指针重合了,说明 左指针和中间指针所加起来的数太小了,右指针指不到适合的数
             if( nums[left]+nums[mid]+nums[right]==0 )
                 v.push_back( { nums[left],nums[mid],nums[right] } );    //②新学到一个 push_back() 的书写格式
           }
        }
      return v;

      }

    };

    运行结果: 

    我的输入
    [-1,0,1,2,-1,-4]
    我的答案
    [[-1,-1,2],[-1,0,1]]
    预期答案
    [[-1,-1,2],[-1,0,1]]

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

    数组_第2题:矩阵置零

    题目描述:

     给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。

    举例:

    示例 1:

    输入: 
    [
      [1,1,1],
      [1,0,1],
      [1,1,1]
    ]
    输出: 
    [
      [1,0,1],
      [0,0,0],
      [1,0,1]
    ]
    

    示例 2:

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

    进阶:

    • 一个直接的解决方案是使用  O(mn) 的额外空间,但这并不是一个好的解决方案。
    • 一个简单的改进方案是使用 O(m + n) 的额外空间,但这仍然不是最好的解决方案。
    • 你能想出一个常数空间的解决方案吗?

    解题思路:我是想的是 先用一个队列来 储存矩阵里出现 “0” 的元素的下标。 记录完后 再在原矩阵上 “动手脚”。、

    学习心得:这是一个笨方法,力扣上有更好的方法。但是这个方法是我自己想出来的,也独立完成了,

    还是有点小开心,哈哈哈~ 待我第二遍刷到你时,再来切磋切磋!

    实现:(C++) 

    class Solution {
      public:
        void setZeroes(vector<vector<int>>& matrix) {
        int row_size=matrix.size(); //row_size 用来储存matrix行的个数
        int col_size=matrix[0].size(); //col_size 用来储存matrix每行中的元素的个数
        int row,col;
        queue<int> q; //一号小分队出来!
        int i,j;
        for( i=0;i<row_size;i++ )
           for( j=0;j<col_size;j++ )
          if( matrix[i][j]==0 ) //记录那些 背上含有“0”的 “间谍”
            {
               q.push( i );
             q.push( j );
              }
          for( i=0;!q.empty(); ) //只要队列不为空,说明还有 “间谍” 未被清除
           {
              row=q.front();
                q.pop();
             matrix[ row ].assign( col_size,0 ); //③新学到一个 vector库里的 assign( 坐标, 赋给那个坐标的值 )函数
             col=q.front();
             for( j=0;j<row_size;j++ )
                matrix[ j ][ col ]=0;
            q.pop(); //注意:“间谍”有横坐标和纵坐标,所以要pop()两次
           }
        }
    };

    运行结果:

    代码执行结果:
    我的输入
    [[1,1,1],[1,0,1],[1,1,1]]
    我的答案
    [[1,0,1],[0,0,0],[1,0,1]]
    预期答案
    [[1,0,1],[0,0,0],[1,0,1]]

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

    数组_第3题:字母异位词分组

    题目描述:

    给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

    举例:

    示例:

    输入: ["eat", "tea", "tan", "ate", "nat", "bat"]
    输出:
    [
      ["ate","eat","tea"],
      ["nat","tan"],
      ["bat"]
    ]

    说明:

    • 所有输入均为小写字母。
    • 不考虑答案输出的顺序。

    解题思路:灵活运用 哈希表(无序)。然后结合 sort() 函数,整理每个字符串,整理过后的 字母异位词 是相同的结果,然后他们就可以放入 同一个 键值对里面。

    到最后 一排排 地输出。

    学习心得:做了这道题,我又对这个哈希表啊,既爱又恨,爱是其功能强大,适合这道题,恨是很多

    关于maps的格式、库函数不了解,屡屡碰壁。

    实现:(C++)

    class Solution {
      public:
        vector<vector<string>> groupAnagrams(vector<string>& strs) {
        unordered_map<string,vector<string>> hashmap;     //构造一个 无序哈希表(unordered_map),key(键)对应string类型,val(值)对应vector属性的 string类型
        vector<vector<string>> v_res;
        string temp;            //temp是个打工仔,做做替身
        int index=0;
        for( auto s:strs )
          {
          temp=s;
          sort( temp.begin(),temp.end() );     //整理“打工仔”,例如:"eta"整理后为“aet”;“dcba”整理后为“abcd”
          hashmap[ temp ].push_back( s );      //如果哈希表中无“aet”这个key(键),则自动新建一个key(键)。并将未被“sort()”的字符串s放入
          }
        v_res.resize( hashmap.size() );         //④自学了 vector库里的resize( 整数数值 )函数
        for( auto it:hashmap )             //⑤原来auto还可以这样用,长知识了!
          {
          v_res[ index ]=it.second ;          //it是个迭代器。 类似于 C++ 中的对象(具有一些公有成员/共有成员函数)。it.second访问的it指向的val(值)
          index++;
         }
      return v_res;
     }
    };

    运行结果:

    代码执行结果:
    我的输入
    ["eat","tea","tan","ate","nat","bat"]
    我的答案
    [["bat"],["eat","tea","ate"],["tan","nat"]]
    预期答案
    [["bat"],["nat","tan"],["ate","eat","tea"]]

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

    数学_第4题: 无重复字符的最长子串

    题目描述:

    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

    举例:

    示例 1:

    输入: "abcabcbb"
    输出: 3 
    解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
    

    示例 2:

    输入: "bbbbb"
    输出: 1
    解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
    

    示例 3:

    输入: "pwwkew"
    输出: 3
    解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
         请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

    解题思路:双指针,再一次登场!再结合标准关联容器set (系统能根据元素的值自动进行排序)来解题。

    学习心得:今天第二次使用“双指针”,又是针对于 解决字符串 这样的题。然后今天学习到了 C++中set 这个库。

    在力扣 的官方解题思路中,提到“滑动窗口”,这个名词形容得很恰当。

    实现:(C++)

    class Solution {
      public:
        int lengthOfLongestSubstring(string s) {
        unordered_set<char> js;
        int n=s.size();
        int left,right=-1,res=0;       //left:左指针。right:右指针(至于为什么要赋初始值为 -1 ,是因为用于表示 s[ right+1 ] )
                        //其实刚开始我是不知道right应该赋什么初始值的,但是敲到后面,就发现赋值-1 更方便
        for( left=0;left<s.size();left++ )
          {
          if( left!=0 )          //如果left,即左指针下标值不为零,清除 前一位 的值。(只是清除,但那个位置依然保留)
          js.erase( s[left-1] );     //⑥新学到 set标准库 里的 erase( 数据 )函数。
          while( right<n-1&&!js.count( s[right+1] ) )      //⑦新学到 set标准库 里的 count( 数据 )函数。作用是:返回 set属性的对象中 某个值元素的个数

                                 //提醒一下,n不能换成s.size()。我现在还不知道为什么
            {
            js.insert( s[right+1] );      //⑧新学到 set标准库 里的 insert( 数据 )函数。作用:在集合中插入元素
            right++;            //插入一个元素后,右指针继续向右移动,循环,再判断
                }
            res=max( right-left+1,res );     //“ right-left+1 ” 是敲到后面,自然而然想到的
           }
      return res;
     }
    };

    运行结果:

    我的输入
    "abcabcbb"
    我的答案
    3
    预期答案
    3
  • 相关阅读:
    网页 js 获取DPI pxTomm
    利用自定义属性实现js点击事件 委托
    鼠标移动div时禁止选中div中的文字的方法
    关于if简写语句优化的方法
    .clearfix::after(清除浮动)
    js 事件委托
    清空共享池
    oracle中scott用户权限不足
    安装完Oracle 12C数据库,scott账户过期,解锁方法
    Vulnhub靶场-Me Tomcat Host 学习笔记
  • 原文地址:https://www.cnblogs.com/Wang-dou-dou/p/13303210.html
Copyright © 2011-2022 走看看