首页 > 编程语言 >代码随想录算法训练营第一天| LeetCode 704. 二分查找、LeetCode 27. 移除元素

代码随想录算法训练营第一天| LeetCode 704. 二分查找、LeetCode 27. 移除元素

时间:2023-07-26 17:37:23浏览次数:40  
标签:cout int 元素 随想录 左闭 查找 数组 移除 LeetCode

704. 二分查找

        题目链接:https://leetcode.cn/problems/binary-search/       视频链接:https://www.bilibili.com/video/BV1fA4y1o715         文章讲解:https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html

       卡哥的题目建议 大家能把 704 掌握就可以,35. 搜索插入位置 和 34. 在排序数组中查找元素的第一个和最后一个位置 ,如果有时间就去看一下,没时间可以先不看,二刷的时候在看。先把 704写熟练,要熟悉 根据 左闭右开,左闭右闭 两种区间规则 写出来的二分法。

       做题思路:

      1,先了解什么是二分查找:二分查找也称折半查找(Binary Search)。      2,再了解折半查找的实现原理:假设我们在有三个数的有序数组中查找一个目标数,这个目标数我们一开始也不知道是有序数组中的哪个数,只能通过把目标数与有序数组的中间数进行比较,进一步缩小范围(见下面的 3)来找到目标数。如果目标数比中间的数大,则在有序数组的后半部分进行查找;如果目标数比中间数小,则在有序数组的前半部分进行比较;如果相等,则找到了比较元素的位置。折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序(升序降序都可,我们默认升序)排列。

    3,确定在哪个范围里比较和查找,一开始大范围是在整个数组,当比较完了,我们就知道在前半部分或者后半部分的小范围里查找,还要更新小范围的边界值,在小范围里比较再细分成更小的范围,如此类推.........,这个范围数学化理解就是区间,区间可以分为左闭右闭,左闭右开,(这两种区间用得多),我自己比较好理解左闭右闭这种方式的。

我没用力扣的环境运行,用的是vs,看了视频后,就差不多能理解代码了,用左闭右闭方式的完整代码如下:

 

 1 #include <iostream>
 2 using namespace std;
 3 const int N = 10;
 4 int a[N]; //声明全局数组
 5 int BinarySearch(int a[], int target)
 6 {
 7     int left = 0, right = sizeof(a) - 1; //左闭右闭区间范围为[left, right],即[0, n-1],left,right,也是数组下标
 8     int middle; //数组的中间数的下标
 9     while (left <= right) //在一个合法的区间里比较和查找,比如[1, 1],这个区间只有1,合法
10     {
11         middle = left + (right - left) / 2; //防止溢出 等同于(left + right)/2
12         if (target < a[middle]) //查找范围在数组的前半部分
13         {
14             right = middle - 1;//因为区间是左闭右闭,所以前半部分的右边界值不包含middle
15         }
16         else if (target > a[middle]) //查找范围在数组的后半部分
17         {
18             left = middle + 1;//因为区间是左闭右闭,所以后半部分的左边界值不包含middle
19         }
20         else if (target == a[middle])//目标数和数组中间数相等
21         {
22             return middle; //直接输出数组中间数的下标,break退出循环
23             break;
24         }    
25     }
26     return -1;
27 }
28 int main()
29 {
30     int n; //数组的元素个数为 n 
31     cout << "请输入数组的元素个数:" << endl;
32     cin >> n;
33     cout << "请输入数组:" << endl;
34     for (int i = 0; i < n; i++)
35     {
36         cin >> a[i]; //循环输入数组中的元素
37     }
38     cout << "请输入要查找的值:" << endl;
39     int target;  //目标数
40     cin >> target;
41     cout << BinarySearch(a, target) << endl;
42     
43     return 0;
44 }

 

       关于代码中的middle = left + (right - left) / 2, ,不理解溢出的话,就死记住吧。

 运行结果如下:

 

 

 

 

 27. 移除元素

       题目链接:https://leetcode.cn/problems/remove-element/

       视频讲解:https://www.bilibili.com/video/BV12A4y1Z7LP

       文章讲解:https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html

      卡哥的题目建议  暴力的解法,可以锻炼一下我们的代码实现能力,建议先把暴力写法写一遍。 双指针法 是本题的精髓,今日需要掌握,至于拓展题目可以先不看。 

        有两种方法:暴力解法和双指针法。

        暴力解法思路:用两个for循环,第一个for循环用来遍历数组,第二个for循环用来前移数据覆盖,就跟单链表的删除操作类似。完整代码如下:

 

 1 #include <iostream>
 2 using namespace std;
 3 const int N = 10;
 4 int a[N]; //声明全局数组
 5 int main()
 6 {
 7     int n; //数组的元素个数为 n 
 8     cout << "请输入数组的元素个数:" << endl;
 9     cin >> n;
10     cout << "请输入数组:" << endl;
11     for (int i = 0; i < n; i++)
12     {
13         cin >> a[i]; //循环输入数组中的元素
14     }
15     cout << "请输入要移除元素的值:" << endl;
16     int val;
17     cin >> val;
18     for (int i = 0; i < n; i++)//第一个循环是为了把遍历数组
19     {
20         if (a[i] == val) //判断数组的哪个数和要移除的数相等
21         {
22             for (int j = i; j < n; j++)//如果有一个数相等的话,那就从当前位置开始进行前移覆盖操作
23             {
24                 a[j] = a[j + 1];//数组的后一个数前移覆盖当前位置的数
25             }
26             i--; //覆盖后,数组的有效元素减一,更新i值
27             n--; //数前移移除后,原来数组的有效元素减一,更新n值
28         }    
29     }
30     cout << n << endl; 
31     return 0;
32 }

 

 

