leetcode 3.11

leetcode hot 100

    • 二分查找
      • 1.寻找旋转排序数组中的最小值
    • 矩阵
      • 1.搜索二维矩阵 II
        • 知识点:upper_bound, lower_bound
        • 知识点:二分查找
      • 2.搜索二维矩阵
    • 链表
      • 1.合并两个有序链表
      • 2.两数相加
      • 3. 删除链表的倒数第 N 个结点

二分查找

1.寻找旋转排序数组中的最小值

寻找旋转排序数组中的最小值
根据题意可知,一定存在一个点,让整个数组断崖式下跌,
[7, 6, 5, 4, 3, 2, 0, 1] 比如在这个数组中的0
我们需要找到这个断崖式下跌的点,就是这个数组的最小值
在这里插入图片描述
我们考虑数组中的最后一个元素 x:在最小值右侧的元素(不包括最后一个元素本身),它们的值一定都严格小于 x;而在最小值左侧的元素,它们的值一定都严格大于 x。因此,我们可以根据这一条性质,通过二分查找的方法找出最小值。
查找第一个大于等于目标值的元素(加了其它代码的解释,原来的题解放在链接里了)

class Solution {
public:int findMin(vector<int>& nums) {int low  = 0; int high = nums.size() - 1;while (low  < high) {int pivot = low + (high - low) / 2;if (nums[pivot] < nums[high]) {high = pivot;} else {low  = pivot + 1;}}return nums[low];}
};

矩阵

1.搜索二维矩阵 II

240. 搜索二维矩阵 II

第一种:最容易想到的暴力解法
时间复杂度:o(mn)
空间复杂度:o(1)

第二种:暴力解法的进阶版,用二分查找每一行,这样可以减少时间复杂度
时间复杂度:o(nlogn)
空间复杂度:o(1)

第三种:比较巧妙的方法,从左上或者右下角开始查找,以右下角matrix[n - 1][0] 为例,如果当前matrix[i][j] 值为 a

  • 如果我们找的元素target大于a,那么 j++ 寻找
  • 如果我们找的元素target小于a,那么 i-- 寻找
  • 如果等于,则直接返回

第二种: 二分优化暴力查找

