LeetCode-01day

LeetCode01-两数之和

1.算法题目

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

2.算法思路

  1. 暴力枚举法
    将数组的每个元素都一一比较,例如先将第一个元素和后面所有元素相加,判断能不能得到target值,如果不能就用第二个元素和之后的所有元素来相加比较,以此类推,直到找到target值,如果循环下来没找到就返回空。
    其代码为:
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int i,j;
        for(i = 0;i<nums.size()-1;++i){
            for(j = i+1;j<=nums.size()-1;++j){
                if(nums[i] + nums[j] == target){
                    return {i,j};
                }
            }
        }
        return {};
    }
};

时间复杂度:O(n^2)。
优点:简单容易想到。
缺点:运行速度慢且内存空间消耗较大。

  1. 两遍哈希表
    使用哈希表的key、value思想,将数组数据存放在哈希表中,通过哈希表的算法来查找符合两数之和等于target值的数据,最后返回。
    其代码为:
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        //建立哈希表
        map<int,int> a;
        vector<int> b(2,-1);//存放返回值
        //将数据存入到哈希表中
        for(int i = 0;i<nums.size();++i){
            a.insert(map<int,int>::value_type(nums[i],i));  //前面是值,后面是值所在的位置
        }
        //查找
        for(int i=0;i<nums.size();++i){
        	//使用count函数来查找是否出现过两数之和等于target的值,同时也避免查找到值是i本身
            if(a.count(target-nums[i]) >0 && (a[target-nums[i]] != i)){
                b[0] = i;
                b[1] = a[target - nums[i]];
                break;
            }
        }
        return b;
    }
};

其中,count(key)是查找key出现的次数,代码中是查找是否有另外一个数能等于target减去i值,并且一般value = map[key],文中是i = a[nums[i]]。
优点:大大减少了内存的消耗并且运行速度也得到了很大的提升。

  1. 哈希表改进
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        map<int,int> a;
        vector<int> b(2,-1);
        for(int i=0;i<nums.size();i++)
        {
            if(a.count(target-nums[i])>0)
            {
                b[0]=a[target-nums[i]];
                b[1]=i;
                break;
            }
            a[nums[i]]=i;
        }
        return b;
    };
};

刚开始哈希表内是没有数据的,在循环函数内将每一个键值对都放入表中,直到找到判断函数被调用的时候。

  1. 双指针
    直接贴代码
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<int> ids(nums.size());
        iota(ids.begin(), ids.end(), 0);
        sort(ids.begin(), ids.end(), [&](int& a, int& b){return nums[a] < nums[b];});
        
        int left = 0, right = ids.size() - 1;
        while (left < right) {
            int res = nums[ids[left]] + nums[ids[right]];
            if (res < target) {
                left++;
            } else if (res > target) {
                right--;
            } else {
                break;
            }
        }

        return vector<int>{ids[left], ids[right]};
    }
};

其中,itoa代码是将ids填充为从0开始的递增序列,之后sort进行排序,以lambda表达式中的逻辑进行排序,也就是升序排序,之后进行逻辑判断,跟二分查找算法逻辑有点像。

LeetCode11-盛最多水的容器

1.算法题目

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器。

2.算法思路

  1. 双指针
    首先要知道水量的算法逻辑,先定义一个left和一个right以及num来分别表示左指针、右指针、水量存放。水量的宽是确定了的,主要是看水量的高度,当left表示数组的第一个元素,right表示数组的最后一个元素,假设left位置的值大于right位置的值,如果移动left那么水量的面积只有两种可能,要么保持不变要么变小,不可能变大;反过来移动right就有多种可能了,可能变大可能变小可能不变。所以移动的时候只能移动小的那一边才可能得到最大值。
    代码如下:
class Solution {
public:
    int maxArea(vector<int>& height) {
        int left = 0,right = height.size()-1,num = 0;
        while(left<right){
            num = height[left] > height[right] ? 
            max(num,(right-left)*height[right--]):
            max(num,(right-left)*height[left++]);
        }
        return num;
    }
};

