算法训练第一天|数组

Day 1 千里之行始于足下~

1. 704 二分查找法

第一次提交,未使用到数组升序排序的已知条件,归结为暴力求解法,直接遍历求解

下面是二分求解法的内容:
左闭右开:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int iLen = nums.size();
        int iRes = -1;
        if(iLen == 0) return iRes;
        if(iLen == 1) { return nums[0] == target? 0: -1;}
        int iLeft = 0;
        int iRight = iLen - 1;
        while(iRight - iLeft + 1 > 2)
        {
            int iMid = (iRight - iLeft) / 2 + iLeft;//此处要加入偏移
            if(nums[iMid] > target)
            {
                iRight = iMid;
            }
            else if(nums[iMid] < target)
            {
                iLeft = iMid + 1; //加1 才算左闭右开
            }
            else
            {
                iRes = iMid;
                return iRes;
            }
        }
        return nums[iLeft] == target ? iLeft : (nums[iRight] == target ?  iRight :  iRes);
    }
};

左闭右闭:

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int iLen = nums.size();
        int iRes = -1;
        if(iLen == 0) return iRes;
        if(iLen == 1) { return nums[0] == target? 0: -1;}
        int iLeft = 0;
        int iRight = iLen - 1;
        while(iRight - iLeft + 1 > 2)
        {
            int iMid = (iRight - iLeft) / 2 + iLeft;
            if(nums[iMid] > target)
            {
                iRight = iMid - 1;
            }
            else if(nums[iMid] < target)
            {
                iLeft = iMid + 1;
            }
            else
            {
                iRes = iMid;
                return iRes;
            }
        }
        return nums[iLeft] == target ? iLeft : (nums[iRight] == target ?  iRight :  iRes);
    }
};

多判断了数组0、1、2,简洁一些的代码:
左闭右闭

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int iRight = nums.size() - 1;
        int iLeft = 0;
        int iRes = -1;
        while(iLeft <= iRight)
        {
            int iMid = iLeft + (iRight - iLeft) / 2;
            if(nums[iMid] < target)
            {
                iLeft = iMid + 1;
            }
            else if(nums[iMid] > target)
            {
                iRight = iMid - 1;
            }
            else
            {
                return iMid;
            }
        }
        return iRes;
    }
};

相关题目: 35 34 69 367
2. 27移除元素

解答:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        nums.erase(std::remove(nums.begin(), nums.end(), val), nums.end());
        return nums.size();
    }
};

下面是vector一些删除函数:

  1. erase()
    接受一个迭代器或者两个迭代器,删除范围内的元素
std::vector<int> v = {1, 2, 3, 4, 5};
auto it = std::find(v.begin(), v.end(), 3); // 查找值为3的元素
if (it != v.end()) {
    v.erase(it); // 删除找到的元素
}
// v 现在包含 {1, 2, 4, 5}
  1. clear()
    删除vector中的所有元素
std::vector<int> v = {1, 2, 3, 4, 5};
v.clear(); // 清除所有元素
// v 现在为空
  1. pop_back()
    删除最后一个元素
std::vector<int> v = {1, 2, 3, 4, 5};
v.pop_back(); // 删除最后一个元素
// v 现在包含 {1, 2, 3, 4}
  1. resize()
    虽然 resize 主要用于改变 std::vector 的大小,但如果你将大小减小到小于当前大小,它也会删除多余的元素。
std::vector<int> v = {1, 2, 3, 4, 5};
v.resize(3); // 删除最后两个元素
// v 现在包含 {1, 2, 3}
  1. 使用 swap 方法配合临时 vector
    这是一种高效删除多个元素的方法,尤其是当你不需要保留元素的顺序时。
std::vector<int> v = {1, 2, 3, 4, 5};
v.erase(std::remove(v.begin(), v.end(), 3), v.end()); // 删除所有值为3的元素
// v 现在包含 {1, 2, 4, 5}(元素的顺序可能已改变)

这里,std::remove 并没有真正删除元素,而是将不想要的元素移动到容器的末尾,并返回一个指向新逻辑末尾的迭代器。然后,你可以使用 erase 和这个迭代器来删除这些不想要的元素。
请注意,std::vector 管理其内部元素的内存,因此当你从 std::vector 中删除元素时,你不需要(也不应该)手动调用 delete。相反,std::vector 会在适当的时候自动调用析构函数并释放内存。
双指针思路:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int iLen = nums.size();
        int iFast = 0;
        int iSlow = 0;
        for(iFast = 0;iFast < iLen; iFast++)
        {
            if(nums[iFast] != val)
            {
                nums[iSlow++] = nums[iFast];
            }
        }
        return iSlow;
    }
};
  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值