5.13——数组

数组是在程序设计中,把具有相同类型的若干元素按有序的形式组织起来的一种形式。

作为线性表的实现方式之一,数组中的元素在内存中是 连续 存储的,且每个元素占相同大小的内存。

数组通过 索引 快速访问每个元素的值。在大多数编程语言中,索引从 0 算起。

在不同的编程语言中,数组的实现方式具有一定差别。比如 C++ 和 Java 中,数组中的元素类型必须保持一致,而 Python 中则可以不同。相比之下,Python 中的数组(称为 list)具有更多的高级功能。

1. 两数之和

1.1 最直观的解法,也是最容易想到的算法,暴力遍历

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> answer;
        //将数组中的每一个元素都和后面的元素一一配对比较,时间复杂度是
        //(n-1)+(n-2)+(n-3)+...+1 = [(n-1)/2]*n = O(n^2)

        //空间复杂度,除了表达问题所需要的存储空间,另外借助了两个int变量
        //和一个确定为0或2个元素的数组,所以是常数级的复杂度,即O(1)
        for(int i=0;i<nums.size()-1;i++){
            for(int j=i+1;j<nums.size();j++){
                if(nums[i]+nums[j] == target){
                    answer.push_back(i);
                    answer.push_back(j);
                    return answer;
                }
            }
        }
        //若不存在符合条件的元素,则返回空的下标数组
        return answer;
    }
};

1.2 你可以想出一个时间复杂度小于 O(n2) 的算法吗?

多学点,后面回过头来再看(掩盖不了我的菜了😭) 

这里使用双指针需要提前对数组进行排序

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> answer;
        //。。。。。。。。。。//
        //用双指针,将时间复杂度降为O(n),需要先对nums进行排序才行
        int i = 0;
        int j = nums.size()-1;
        while(i!=j){
            //如果找到了符合条件的元素,将其下标放入返回数组,跳出循环
            if(nums[i]+nums[j]==target){
                answer.push_back(i);
                answer.push_back(j);
                break;
            }
            //若不符合条件,判断当前结果是否大于目标值
            //若大于,则移动数值大的指针
            if(nums[i]+nums[j]>target){
                if(nums[i]>nums[j]){
                    i++;
                }else{
                    j--;
                }
            }else{  //若小于,则移动数值小的指针
                if(nums[i]<nums[j]){
                    i++;
                }else{
                    j--;
                }
            }
        }
        return answer;
    }
};

2. 盛最多水的容器

2.1 最直观的解法,也是最容易想到的算法,暴力遍历(超出时间限制了🚫)

class Solution {
public:
    int maxArea(vector<int>& height) {
        //假设这两条线是第i和j条,那么它们围成的面积是 
        //|j-i|*min(height(i),height(j))
        int max = -1;
        int mh;
        //暴力破解,每两个元素都试一遍,时间复杂度是O(n^2)
        //空间复杂度,O(1)
        for(int i=0;i<height.size()-1;i++){
            for(int j=i+1;j<height.size();j++){
                //找高度小的
                if(height[i]<=height[j]){
                    mh = height[i];
                }else{
                    mh = height[j];
                }
                //计算面积
                int area = (j-i)*mh;
                if(area>max){
                    max = area;
                }
            }
        }
        return max;
    }
};

2.2 从算法上改进时间复杂度为O(n)

一个一个试没必要,我们从公式出发,目的是找到最大的面积,面积由底长和高度决定。可以用两个指针指向数组的一头一尾,慢慢靠里面移动,这就保证了底长一直是最大的,再移动高度值小的指针(🤔)

class Solution {
public:
    int maxArea(vector<int>& height) {
        //使用双指针,时间复杂度O(n)
        //空间复杂度依然是O(1)
        int i=0;
        int j=height.size()-1;
        int max = -1;
        int len;
        int h;
        int area;
        while(i!=j){
            len = j-i;
            h = height[j];
            if(height[i]<height[j])
                h = height[i];
            //求面积
            area = len*h;
            
            if(area>max){
                max = area;
            }

            if(height[i]<height[j]){
                i++;
            }else{
                j--;
            }
        }
        return max;
    }
};

这么一看,两数之和好像也可以用双指针

(看来数组里面运用双指针对于减少算法复杂度很有效)

3. 寻找两个正序数组的中位数

要从问题本身的特点出发,算法也是因题而异的

本来想着先合并再找中位数的,但是合并两个排好序的数组也是需要O(m+n)的时间复杂度的。要求算法的时间复杂度为 O(log(m+n)),这是对数级别的复杂度,首先就要想到要有除以2的操作了。2^k = m+n,k=log(m+n)。

中位数就是排在中间位置的数,或取中间两个数的平均值。

一般找规律都可以用特殊情况来找,两个数组分别求中位数,小的去掉左部分继续求,大的去掉右部分继续求,直到两个数组的中位数一致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值