力扣_中级算法_数组_1~4题

Posted wang-dou-dou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了力扣_中级算法_数组_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

 

以上是关于力扣_中级算法_数组_1~4题的主要内容,如果未能解决你的问题,请参考以下文章

力扣_中级算法_链表_第3题_和_树和图_第1~3题

力扣_初级算法_其他_2~6题_和_数组_10~11题

力扣_初级算法_树_4~5题_和_排序和搜索_2题_和动态规划_1~4题

力扣_初级算法_链表_1~6题

力扣_初级算法_树_1~3题_和_排序和搜索_1题

力扣_初级算法_字符串_5~8题