class Solution {
public:bool searchMatrix(vector<vector<int>>& matrix, int target) {int n = matrix.size(), m = matrix[0].size();for (int i = 0; i < n; i++) {auto ans = lower_bound(matrix[i].begin(), matrix[i].end(), target);//auto tmp = ans - matrix[i].begin();//if (ans != matrix[i].end() &&  matrix[i][tmp] == target) {if (ans != matrix[i].end() && *ans == target) {return true;}}return false;}
};

或者不用库函数,手写二分:

class Solution {
public:bool searchMatrix(vector<vector<int>>& matrix, int target) {int n = matrix.size(), m = matrix[0].size();for (int i = 0; i < n; i++) {int l = 0, r = m;while (l < r) {int mid = (r - l) / 2 + l;if (matrix[i][mid] < target) {l = mid + 1;} else {r = mid;}}if (l < m && matrix[i][l] == target) return true;}return false;}
};
class Solution {
public:bool searchMatrix(vector<vector<int>>& matrix, int target) {int n = matrix.size(), m = matrix[0].size();for (int i = 0; i < n; i++) {int l = 0, r = m - 1;while (l <= r) {int mid = (r - l) / 2 + l;if (matrix[i][mid] < target) {l = mid + 1;} else  if (matrix[i][mid] > target) {r = mid - 1;} else {return true;}}}return false;}
};
知识点:upper_bound, lower_bound

upper_bound, lower_bound两者都是定义在头文件里。用 二分查找的方法在一个排好序的数组中进行查找。既然是二分,时间复杂度就是O(logN)。

基础用法

upper_bound(begin, end, value)

从小到大的排好序的数组中,在数组的 [begin, end) 区间中二分查找第一个大于value的数,找到返回该数字的地址,没找到则返回end。

lower_bound(begin, end, value)

在从小到大的排好序的数组中,在数组的 [begin, end) 区间中二分查找第一个大于等于value的数,找到返回该数字的地址,没找到则返回end。

用greater()重载

upper_bound(begin, end, value, greater<int>())

在从大到小的排好序的数组中,在数组的 [begin, end) 区间中二分查找第一个小于value的数,找到返回该数字的地址,没找到则返回end。

lower_bound(begin, end, value, greater<int>())

在从大到小的排好序的数组中,在数组的 [begin, end) 区间中二分查找第一个小于等于value的数,找到返回该数字的地址,没找到则返回end。

第三种:将二维矩阵抽象成「以右上角为根的 BST」

以右上为根

class Solution {
public:bool searchMatrix(vector<vector<int>>& matrix, int target) {int n = matrix.size(), m = matrix[0].size();int i = 0, j = m - 1;while (i < n && j >= 0) {if (matrix[i][j] > target) j--;else if (matrix[i][j] < target) i++;else return true;}return false;}
};

以左下为根……

class Solution {
public:bool searchMatrix(vector<vector<int>>& matrix, int target) {int n = matrix.size(), m = matrix[0].size();int i = n - 1, j = 0;while (i >= 0 && j < m) {if (matrix[i][j] > target) i--;else if (matrix[i][j] < target) j++;else return true;}return false;}
};
知识点:二分查找

二分查找的难点在于边界判断,如果实在没法判断可以写几个数字自己模拟二分过程推导一次就能得出结论。以下为个人总结,仅供参考

记住两个模板,在这两个模板上修改:
当我们需要查找第一个大于等于target的数时:

  • 第一种方法:
    • r = n
    • l < r不加等号,这样l == r 时会返回
    • 需要判断 >= target 的情况,因为如果用<=会导致死循环
    • return l/ r
int l = 0, r = n;
while (l < r) {......if (nums[mid] >= targer) {r = mid;} else {l = mid + 1;}
}
  • 第二种方法:
    • r = n - 1
    • l <= r 加等号,这样l > r (l > r && r - l = 1) 时会返回
    • 加上 == target 的情况判断会比较清晰(个人习惯)
    • return l (也就是r + 1)
int l = 0, r = n - 1;
while (l <= r) {......if (nums[mid] == target) {return mid + 1;} else if (nums[mid] < target) {l = mid + 1;} else {r = mid - 1;}
}
return l;

当我们需要查找第一个大于target的数时:

  • 第一种方法:
    • r = n
    • l < r不加等号,这样l == r 时会返回
    • 需要判断 >= target 的情况,因为如果用<=会导致死循环
    • 判断结果,如果等于则return l + 1, 否则return l (也就是r + 1)
int l = 0, r = n;
while (l < r) {......if (nums[mid] >= targer) {r = mid;} else {l = mid + 1;}
}
  • 第二种方法:
    • r = n - 1
    • l <= r 加等号,这样l > r (l > r && r - l = 1) 时会返回
    • 加上 == target 的情况判断会比较清晰(个人习惯)
    • 判断结果,如果等于则return mid + 1, 否则return l (也就是r + 1)
int l = 0, r = n - 1;
while (l <= r) {......if (nums[mid] == target) {return mid + 1;} else if (nums[mid] < target) {l = mid + 1;} else {r = mid - 1;}
}
return l;

同理可以推出其他情况。

现在让我们用抽象成BST的方法来重新做以下这道题

2.搜索二维矩阵

搜索二维矩阵
我们从以右上为根节点

class Solution {
public:bool searchMatrix(vector<vector<int>>& matrix, int target) {vector<int> ans;int n = matrix.size(), m = matrix[0].size();int i = 0, j = m - 1;while (i < n && j >= 0) {if (matrix[i][j] > target) {j--;} else if (matrix[i][j] < target) {i++;} else return true;}return false;}
};

链表

1.合并两个有序链表

合并两个有序链表
方法一:迭代
当 list1 和 list2都不为空时,依次连接,之后判断哪个链表不为空,把剩余链表合并。
时间复杂度:O(n+m)
空间复杂度:O(1)

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {ListNode* dummy = new ListNode(-1);ListNode* ans = dummy;while (list1 != nullptr && list2 != nullptr) {if (list1->val < list2->val) {ans->next = list1;list1 = list1->next;} else {ans->next = list2;list2 = list2->next;}ans = ans->next;}ans->next = list1 == nullptr ? list2 : list1;return dummy->next;}
};

方法二:递归

一开始并没有想到这个递归方法,所以需要再次复习递归的知识点:

  • 递归函数必须要有终止条件,否则会出错;
  • 递归函数先不断调用自身,直到遇到终止条件后进行回溯,最终返回答案。

在此题中,终止条件就是list1 == nullptr || list2 == nullptr
我们可以如下递归地定义两个链表里的 merge 操作(忽略边界情况,比如空链表等):

  • list1[0] + merge(list1[1:], list2) list1[0] < list2[0]
  • list2[0] + merge(list1, list2[1:]) otherwise

也就是说,两个链表头部值较小的一个节点与剩下元素的 merge 操作结果合并。

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {if (list1 == nullptr) return list2;else if (list2 == nullptr) return list1;else if (list1->val < list2->val) {list1->next = mergeTwoLists(list1->next, list2);return list1;} else {list2->next = mergeTwoLists(list1, list2->next);return list2;}}
};

2.两数相加

