代码随想录算法训练营第一天 | LeetCode 704. 二分查找,27. 移除元素,26.删除排序数组中的重复项,283.移动零,844.比较含退格的字符串,977.有序数组的平方

LeetCode 704. 二分查找

题目链接:704. 二分查找

视频讲解

题目描述:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

主要思想:二分查找

难点:while循环中“=”问题,right/left更新时是否有+-1

int left = 0;
int right = n - 1; //数组长度为n
while(left op1 right) //op1为<或<=
{
    int middle = left + (right - left) / 2;
    if(nums[middle] > target) right = middle (- 1); //是否-1
    else if(nums[middle] < target) left = middle (+ 1); //是否+1
    else return middle;
}
return -1;

左闭右闭

思想:左端点和右端点都可以取到

对op1,因为left和right都可以取到,故当他们取“=”是合法的,所以op1为<=

因nums[middle]>target和nums[middle]< target,此时知nums[middle]一定不是所需要的数,所以right和left均不能取到middle值,要比middle值大1或小1,故有+1,-1。

int left = 0;
int right = n - 1; //数组长度为n
while(left <= right) //op1为<或<=
{
    int middle = left + (right - left) / 2;
    if(nums[middle] > target) right = middle - 1; //是否-1
    else if(nums[middle] < target) left = middle + 1; //是否+1
    else return middle;
}
return -1;

左闭右开

思想:左端点可以取到和右端点不可以取到

对op1,因为right不可以取到,故当他们取“=”是不合法的,所以op1为<

因nums[middle]>target和nums[middle]< target,此时知nums[middle]一定不是所需要的数,所以right能取到middle值而left不能取到middle值,left要比middle值大1。

int left = 0;
int right = n; //数组长度为n
while(left < right) //op1为<或<=
{
    int middle = left + (right - left) / 2;
    if(nums[middle] > target) right = middle; //是否-1
    else if(nums[middle] < target) left = middle + 1; //是否+1
    else return middle;
}
return -1;

题目特征

有序数组

无重复元素

 总结

判断条件:当前值取到是否合法

LeetCode 27. 移除元素

题目链接:27. 移除元素

视频讲解

题目描述:给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。

假设 nums 中不等于 val 的元素数量为 k,要通过此题,您需要执行以下操作:

  • 更改 nums 数组,使 nums 的前 k 个元素包含不等于 val 的元素。nums 的其余元素和 nums 的大小并不重要。
  • 返回 k。

示例 1:

输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2,_,_]
解释:你的函数函数应该返回 k = 2, 并且 nums 中的前两个元素均为 2。
你在返回的 k 个元素之外留下了什么并不重要(因此它们并不计入评测)。

主要思想:快慢指针

fast指针:寻找新数组的元素,新数组就是不包含要删除元素的数组

slow指针:更新新数组

代码实现:

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

题目特征

原地改变数组

删除等于val的元素

LeetCode中移除元素扩展题 

LeetCode 26.删除排序数组中的重复项

题目链接:26.删除排序数组中的重复项

题目描述:给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

  • 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
  • 返回 k 。

解题思路:

双指针思想,fast位于数组第二个位置开始增加一个判断条件即nums[fast-1] != nums[fast]

代码:

class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
        int len = nums.size();
        int slow = 0;
        for(int fast = 0; fast < len; fast++)
        {
            if(fast == 0) nums[slow++] = nums[fast];
            else
            {
                if(nums[fast-1] != nums[fast]) nums[slow++] = nums[fast];
            }
        }
        return slow;
    }
};

 题目特征

非严格递增数组

原地改变数组

删除重复元素只保留1个

LeetCode 283.移动零

题目链接:283.移动零

题目描述:给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

代码:

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int slow = 0;
        for(int fast = 0; fast < nums.size(); fast ++)
        {
            if(nums[fast] != 0) nums[slow++] = nums[fast];
        }
        for(int i = slow ; i < nums.size(); i++)
        {
            nums[i] = 0;
        }
    }
};

 解题思路:

同LeetCode 27.移除元素,不同点在于最后要从slow开始补0

题目特征:

原地改变数组

等于0的元素放在数组末尾

LeetCode 844.比较含退格的字符串

题目链接:844.比较含退格的字符串

题目描述:给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true 。# 代表退格字符。

注意:如果对空文本输入退格字符,文本继续为空。

示例 1:

输入:s = "ab#c", t = "ad#c"
输出:true
解释:s 和 t 都会变成 "ac"。

 解题思路:

双指针法应用,若遇到‘#’,slow--。最后使用substr()函数获取子串判断是否相等。

代码:

class Solution {
public:
    bool backspaceCompare(string s, string t) {
        int slow1 = 0, slow2 = 0;
        int len1 = s.size();
        int len2 = t.size();
        for(int fast = 0; fast < len1; fast ++)
        {
            if(s[fast] != '#') s[slow1++] = s[fast];
            else {
                if(slow1 >= 1) slow1--;
            }
            
        }

        for(int fast = 0; fast < len2; fast ++)
        {
            if(t[fast] != '#') t[slow2++] = t[fast];
            else 
            {
                if(slow2 >= 1) slow2--;
            }
        }

        if(slow1 == 0 && slow2 == 0) return true;
        else if((slow1 != 0 && slow2 == 0) ||(slow2 != 0 && slow1 == 0)) return false;
        else {
            string ss = s.substr(0,slow1);
            string tt = t.substr(0,slow2);
            return ss == tt;
        }
    }
};

题目特征:

删除当前值和前一个值

原地变换

注意点:

若‘#’位于开头,则slow不要--

LeetCode 977.有序数组的平方

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

题目描述:给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

示例 1:

输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

 解题思路:

开辟一个新数组ans,将原数组区间分为正区间和负区间,指针i从负数区间中左端开始,指针j从正数区间中右端开始,比较过程中较大的数从右至左依次放置在ans数组中

代码:

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

题目特征:

非递减数组

元素平方后从小到大排列

双指针题目总结 

使用场景:

数组原地变换删除某元素

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值