打卡——【LeetCode学习计划】《数据结构入门-C++》第2天 数组

原文链接;【LeetCode学习计划】《数据结构入门-C++》第2天 数组_Wang_Xin_Ling的博客-CSDN博客

目录

1. 两数之和LeetCode: 1. 两数之和

方法一:暴力破解 

方法2:哈希表方法1中时间复杂度较高的原因是内层寻找target-x的复杂度较高,

主要是思路:

88. 合并两个有序数组LeetCode: 88. 合并两个有序数组

方法1:合并后排序

方法2:双指针

方法3:逆向双指针


1. 两数之和
LeetCode: 1. 两数之和

题目:

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
 

 

思路: 我们先找到一个数,我们设为x,则另外的一个数就是target - x

于是我们可以使用两重循环,外层确定一个x,内层寻找target-x

方法一:暴力破解 

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        const int n = nums.size();
        for(int left = 0;left < n;left++)
        {
            for(int right = left +1;right<n;right++)
            {
                if(nums[left] + nums[right] ==target)
                {
                    return {left,right};
                }
            }
        }
        return {};
    }
};

 

方法2:哈希表
方法1中时间复杂度较高的原因是内层寻找target-x的复杂度较高,

而使用哈希表,可以使查找target-x的时间复杂度从O ( n ) ——> O(1)。

主要是思路:

对于每一个x,先查找target-x是否在哈希表中,若在则返回答案。然后把x插入到哈希表中。
 

 解析

1.什么是vector
向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。

2.c++的容器——unordered_map,它是一个关联容器,内部采用的是hash表结构,拥有快速检索的功能 参考文章 STL—unordered_map 哈希表_ZS_Wang_Blogs的博客-CSDN博客

3.auto it = hashtable.find(target - nums[i]);
            if (it != hashtable.end())
                return {it->second, i};
            hashtable[nums[i]] = i;

1)it->first和it->second相当于键和值   对应map<int,int> 就是类似python中的字典

2)hashtable[nums[i]]=i相当于插入操作 

3)find函数返回的是一个迭代器(就是索引)

4)it是一个指针    存了哈希表每一项的信息

5)auto it = hashtable.find(target - nums[i]); if (it != hashtable.end())

这两个组合在一起的意思是 元素如果在哈希表中

则  证明找到return 键值对 和 i(就是x的索引)


这几行代码总体意思就是找到 target - x 元素的下标

#include<vector>
#include<unordered_map>
using std::unordered_map;
using std::vector;
class Solution
{
public:
    vector<int> twoSum(vector<int> &nums,int target)
    {
        unordered_map<int, int> hashtable;
        for(int i = 0;i <nums.size();i++)
        {
            auto it = hashtable.find(target - nums[i]);
            if (it != hashtable.end())
                return {it->second,i};
            hashtable[nums[i]] = i;
        }
        return {};
    }
};

88. 合并两个有序数组
LeetCode: 88. 合并两个有序数组

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
 

方法1:合并后排序

最暴力的方法就是把nums2的所有元素先插入到nums1的后面,然后对nums1进行排序

#include<vector>
#include<algorithm>
using namespace std;
class Solution
{
public:
    void merge(vector<int> &num1,int m,vector<int> &num2,int n)
    {
        for (int i = 0;i<n;i++)
        {
            num1[m+i] = num2[i];
        }
        sort(num1.begin(),num1.end());
    }
};

方法2:双指针

题目中提到两个数组都是已排序好的,于是我们在各数组的起始项设置一个指针,这样我们就能从小至大遍历2个数组了。每次遍历,将两个指针指向的更小的那个值存入一个新数组ans。最后将整个ans复制到nums1中即可

字有点丑,博主在坚持每天练字了

#include <vector>
using namespace std;
class Solution
{
public:
    void merge(vector<int> &nums1, int m, vector<int> &nums2, int n)
    {
        int p1 = 0, p2 = 0, p = 0;
        int *ans = new int[m + n];
        while (p1 < m && p2 < n)
        {
            if (nums1[p1] < nums2[p2])
            {
                ans[p] = nums1[p1];
                p1++;
                p++;
            }
            else
            {
                ans[p] = nums2[p2];
                p2++;
                p++;
            }
        }
        while (p1 < m)
        {
            ans[p] = nums1[p1];
            p1++;
            p++;
        }
        while (p2 < n)
        {
            ans[p] = nums2[p2];
            p2++;
            p++;
        }
        for (int i = 0; i < m + n; i++)
        {
            nums1[i] = ans[i];
        }
    }
};

方法3:逆向双指针


方法2中需要用到中间数组的根本原因是:我们在确认nums1每个位置最终的元素时,又要保持原数组nums1不变。

而方法3的入手点在于:nums1数组的后半部分是无效值,也就是说这一部分的值是不用维护的。这样一来,我们可以在nums1和nums2数组的末项处各设置一个指针,每次将更大的元素存入nums1,这样就不会覆盖掉nums1中任何未被遍历的值,而且也省去了用于维护的中间数组。

字有点丑,博主在坚持每天练字了

#include <vector>
using namespace std;
class Solution
{
public:
    void merge(vector<int> &nums1, int m, vector<int> &nums2, int n)
    {
        int p1 = m - 1, p2 = n - 1, p = m + n - 1;
        while (p1 >= 0 && p2 >= 0)
        {
            if (nums1[p1] < nums2[p2])
            {
                nums1[p] = nums2[p2];
                p2--;
                p--;
            }
            else
            {
                nums1[p] = nums1[p1];
                p1--;
                p--;
            }
        }
        while (p1 >= 0)
        {
            nums1[p] = nums1[p1];
            p1--;
            p--;
        }
        while (p2 >= 0)
        {
            nums1[p] = nums2[p2];
            p2--;
            p--;
        }
    }
};


Guess you like

Origin blog.csdn.net/qq_62932195/article/details/121798877