LeetCode 刷题 -- Day 1

今日题目

题目难度备注
1. 两数之和 暴力求解,需优化
704. 二分查找 - 力扣(LeetCode)简单不是很熟练
27. 移除元素 - 力扣(LeetCode)简单
977. 有序数组的平方 - 力扣(LeetCode)简单得加强双指针思想
209. 长度最小的子数组 - 力扣(LeetCode)中等
59. 螺旋矩阵 II - 力扣(LeetCode)中等♥♥♥

题目:1.两数之和

1. 两数之和 - 力扣(LeetCode)

一、 源代码

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> ans;
        for(int i=0;i<nums.size()-1;i++){
            for(int j=i+1;j<nums.size();j++){
                if(nums[i]+nums[j]==target){
                    ans.push_back(i);
                    ans.push_back(j);
                    return ans;
                }
            }
        }
        return {};
    }    
    
};

二、优化思路

考虑过把nums[i] 的值和 下标i 绑定在一起,但是却只想到用数组绑定,瞬间没有思路了。这是对数据结构的不熟悉,殊不知map 就是用来绑定两个数值的(当然其他数据类型也可以绑定)

把nums[i] 当key,i 当value,绑定后就好做了。令 x =nums[i],则只要在map中查找 target - x 就行,若查找成功则输出 “x = nums[i] ” 中的 i 和 map中的value就行;没查到说明没有满足的,直接把num[i] 和 i 压入map继续查找就行

三、优化代码

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> hamap;
        int x = -1;
        for (int i = 0; i < nums.size(); i++)
        {
            x = target - nums[i];
            if (hamap.find(x) != hamap.end())
            {
                return{ hamap.find(x)->second, i };
            }
            hamap[nums[i]] = i;
        }
        return {};  /*注意方法 一定要return;
    }
};


题目:977. 有序数组的平方

977. 有序数组的平方 - 力扣(LeetCode)

一、 源代码

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        vector<int> ans;
        for(int i = 0; i < nums.size() ; i++){
            int n = abs(nums[i]);
                ans.push_back(n*n);
        }
        sort(ans.begin(),ans.end());
        return ans;
    }
};

二、优化思路

数组a不降序且值从负到正,再平方插入数组b,要求b不降序;

若把数组a从下标0 到 a.size()-1 的值平方,所得的数组应该是先降序再升序;

处理两头大中间小,成不降序;用什么方法呢?当然是双指针,选择较大的数逆序放入b就行;

三、优化代码

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int n = nums.size();
        vector<int> ans(n);
        for (int i = 0, j = n - 1, pos = n - 1; i <= j;) {
            if (nums[i] * nums[i] > nums[j] * nums[j]) {
                ans[pos] = nums[i] * nums[i];
                ++i;
            }
            else {
                ans[pos] = nums[j] * nums[j];
                --j;
            }
            --pos;
        }
        return ans;
    }
};


X 题目:209. 长度最小的子数组

209. 长度最小的子数组 - 力扣(LeetCode)

一、 源代码

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int a[200][200];  //a[i][j]表示i与j 之间连续子数组和
        a[0][0] = nums[0];
        int ans = 1e9,flag;
        for(int j=1;j<nums.size();j++){
            a[0][j] = a[0][j-1] + nums[j];
        }
        for(int i = 0,flag = 0; i < nums.size(); i++){
            for(int j = nums.size() - 1; j >= 0; j--){
                if(a[i][j] < target){
                    flag = 1;
                    break;
                }
                if(a[i][j] == target && ans > j-i+1){
                    ans = j-i+1;
                }
                if(a[i][j] > target ){
                    a[i+1][j] = a[i][j] - nums[i];
                    a[i][j-1] = a[i][j] - nums[j]; 
                }

            }
        }
        return (ans==1e9)? 0:ans;
    }
};

二、错误原因

看错题目了,以为是找出该数组中满足其总和等于 target 的长度最小的 连续子数组 。原来是大于等于即可。那用一个for循环就行

三、改正代码

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int n = nums.size();
        if (n == 0) {
            return 0;
        }
        int ans = INT_MAX;
        vector<int> sums(n + 1, 0); 
        // 为了方便计算,令 size = n + 1 
        // sums[0] = 0 意味着前 0 个元素的前缀和为 0
        // sums[1] = A[0] 前 1 个元素的前缀和为 A[0]
        // 以此类推
        for (int i = 1; i <= n; i++) {
            sums[i] = sums[i - 1] + nums[i - 1];
        }
        for (int i = 1; i <= n; i++) {
            int target = s + sums[i - 1];
            auto bound = lower_bound(sums.begin(), sums.end(), target);
            if (bound != sums.end()) {
                ans = min(ans, static_cast<int>((bound - sums.begin()) - (i - 1)));
            }
        }
        return ans == INT_MAX ? 0 : ans;
    }
};

四、优化思路

源代码中其实存在很多问题:

1、为表示下标 i 到 j 中连续子数组值的和,居然选择用二维数组,这大大浪费了存储空间,而且二维数组并不能存多大,哪怕用个结构体都比这个好。

所以像本体求的连续子数组的和大于等于 target,是不是可以不用数组呢?靠双指针不停移动来更新ans

2、为了使用双指针不停移动来更新ans,选择了从两端往中间移动,先让 j = nums.size() - 1,若a[i] [j] > target 再分别讨论 a[i+1] [j] 和 a[i] [j-1] 这两种情况,这样则要么使用DFS,要么用二维数组或结构体(发现没有,其实可以不用数组)

所以若双指针 i,j 都从起点开始移动,会怎么样呢?定义sum为连续子数组值的和,sum < target 当然是 ++j,sum > target 那 j 不动,sum - nums[i] 后 i++,是不是比 i,j 从两端开始往中间移动好一点

五、优化代码

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int n = nums.size();
        if (n == 0) {
            return 0;
        }
        int ans = INT_MAX;
        int start = 0, end = 0;
        int sum = 0;
        while (end < n) {
            sum += nums[end];
            while (sum >= s) {
                ans = min(ans, end - start + 1);
                sum -= nums[start];
                start++;
            }
            end++;
        }
        return ans == INT_MAX ? 0 : ans;
    }
};


♥ X 题目:59. 螺旋矩阵 II

59. 螺旋矩阵 II - 力扣(LeetCode)

毫无思路

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值