力扣刷题笔记(12)

嗯,沉寂了这么久,我又回来了。

照旧,一篇三题,不过现在是中等难度了。


第一题:三数之和

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

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

示例:

给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:

[
  [-1, 0, 1],
  [-1, -1, 2]
]

第二题:矩阵置0

给定一个 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)
的额外空间,但这仍然不是最好的解决方案。 你能想出一个常数空间的解决方案吗?

第三题:字母异位词分组

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

示例:

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

说明:

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


我的题解(1)

如果直接对数组使用三个for循环进行寻找,时间复杂度为O(n^3);
优化方法首先对数组进行排序,使用两数之和等于第三数的负数寻找。使用两个指针指向首尾,向中间移动寻找合适的值。
时间复杂度是O(n^2)

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> result;
        int num = nums.size(); 
        sort(nums.begin(),nums.end());
        if(nums.empty() || nums.front()>0 || nums.back()<0)
            return {};
        for(int i = 0;i<num-2;i++){
            if(nums[i]>0) break;
            if(i>0&&nums[i] == nums[i-1]) continue;
            int head = i+1;
            int tail = num-1;
            while(head<tail){
                if(nums[head]+nums[tail] == -nums[i]){
                    if(head == i+1 || tail == num-1){
                        result.push_back(vector<int>{nums[i],nums[head],nums[tail]});
                        head++;tail--;
                    }else if(nums[head] == nums[head-1]){
                        head++;
                    }else if(nums[tail] == nums[tail+1]){
                        tail--;
                    }else{
                        result.push_back(vector<int>{nums[i],nums[head],nums[tail]});
                        head++;tail--;
                    }
                }else if(nums[head]+nums[tail]<-nums[i]){
                    head ++;
                }else{
                    tail--;
                }
            }
        }
        return result;
    }
};

我的题解(2)

利用set的特性,将需要清零的行列坐标放入set,再清零。
空间复杂度:O(m+n)

class Solution {
public:
    void setZeroes(vector<vector<int>>& matrix) {
    if(matrix.empty())
        return;
    int r = matrix.size();
    int c = matrix[0].size();

    set<int> rs;
    set<int> cs;
    set<int>::iterator sit;

    //将有0的行列提取出来
    for (int i = 0; i < r; i++)
    {
        for (int j = 0; j < c; j++)
        {
            if (matrix[i][j] == 0)
            {
                rs.insert(j);
                cs.insert(i);
            }
        }
    }

    if (!cs.empty())
    {
        int a = c;
        vector<int> temp;
        while (a > 0)
        {
            temp.push_back(0);
            a--;
        }
        
        //将行清零
        for (sit = cs.begin(); sit != cs.end(); sit++)
        {
            matrix[*sit] = temp;
        }
    }

    //将列清零
    if (!rs.empty())
    {
        for (sit = rs.begin(); sit != rs.end(); sit++)
        {
            for (int k = 0; k< r; k++)
            {
                matrix[k][*sit] = 0;
            }
        }
    }
}
};

我的题解(3)

先将字符串内部排序,再利用map的特性,以排过序的字符串作为键值···

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) 
    {
        vector<vector<string>> res;
        map<string,vector<string>> vec;
        if(strs.empty()) return res;
        for(int i=0;i<strs.size();i++)
        {
            string temp=strs[i];
            sort(temp.begin(),temp.end());
            vec[temp].push_back(strs[i]);
        }
        map<string,vector<string>>::iterator it;
        for(auto it=vec.begin();it!=vec.end();it++)
        {
            res.push_back(it->second);
        }
        return res;
    }
};


官方题解(1)

排序 + 双指针

本题的难点在于如何去除重复解。

算法流程:

特判,对于数组长度 n,如果数组为 null 或者数组长度小于 3,返回 [ ]。

对数组进行排序。

遍历排序后数组:

若 nums[i]>0:因为已经排序好,所以后面不可能有三个数加和等于 0,直接返回结果。

对于重复元素:跳过,避免出现重复解

令左指针 L=i+1,右指针 R=n−1,当 L<R 时,执行循环:

当 nums[i]+nums[L]+nums[R]==0,执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 L,R 移到下一位置,寻找新的解

若和大于 0,说明 nums[R] 太大,R 左移
若和小于 0,说明 nums[L] 太小,L 右移

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        
        n=len(nums)
        res=[]
        if(not nums or n<3):
            return []
        nums.sort()
        res=[]
        for i in range(n):
            if(nums[i]>0):
                return res
            if(i>0 and nums[i]==nums[i-1]):
                continue
            L=i+1
            R=n-1
            while(L<R):
                if(nums[i]+nums[L]+nums[R]==0):
                    res.append([nums[i],nums[L],nums[R]])
                    while(L<R and nums[L]==nums[L+1]):
                        L=L+1
                    while(L<R and nums[R]==nums[R-1]):
                        R=R-1
                    L=L+1
                    R=R-1
                elif(nums[i]+nums[L]+nums[R]>0):
                    R=R-1
                else:
                    L=L+1
        return res

作者:wu_yan_zu
链接:https://leetcode-cn.com/problems/3sum/solution/pai-xu-shuang-zhi-zhen-zhu-xing-jie-shi-python3-by/
来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

官方题解(2)

方法 2:O(1)空间的暴力 惊呆我

在上面的方法中我们利用额外空间去记录需要置零的行号和列号,通过修改原始矩阵可以避免额外空间的消耗。

算法

遍历原始矩阵,如果发现如果某个元素 cell[i][j] 为 0,我们将第 i 行和第 j 列的所有非零元素设成很大的负虚拟值(比如说 -1000000)。注意,正确的虚拟值取值依赖于问题的约束,任何允许值范围外的数字都可以作为虚拟之。
最后,我们便利整个矩阵将所有等于虚拟值(常量在代码中初始化为 MODIFIED)的元素设为 0。

class Solution {
  public void setZeroes(int[][] matrix) {
    int MODIFIED = -1000000;
    int R = matrix.length;
    int C = matrix[0].length;

    for (int r = 0; r < R; r++) {
      for (int c = 0; c < C; c++) {
        if (matrix[r][c] == 0) {
          // We modify the corresponding rows and column elements in place.
          // Note, we only change the non zeroes to MODIFIED
          for (int k = 0; k < C; k++) {
            if (matrix[r][k] != 0) {
              matrix[r][k] = MODIFIED;
            }
          }
          for (int k = 0; k < R; k++) {
            if (matrix[k][c] != 0) {
              matrix[k][c] = MODIFIED;
            }
          }
        }
      }
    }

    for (int r = 0; r < R; r++) {
      for (int c = 0; c < C; c++) {
        // Make a second pass and change all MODIFIED elements to 0 """
        if (matrix[r][c] == MODIFIED) {
          matrix[r][c] = 0;
        }
      }
    }
  }
}

作者:LeetCode
链接:https://leetcode-cn.com/problems/set-matrix-zeroes/solution/ju-zhen-zhi-ling-by-leetcode/
来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

官方题解(3)

跟我的差不多,人家是Java,我是C++.


总结:

我觉得,我要把这些题提取出一部分,这样写没啥意思了。

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 撸撸猫 设计师: 设计师小姐姐
应支付0元
点击重新获取
扫码支付

支付成功即可阅读