LEETCODE 704.二分查找+27.移除元素 +34. 在排序数组中查找元素的第一个和最后一个位置+35. 搜索插入位置

文章介绍了使用二分法解决查找、删除元素以及确定元素搜索范围的问题。在C++代码实现中,强调了避免溢出和优化算法效率的重要性,对比了不同解题策略,如使用双向指针和交换元素的技巧。

704:主要运用二分法查找,下面是第一次写的代码,题目比较简单,长时间没写C++语法快忘光了,这里有个疑问,为什么计算flag(mid)值的时候要避免溢出?

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int sta = 0;
        int en = nums.size()-1;
        int res= -1;
        while(sta <= en)
        {
            int flag = 0;
            if((en + sta) % 2 == 0)
            {
                flag = (en + sta) / 2; 
            }
            else
            {
                flag = (en + sta + 1) / 2;
            }
            if(nums[flag] < target)
            {
                sta = flag + 1;
            }
            else if(nums[flag] > target)
            {
                en = flag-1;
            }
            else
            {
                res = flag;
                break;
            }
        }
        return res;
    }
};

10-17行更正:

int falg = (sta - en) / 2 + en;

27.移除元素

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int len = nums.size();
        for(int i = 0; i < nums.size(); i++)
        {
            if(nums[i] == val)
            {
                nums[i] = nums[i] ^ nums[len-1];
                nums[len-1] = nums[i] ^ nums[len-1];
                nums[i] = nums[i] ^ nums[len-1];
                len--;
            }
        }
        return len;
    }
    
};

这是错误代码,没法在交换的时候保证交换的两个元素有一个不等于val

9-12行应该进行更改

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

//作者:LeetCode-Solution
//链接:https://leetcode.cn/problems/remove-element/solution/yi-chu-yuan-su-by-leetcode-solution-svxi/
//来源:力扣(LeetCode)
//著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

看了第二种双向指针的方法,感觉自己第一种方法有两个问题:

1,总想着交换,实际不用

2,“赋值”过后没有再次检查,陷入每次循环i必须增加的固定思维中

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int len = nums.size();
        int i = 0;
        while( i < len)
        {
          if(nums[i] == val)
          {
              nums[i] = nums[len-1];
              len--;
          }
          else
          i++;
        }
        return len;
    }
    
};

34题用二分法

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size()-1;
        if(right == -1 )
        {
            return vector<int>{-1 , -1};
        }
        int i = 0;
        while((nums[left] != target || nums[right] != target) && left < right)
        {
            int mid = left + (right - left) / 2;
            if(nums[mid] < target && nums[left] !=target)
            {
                left = mid + 1;
            }
            else if(nums[mid] > target && nums[right] !=target)
            {
                right = mid -1;
            }
            else if(nums[mid] == target)
            {
                if(nums[left] != target)
                {
                    left++;
                }
                if(nums[right] != target)
                {
                    right--;
                }
            }
        }
        if(nums[left] != target)
        {
            left = -1;
            right = -1;
        }
        return vector<int>{left, right};

    }
};

35题也是二分法,要逻辑清晰,知道应该插入哪里

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int left = 0;
        int right = nums.size()-1;
        if(right == -1)
        {
            return 0;
        }
        int len = 0;
        while(left < right)
        {
            len = left + (right - left)/2;
            if(nums[len] < target)
            {
                left = len + 1;
            }
            else if(nums[len] > target)
            {
                right = len-1;
            }
            else 
            return len;
        }
        if(nums[left] >= target)
        {
            return left;
        }
        else
        return left+1 ;

    }
};
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值