运行结果如下:

 

 

     

         双指针法做题思路:也称快慢指针法,通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。这个解法不用知道为啥,为了方便操作就行。

      快指针:寻找新数组的元素 ,新数组就是不含有要移除的元素的数组;

      慢指针:指向更新新数组下标的位置。

        完整代码如下:

 1 #include <iostream>
 2 using namespace std;
 3 const int N = 10;
 4 int a[N]; //声明全局数组
 5 int main()
 6 {
 7     int n; //数组的元素个数为 n 
 8     cout << "请输入数组的元素个数:" << endl;
 9     cin >> n;
10     cout << "请输入数组:" << endl;
11     for (int i = 0; i < n; i++)
12     {
13         cin >> a[i]; //循环输入数组中的元素
14     }
15     cout << "请输入要移除元素的值:" << endl;
16     int val;
17     cin >> val;
18     int slow = 0; //慢指针的变量
19     for (int fast = 0; fast < n; fast++)
20     {
21         if (val != a[fast]) //如果fast位置上的元素和要移除的元素不相等的话,
22         {
23             a[slow] = a[fast]; //就把fast位置上的元素覆盖成slow位置上的元素
24             slow++;//slow虽然是下标,但是它也记录了新数组的个数,自己看视频就会发现
25         }
26     }
27     cout << slow << endl; 
28     return 0;
29 }

 

 运行结果如下:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

标签:cout,int,元素,随想录,左闭,查找,数组,移除,LeetCode
From: https://www.cnblogs.com/romantichuaner/p/17581700.html

相关文章

  • LeetCode 560. 和为 K 的子数组
    classSolution{public:intsubarraySum(vector<int>&nums,intk){intn=nums.size(),res=0;vector<int>s(n+1,0);unordered_map<int,int>hash;//记录端点i之前所有前缀和的出现情况for(inti=1;i<=n;i++)......
  • go刷题Leetcode,生成文件夹与go文件模板
    go生成文件夹与模板起因以前是用C/C++刷Leetcode时,将多个C/CPP文件放在同一个目录下,没有出任何问题,但是换成Go语言刷题。在一个目录下创建多个go文件,每个文件都是以下packagemainfuncmain(){}在vscode下会出问题,会报错,这让我很难受。这样做,在Goland下没有问题,Go......
  • LeetCode 406. 根据身高重建队列
    classSolution{public:structnode{intval;intpre;node*next;node(inta,intb,node*c){val=a;pre=b;next=c;}};voidinsert(node*&head,int......
  • leetcode第354场周赛 2 - 双指针
    题目传送门2779.数组的最大美丽值题意给你一个数组和一个整数k,数组里面每个数都只能操作一次:加上区间\([-k,k]\)里的数。问你最终由相等元素组成的最长子序列的长度双指针的妙用!思路先排序,前后双指针取差值在2k之间的区间,此区间的所有数均可以操作为同一个属,ans统计最大值......
  • LeetCode 热题 100 之 21. 合并两个有序链表
    题目将两个升序链表合并为一个新的升序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。示例1:输入:l1=[1,2,4],l2=[1,3,4]输出:[1,1,2,3,4,4]示例2:输入:l1=[],l2=[]输出:[]示例3:输入:l1=[],l2=[0]输出:[0]提示:两个链表的节点数目范围是[......
  • LeetCode 热题 100 之 560. 和为 K 的子数组.md
    题目给你一个整数数组nums和一个整数 k,请你统计并返回该数组中和为 k 的连续子数组的个数 。示例1:输入:nums=[1,1,1],k=2输出:2示例2:输入:nums=[1,2,3],k=3输出:2提示:1<=nums.length<=2*10^4-1000<=nums[i]<=1000-10^7<=k<=10^7思路......
  • [Leetcode Weekly Contest]355
    链接:LeetCode[Leetcode]6921.按分隔符拆分字符串给你一个字符串数组words和一个字符separator,请你按separator拆分words中的每个字符串。返回一个由拆分后的新字符串组成的字符串数组,不包括空字符串。注意separator用于决定拆分发生的位置,但它不包含在结果字符串......
  • LeetCode 热题 100 之 438. 找到字符串中所有字母异位词
    题目给定两个字符串 s 和p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。异位词指由相同字母重排列形成的字符串(包括相同的字符串)。示例 1:输入:s="cbaebabacd",p="abc"输出:[0,6]解释:起始索引等于0的子串是"cba"......
  • LeetCode 热题 100 之 3. 无重复字符的最长子串
    题目给定一个字符串s,请你找出其中不含有重复字符的 最长子串 的长度。示例 1:输入:s="abcabcbb"输出:3解释:因为无重复字符的最长子串是"abc",所以其长度为3。示例2:输入:s="bbbbb"输出:1解释:因为无重复字符的最长子串是"b",所以其长度为1。示例3:......
  • LeetCode 399. 除法求值
    classSolution{public:vector<double>calcEquation(vector<vector<string>>&equations,vector<double>&values,vector<vector<string>>&queries){unordered_set<string>node;//记录所有节点......