两数相加
暴力思路:先把链表转为int, 加起来之后再放到int里,那肯定是会超时/超空间的
看了题解可以发现:
1.如果遍历到某个链表之后为空,值为0
2.链表每一位上的和为 (list1->val + list2->val + carry)% 10,carry为上一位的进位,初始值为0
3.链表每一位上的进位为 carry = (list1->val + list2->val + carry) / 10
4.因为是逆序存储,那么直接计算,如果最后一位有进位,那么end->next后再new 一个 node(1)

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {ListNode* dummy = new ListNode(-1);ListNode* result = dummy;int carry = 0;while (l1 != nullptr || l2 != nullptr) {int x = l1 == nullptr ? 0 : l1->val;int y = l2 == nullptr ? 0 : l2->val;int tmp = (x + y + carry) % 10;result->next = new ListNode(tmp);result = result->next;carry = (x + y + carry) / 10;if (l1 != nullptr) l1 = l1->next;if (l2 != nullptr) l2 = l2->next;}if (carry) result->next = new ListNode(1);return dummy->next;}
};

3. 删除链表的倒数第 N 个结点

删除链表的倒数第 N 个结点
第一次遍历得出链表个数,第二次遍历删除节点

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode* p = head, *q = head;int num = 0;while(p != nullptr) {p = p->next;num++;}// 如果要删除的节点是第一个节点,直接返回第二个节点即可if (num == n) return head->next;num = num - n - 1;while (num--) {q = q->next;}//如果要删除的是最后一个节点之后的节点,空节点,直接return headif (q->next != nullptr)q->next = q->next->next;return head;}
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/747578.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

复习C语言基础中的基础:C语言发展、C89 C99有何区别、C语言特点

参考《C程序设计&#xff08;第五版&#xff09;》&#xff08;谭浩强&#xff09;一书&#xff1a; 1. 发展、C89 C99 2. 特点 记得时不时回顾一下背景特点&#xff0c;加深对C语言的理解。

git的实际运用

1. SSH配置和Github仓库克隆 注意博主在这里演示的SSH密钥生成方式&#xff0c;下面追加的五行不成功时可手动到.ssh下的config文件中添加即可 $ tail -5 config Host github.comHostName github.comPreferredAuthentications publickeyIdentityFile ~/.ssh/test 演示 2. 关联…

数据完整性

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 数据完整性 数据完整性是关系数据库的一个重要特征&#xff0c;一般包含实体完整性、参照完整性和用户自定义完整性 3 种 实体完整性 实体完整性&#xff1a;规定表中的每…

QML| QML 组件

# | QML 组件 | 组件是可重用的、封装好的QML类型,并提供了定义好的接口。组件一般使用一个.qml文件定义。前面讲到的使用QML文档定义对象类型,其实就是创建了一个组件。这种使用独立QML文件创建组件的方法这里不再讨论。除了使用单独的QML文件,还可以使用Component类型在一…

如何规范员工上网行为(规范员工上网行为的有效方法)

有很多企业会有员工管理问题&#xff0c;比如以下几位老板的担忧&#xff1a; 可见&#xff0c;很多企业都想要对员工上网行为进行管理。 我想企业要对员工上网行为进行规范管理&#xff0c;肯定也是出于多方面的考量。这些考量可能涵盖了工作效率、信息安全、网络带宽利用以及…

2024 ICDE | 时间序列(Time Series)论文总结

第40届IEEE数据工程国际会议&#xff08;ICDE2024 &#xff09;于5月13日到17日在荷兰乌德勒支召开。 本届ICDE Research共接收论文375篇&#xff0c;Industry and Application接受论文21篇。本文总结了ICDE 2024上有关时间序列&#xff08;Time Series&#xff09;的工作&…

C语言-存储期2.0

静态存储期 在数据段中分配的变量&#xff0c;统统拥有静态存储期&#xff0c;因此也都被称为静态变量。这里静态的含义&#xff0c;指的是这些变量的不会因为程序的运行而发生临时性的分配和释放&#xff0c;它们的生命周期是恒定的&#xff0c;跟整个程序一致。 静态变量包含…

一文轻松学会远程服务器/docker内 vscode,调试(debug)无/多参数/bash以及多工作空间运行的python程序,欢迎大佬补充,一起学习

至于如何SSH、docker以及无需参数的程序调试这篇就先不说了。本篇文章主要记录一下多参数和多工作空间调试的问题。 一、launch.json文件 如上图所示&#xff0c;正常情况下当我们想要调试项目名字为0的目录下的train.py文件时&#xff0c;我们会按顺序点1&#xff0c;2&#…

防范服务器被攻击:查询IP地址的重要性与方法

在当今数字化时代&#xff0c;服务器扮演着重要的角色&#xff0c;为企业、组织和个人提供各种网络服务。然而&#xff0c;服务器也成为了网络攻击者的目标之一&#xff0c;可能面临各种安全威胁&#xff0c;例如DDoS攻击、恶意软件攻击、数据泄露等。为了有效地防范服务器被攻…

