leetcode刷题(第一天)数组理论基础,704.二分查找,27.移除元素

今日任务:数组理论基础,704.二分查找,27.移除元素

卡哥建议:(1)了解一下数组基础,以及数组的内存空间地址,数组也没那么简单。

                  (2)把 704 掌握就可以,35.搜索插入位置 和 34. 在排序数组中查找元素的第一个和最后一个位置.

重点:要熟悉 根据 左闭右开,左闭右闭 两种区间规则 写出来的二分法

链接:代码随想录:代码随想录 (programmercarl.com)

补充:35搜索插入位置;34在排序数组中查找元素的第一个和最后一个位置;69.X的平方根;367.有效的完全平方数

数理论基础组

代码随想录

1.数组是存放在连续内存空间上的相同类型数据的集合。

2.数组下标都是从0开始的。

3.数组的内存空间的地址是连续的

注意事项:因为数组的内存空间地址是连续的,所以我们在删除或者增添元素时,就难免需要移动其他元素的地址。(因此数组的元素不能删除,只能覆盖。)

int arr[2][3] =
	{
		{0,1,2},
		{3,4,5}
	};
	cout << &arr[0][0] << "  " << &arr[0][1] << "  "
		<< &arr[0][2] << "  " << &arr[1][0] << "  "
		<< &arr[1][1] << "  " << &arr[1][2] << "  "
		<< endl;

地址一般为16进制且连续;A代表10,"ABCDEF0123456789"类推.

704.二分查找

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

文章链接:代码随想录

视频链接:手把手带你撕出正确的二分法 | 二分查找法 | 二分搜索法 | LeetCode:704. 二分查找_哔哩哔哩_bilibili

第一想法第一次写:只想着遍历,没有时间概念,就遍历返回了;

划重点:有序数组--无重复元素--使用二分法

注意:边界条件确定好;[left,right]和[left,right)

class Solution {
public:
    int search(vector<int>& nums, int target) {
        //设置区间;
        int left=0;
        int right=nums.size()-1;
        //进行二分法算法设计
        while(left<=right)
        {
            //设置二分中间值,注意防溢出;int向下取整
            int middle=left+(right-left)/2;
            //条件判断--三种情况
            //target>middle,上半区间,左边界变化
            if(target>nums[middle])
            {
                left=middle+1;//已经大于了,所以+1;
            }
            //target<middle,下半区间,右边界变化
            else if(target<nums[middle])
            {
                right=middle-1;
            }
            //最后就剩相等了
            else
            {
                return middle;

            }
        }
        //如若都不符合,返回-1
        return -1;
    }
};

第二种写法为边界[left,right)

class Solution {
public:
    int search(vector<int>& nums, int target) {
        //设置区间;
        int left=0;
        //注意不能-1;否则少了数组最后一个元素
        int right=nums.size();
        //进行二分法算法设计
        while(left<right)
        {
            //设置二分中间值,注意防溢出;int向下取整
            int middle=left+(right-left)/2;
            //条件判断--三种情况
            //target>middle,上半区间,左边界变化
            if(target>nums[middle])
            {
                left=middle+1;//已经大于了,所以+1;
            }
            //target<middle,下半区间,右边界变化
            else if(target<nums[middle])
            {
                right=middle;
            }
            //最后就剩相等了
            else
            {
                return middle;
            }
        }
        //如若都不符合,返回-1
        return -1;
    }
};

相关题目:35搜索插入位置;34在排序数组中查找元素的第一个和最后一个位置;69.X的平方根;367.有效的完全平方数

 27.移除元素

题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

文章讲解:代码随想录

视频链接:数组中移除元素并不容易! | LeetCode:27. 移除元素_哔哩哔哩_bilibili

注意:要知道数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。

此为暴力解法

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        //设置数组大小
        int size=nums.size();
        //遍历数组删除数值val
        for(int i=0;i<size;i++)
        {
            if(nums[i]==val)
            {
                //只能覆盖,不能删除
                for(int j=i+1;j<size;j++)
                {
                    nums[j-1]=nums[j];
                }
                 i--;
                size--;
            }
        }
        return size;
    }
};

while与if区别:

while语句属于循环语句,在判断是,如果条件为true,则会继续判断,直到false为止,即会进行多次判断(除非一开始条件就是错的)
if语句属于条件判断语句,如果条件是true,则继续执行,为false则跳出语句不执行,只会进行单次判断。

while与if语句的最大的相同点是都有至少一步的判断。
最大的不同点是:IF语句运行完毕后,接着运行下面的语句。而While中的执行语句运行完毕后,还要进行继续判断条件是否符合循环条件,根据判断的条件,返回执行语句或继续运行下面的程序。

双指针法

双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

定义快慢指针

  • 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
  • 慢指针:指向更新新数组下标的位置

其实就是用一个快指针遍历整个数组,当找到需要的数值时,慢指针操作(此题就是慢指针重写数组)

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        //设置数组大小
        int slowIndex=0;
        //设置快慢指针在一个for循环里面完成移除元素
        for(int fastIndex=0;fastIndex<nums.size();fastIndex++)
        {
            if(nums[fastIndex]!=val)
            {
                nums[slowIndex]=nums[fastIndex];
                slowIndex++;
                //nums[slowIndex++]=nums[fastIndex];慢指针更新在加1(也就是数组的长度)
                //快指针遍历,相当于旧数组重新写一遍,=val的不要就好了。
            }
        }
        return slowIndex;
    }
};

相向双向指针法

相当于一边从头出发找到不一样的就前进,找到一样的停下替换从后面找到的不一样的,疑惑的是,最后面的一样的咋办,就消失了,确实是有这样,因为左右一起走,这样的话右边不一样的就换全部换到左边,而一样的就被抛弃了,注意要left<=right;这样就全了

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        //相向双指针法
        //相当于一边从头出发找到不一样的就前进,找到一样的停下替换从后面找到的不一样的
        //疑惑的是,最后面的一样的咋办,就消失了
        //确实是有这样,因为左右一起走,这样的话右边不一样的就换全部换到左边,
        //而一样的就被抛弃了,注意要left<=right;这样就全了
        
        //相向双指针建立
        int leftIndex=0;
        int rightIndex=nums.size()-1;
        //建立循环条件
        while(leftIndex<=rightIndex)
        {
            //左边一直前进,寻找等于val的值
            while(leftIndex<=rightIndex && nums[leftIndex]!=val)
            {
                leftIndex++;
            }
            //右边寻找不等于val的值,
            while(leftIndex<=rightIndex && nums[rightIndex]==val)
            {
                rightIndex--;
            }
            //替换---需要添加if(leftIndex < rightIndex),防止=时,最后一个元素重复
            //因为=时仍会执行,这样leftIndex就会多加一位(此时leftIndex > rightIndex),等于rightIndex或    rightIndex--的值,这样就会多算一步
            if(leftIndex<rightIndex)
           {
               nums[leftIndex]=nums[rightIndex];
               leftIndex++;
               rightIndex--;
            }      
        }
        return leftIndex;
    }
};

相关题目:26.删除排序数组中的重复项;283.移动零;844.比较含退格的字符串;977.有序数组的平方

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值