在这还要注意一个问题,我刚开始也一直没发现,发现的时候感觉自己好蠢,max函数中必须要将height[right–]和height[left++]放在最后,因为如果你放在前面,你调用数组元素的时候已经使用了left或者right值了,那么它就会自动加一或者减一这会影响后面的right-left的值,从而得不到正确的水量值。

LeetCode15-三数之和

1.算法题目

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

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

2.算法思路

  1. 暴力枚举
    直接三层循环每个都枚举一遍,这样也能得到三元组,但是会因为时间的关系无法通过测试。
    代码:
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        int i,j,k;
        vector<vector<int>> ans;
        sort(nums.begin(),nums.end());
        for(i = 0;i<nums.size();i++){
            for(j = i+1;j<nums.size();j++){
                for(k = j+1;k<nums.size();k++){
                    if(nums[i] + nums[j]+ nums[k] == 0)
                        ans.push_back({nums[i],nums[j],nums[k]});
                    while (k + 1 < nums.size() && nums[k] == nums[k + 1])k++;//重复的直接移动到最后	
                }
                while (j + 1 < nums.size() && nums[j] == nums[j + 1])j++;	//重复的直接移动到最后		
            }
            while (i + 1 < nums.size() && nums[i] == nums[i + 1])i++;	//重复的直接移动到最后	
        }
        return ans;
    }
};
  1. 双指针法
    这个跟前面那个两数之和逻辑其实差不多,只不过在双指针循环外面加了一层for循环,而在while循环外面首先要进行对第一个值的去重之后才能进行while循环,建立两个值分别指向i+1和nums.size()-1,并赋值给left和right。之后进行判断语句,首先判断三数相加和等于0的,如果是就将三个值插入到最开始所建立的res数组中,而插入之后也要进行去重,因为还要进行查找,left和right都需要进行去重。最后对三数之和大于0和小于0都进行相应的操作,这时候不需要去重了,最外层返回res数组。

代码如下:

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        //创建返回参数
        vector<vector<int>> res;
        //排序
        sort(nums.begin(),nums.end());
        for(int i = 0;i<nums.size();++i){
            //去重
            if(i > 0&&nums[i] == nums[i-1])
                continue;
            //双指针
            int left = i+1,right = nums.size()-1;
            while(left < right){
                if(nums[i] + nums[left] +nums[right] == 0){
                    res.push_back({nums[i],nums[left],nums[right]});
                    ++left;
                    //去重
                    while(left<right && nums[left-1] == nums[left])
                        ++left;
                    --right;
                    while(left<right && nums[right] == nums[right+1])
                        --right;
                }
                else if(nums[i] + nums[left] +nums[right] > 0){ 
                    --right;
                }
                else{
                    ++left;
                }
            }
        }
        return res;
    }
};

代码中要注意去重之前是进行了自增的操作,要相应的改一下判断语句。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
LeetCode-Editor是一种在线编码工具,它提供了一个用户友好的界面编写和运行代码。在使用LeetCode-Editor时,有时候会出现乱码的问题。 乱码的原因可能是由于编码格式不兼容或者编码错误导致的。在这种情况下,我们可以尝试以下几种解决方法: 1. 检查文件编码格式:首先,我们可以检查所编辑的文件的编码格式。通常来说,常用的编码格式有UTF-8和ASCII等。我们可以将编码格式更改为正确的格式。在LeetCode-Editor中,可以通过界面设置或编辑器设置来更改编码格式。 2. 使用正确的字符集:如果乱码是由于使用了不同的字符集导致的,我们可以尝试更改使用正确的字符集。常见的字符集如Unicode或者UTF-8等。在LeetCode-Editor中,可以在编辑器中选择正确的字符集。 3. 使用合适的编辑器:有时候,乱码问题可能与LeetCode-Editor自身相关。我们可以尝试使用其他编码工具,如Text Editor、Sublime Text或者IDE,看是否能够解决乱码问题。 4. 查找特殊字符:如果乱码问题只出现在某些特殊字符上,我们可以尝试找到并替换这些字符。通过仔细检查代码,我们可以找到导致乱码的特定字符,并进行修正或替换。 总之,解决LeetCode-Editor乱码问题的方法有很多。根据具体情况,我们可以尝试更改文件编码格式、使用正确的字符集、更换编辑器或者查找并替换特殊字符等方法来解决这个问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值