用 docker 创建 jmeter 容器, 实现性能测试,该如何下手?

用 docker 创建 jmeter 容器, 实现性能测试 我们都知道&#xff0c;jmeter可以做接口测试&#xff0c;也可以用于性能测试&#xff0c;现在企业中性能测试也大多使用jmeter。docker是最近这些年流行起来的容器部署工具&#xff0c;可以创建一个容器&#xff0c;然后把项目放到…

Navicat破解 Navicat下载安装 附教程 免费

百度网盘&#xff1a;https://pan.baidu.com/s/1wRRN_18_uXxPiIWCS4l43A 麻烦各位师傅帮忙填写一下问卷&#xff0c;提取码在问卷填写结束后显示~ 【https://www.wjx.cn/vm/mBBTTKm.aspx# 】 &#xff08;资料来源于网络&#xff0c;侵告删&#xff09;

【护网资料】 应急响应 安全设备 告警分析 蓝中必看 HVV 护网行动

百度网盘&#xff1a;https://pan.baidu.com/s/1wDVamgkyXwP-yiWN4jPEGQ 麻烦各位师傅帮忙填写一下问卷&#xff0c;提取码在问卷填写结束后显示~ 【https://www.wjx.cn/vm/mBBTTKm.aspx# 】 &#xff08;资料来源于网络&#xff0c;侵告删&#xff09;

【CTF笔记】 CTF web方向笔记分享 免费 附预览图

个人不怎么记东西&#xff0c;笔记不多&#xff0c;师傅们凑合看… 百度网盘&#xff1a;https://pan.baidu.com/s/1PspihUX28Y_AOQZPurHqKA 麻烦各位师傅帮忙填写一下问卷&#xff0c;提取码在问卷填写结束后显示~ 【https://www.wjx.cn/vm/mBBTTKm.aspx# 】 &#xff08;…

重学SpringBoot3-路径匹配机制

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-路径匹配机制 AntPathMatcherPathPatternParser 和 PathPattern演示AntPathMatcher 示例PathPattern 示例性能和精确度的提升 选择使用哪一种 在 Spring…

迷宫问题三种种解法(A*算法+BFS+双向广搜)

题目描述 小明置身于一个迷宫&#xff0c;请你帮小明找出从起点到终点的最短路程。 小明只能向上下左右四个方向移动。 输入格式 输入包含多组测试数据。输入的第一行是一个整数T&#xff0c;表示有T组测试数据。 每组输入的第一行是两个整数N和M&#xff08;1<N,M<100&a…

【LeetCode】升级打怪之路 Day 24:回溯算法的解题框架

今日题目&#xff1a; 46. 全排列51. N 皇后78. 子集 目录 LC 46. 全排列LC 51. N 皇后LC 78. 子集 【classic】1&#xff09;思路一2&#xff09;思路二 今天学习了回溯算法的解题框架&#xff1a;回溯算法解题套路框架 | labuladong 回溯算法的整体框架都是&#xff1a; re…

力扣L11--- 344.反转字符串(JAVA版)-2024年3月15日

1.题目 2.知识点 交换两个变量值的代码 char temps[left];//temp为暂时的变量&#xff0c;left是左指针&#xff0c;将left暂时存储在temp里面s[left]s[right];//将右指针的值赋给左指针s[right]temp;//将temp的值给右指针left;//左指针向左移动right--;//右指针向右移动3.代码…

2024年【广东省安全员C证第四批(专职安全生产管理人员)】考试总结及广东省安全员C证第四批(专职安全生产管理人员)模拟试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 广东省安全员C证第四批&#xff08;专职安全生产管理人员&#xff09;考试总结是安全生产模拟考试一点通总题库中生成的一套广东省安全员C证第四批&#xff08;专职安全生产管理人员&#xff09;模拟试题&#xff0c;…

【ShenYu源码阅读】支持提醒通知设计,来看看开源贡献者都做了什么

相信大家碰到源码时经常无从下手&#x1f643;&#xff0c;不知道从哪开始阅读&#xff0c;面对大量代码晕头转向&#xff0c;索性就读不下去了&#xff0c;又浪费了一次提升自己的机会&#x1f62d;。 我认为有一种方法&#xff0c;可以解决大家的困扰&#xff01;那就是通过阅…

修复ElementUI中el-select与el-option无法通过v-model实现数据双向绑定的问题

1. 问题描述 需求&#xff1a;在使用ElementUI时&#xff0c;通过el-select和el-option标签实现下拉列表功能&#xff0c;当el-option中的选项被选中时&#xff0c;被选中的选项可以正确回显到已选择的列表中。 对于上面的下拉列表&#xff0c;当我们选中“超级管理员”的选项…