首页 > 编程语言 >【算法训练营day1】LeetCode704. 二分查找 LeetCode27. 移除元素

【算法训练营day1】LeetCode704. 二分查找 LeetCode27. 移除元素

时间:2022-10-12 13:45:34浏览次数:72  
标签:二分 val LeetCode704 int nums day1 移除 numslen 指针

【算法训练营day1】LeetCode704. 二分查找 LeetCode27. 移除元素

LeetCode704. 二分查找

题目链接:704. 二分查找

初次尝试

看到题目标题是二分查找,所以尝试使用二分查找的思想,代码思路是一直循环二分,直到两个指针相等,再判定所指元素是否等于target,这样对于任何输入都需要二分至尽头才能得出结论,果不其然提交后超时。

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

看完代码随想录后的想法

意识到了不需要对于任何输入都二分到尽头,可以在二分的过程中判断target是否与二分的中间点相等,如果相等就可以直接返回中间点的下标(当然这是在数组元素都不重复的前提下)。这是符合逻辑的,毕竟如果在二分判定的过程中已经找到了和target相等元素的下标,何必继续二分到尽头呢?直接返回不就完事了!

关于题解中讲到的循环不变量,也就是左闭右闭等的问题,我感觉对我个人不是难点,在初次尝试中就有类似的思考过程,感觉对于边界开闭的留意已经是一种习惯了,故在此不再赘述。

class Solution {
public:
    int search(vector<int>& nums, int target) {
        int low = 0, up = nums.size() - 1;
      
        // 左闭右闭
        while (low <= up) {
            int mid = (low + up) / 2;
            if (target < nums[mid]) up = mid - 1;
            else if (target > nums[mid]) low = mid + 1;
            else return mid;
        }
         
        return -1;
    }
};

LeetCode27. 移除元素

题目链接:27. 移除元素

初次尝试

思路是使用暴力解法,直接两个for循环,外层遍历数组,内层寻找等于val的元素并更新数组。

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

然后想到当有连续多个等于val的元素时,每个都要更新一次实在是平添时间复杂度,于是修改了一下,当遇到连续多个等于val的元素时,判定一下有几个,然后一次性更新数组,看似优化了,其实换汤不换药,仍然是嵌套着的for循环,没有大的优化。

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int numslen = nums.size();
      
        for (int i = 0; i < numslen; i++) {
            int k = 0;
            for (int j = i; j < numslen; j++) {
                if (nums[j] == val) k++;
                else break;
            }
            if (k > 0) {
                for (int j = i + k; j < numslen; j++) {
                    nums[j-k] = nums[j];
                }
                numslen -= k;
            }
        }
      
        return numslen;
    }
};

看完代码随想录后的想法

双指针真是yyds!其实看到题解视频的开头我就突然明白怎么用双指针了,定义一个慢指针和一个快指针,快指针负责遍历整个数组,找出可以留下来的元素,每找到一个就把它告诉慢指针,慢指针只需要听令,把可以留下来的元素放到现在的坑里,然后+1跳到下一个坑即可。之所以有快慢指针之分是因为每次for循环,快指针都会+1,而慢指针看情况+1(当快指针指向可以留下来的元素的时候),所以慢指针一定不快于快指针。

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

今日的小想法

对于刷题初期的我,感觉看到题目首先想到的还是如何暴力解出来,然后再进行优化,而题解往往有一些另辟蹊径的解法,所以多积累解题技巧是现阶段的主要任务。今日用时:约4h

标签:二分,val,LeetCode704,int,nums,day1,移除,numslen,指针
From: https://www.cnblogs.com/BarcelonaTong/p/16784235.html

相关文章

  • Python学习路程——Day12
    Python学习路程——Day12global与nonlocal'''global: 是一个内置方法,它的作用是在函数体内声明一个全局名称空间,让这个全局名称空间可以在函数体内的局部名称空间中被......
  • day10-习题
    习题1.Homework01(1) D--没有在别名上加引号(ps:别名的as可以省略)(2) B--判断null或非空不能用不等于号(3) C2.Homework02写出查看dept表和emp表的结构的sql......
  • 代码随想录day17
    110.平衡二叉树递归法:1classSolution{2public:3//递归三步走4//1、确定返回值和函数参数5intgetHeight(TreeNode*node){6//......
  • 禁用或者移除 Ubuntu 中的 cloud-init
    https://www.jianshu.com/p/2fcfee762877cloud-init简介是为解决云环境中,对新建虚拟机的初始化配置问题,所提供的一个解决方案,若你的非云环境,完全可以关闭它。它......
  • Python学习路程——Day11
    Python学习路程——Day11函数参数在使用函数参数时,一般情况下所需要遵循的规范: 越短的、越简单的、越靠前 越长的、越复杂的、越靠后同一个形参在调用的时候不能多......
  • 进入python的世界_day10_python基础——函数之参数、名称空间
    一、位置参数位置形参​ 函数定义阶段(函数定义第一行)括号内从左往右,依次填写变量名位置实参​ 函数调用阶段括号内从左往右,依次填写传入的数据值"""1.位置形参......
  • 代码随想录 day18|513. 找树左下角的值 112. 路径总和 113. 路径总和 II 105. 从前序
    513.找树左下角的值题目|文章1.前序遍历思路题目的要求是先是最底层最左边的节点的值,我们使用前序遍历可以保证是最左边的值,通过深度变化时对节点更新,可以保证是最底......
  • 快捷键Day1
    Ctrl+c复制Ctrl+v粘贴Ctrl+x剪切Ctrl+z撤回Ctrl+s保存Alt +F4关闭窗口Shift+Delete永久删除windows+r 打开指令面板windows+e打开我的电脑Ctrl+Shif......
  • Python学习路程——Day10
    Python学习路程——Day10定义函数''' 函数的使用必须遵循’先定义,后调用’的原则。函数的定义就相当于事先将函数体代码保存起来,然后将内存地址赋值给函数名,函数名就是......
  • Day10函数基础学习以及计算机硬盘修改数据的原理(了解)
    今日内容概要文件内光标的移动实战演练计算机硬盘存取数据的原理文件内容修改函数简介函数的语法结构函数的定义与调用内容详细文件内光标移动案例(了解)im......