当前位置: 首页 > news >正文

数组类算法【leetcode】

704. 二分查找

2024.11.06

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

二分查找 用于有序数组中,没有重复的数组。首先需要定义一个头(left)和尾(right),最后通过mid和target对比不断修改头和尾指向的位置。

【需要注意区间问题,根据区间的开和闭决定边界条件】

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

推荐练习 leetcode35. 

27.移除元素

2024.11.07

题目:给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。力扣题目链接

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

这里其实有序无序都可以,正常的调用内置函数的复杂度是O(n),是用的两个for循环进行暴力解。这里要求我们原地执行,所以用一个for循环解决。

【这里我们要知道数组的删除,其实和我们平时理解的删除并不一样,数组的删除前其实是将不需要的元素进行覆盖,内存中他还是存在的】

这里用到了快慢指针,一个fast和一个slow,fast用于遍历整个数组,所以for循环的执行条件就应该是当fast小于数组长度的时候就进行一次循环,而slow指针怎么变化呢?如果nums[fast]不是需要的val,那就令nums[fast] = nums[slow],当nums[fast] = val的时候,slow指针的位置不需要变,这样可以把slow看作一个新的数组,用于装不包含val值的数组,当nums[fast]再次不等于val的时候将nums[fast]再次赋给nums[slow],slow指针再次向后移动。

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

977.有序数组的平方

2024.11.07

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

思路和上一题类似,也是用双指针,这里两头的平方一定会大于中间的值的平方,所以新建立一个数组从后往前放置原数组的平方的值。

class Solution {
public:vector<int> sortedSquares(vector<int>& nums) {int left = 0;int right = nums.size() - 1;int k = nums.size() - 1;   //因为数组的两头的数字的绝对值一定大于中间的,所以result数组从后往前放vector<int> result(nums.size(), 0);for(; left <= right;){if(nums[left] * nums[left] < nums[right] * nums[right]){   result[k--] = nums[right] * nums[right];right --;}else{result[k--] = nums[left] * nums[left];left ++;}}return result;}
};

209.长度最小的子数组

2024.11.08

这是第一道中等题,但其实也挺简单的力扣题目链接

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。

1.暴力解

这道题目暴力解法当然是 两个for循环,然后不断的寻找符合条件的子序列,时间复杂度很明显是O(n^2)。

class Solution {
public:int minSubArrayLen(int s, vector<int>& nums) {int result = INT32_MAX; // 最终的结果int sum = 0; // 子序列的数值之和int subLength = 0; // 子序列的长度for (int i = 0; i < nums.size(); i++) { // 设置子序列起点为isum = 0;for (int j = i; j < nums.size(); j++) { // 设置子序列终止位置为jsum += nums[j];if (sum >= s) { // 一旦发现子序列和超过了s,更新resultsubLength = j - i + 1; // 取子序列的长度result = result < subLength ? result : subLength;break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break}}}// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列return result == INT32_MAX ? 0 : result;}
};

2.最优解

滑动窗口,有点类似之前的双指针的解法,不断更新子序列的两头指针,只要窗口中的sum大于target,就把左边的指针往右移一格,如果sum一直小于target就右边的指针持续后移。那么我们就可以通过记录每次得到的小于sum的子数组,并每次进行比较,及时更新最小值。

class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int left = 0;int right = 0;int sum = 0;int length = 0;                     //滑动窗口的长度(子数组)//在算法中,当你需要找到一组数中的最小值时,可以将初始值设为 INT32_MAX,这样任何实际的数值都会比它小。int result = INT32_MAX;for(right=0;right < nums.size();right++){sum += nums[right];while(sum >= target){length = right - left + 1;  //截至sum 小于 target, 数组的长度(未必是最小的)if (result > length){result = length;        // 更新最小子数组长度}sum -= nums[left++];}}if(result == INT32_MAX)return 0;elsereturn result;}
};

 不要以为for里放一个while就以为是O(n^2)啊, 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)。

 59.螺旋矩阵II

2024.11.08

这是第一道中等题,思路很简单,只需要注意边界条件,按顺序赋值就完了

题目:给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。

思路:

模拟顺时针画矩阵的过程:

  • 填充上行从左到右
  • 填充右列从上到下
  • 填充下行从右到左
  • 填充左列从下到上

由外向内一圈一圈这么画下去.......【我按照左闭右开的原则】统一填充方式可以很大程度避免自己写到后面乱掉了。

class Solution {
public:vector<vector<int>> generateMatrix(int n) {vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组int x = 0;int y = 0;int loop = n / 2;       //  循环次数int offset = 1;         // 需要控制每一条边遍历的长度,每次循环右边界收缩一位int mid = n / 2;        //  n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)int count = 1;          //  用来给矩阵中每一个空格赋值int i, j;while(loop--){i = x; j = y;for(;j < n - offset;j++){res[i][j] = count++;}//第一个for循环完之后,j = n - offsetfor(;i < n - offset;i++){res[i][j] = count++;}//第二个for循环完之后,i = n - offsetfor(;j > y;j--){res[i][j] = count++;}for(;i > x;i--){res[i][j] = count++;}// 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)x++;y++;// offset 控制每一圈里每一条边遍历的长度offset++;}if (n % 2) {res[mid][mid] = count;}return res;}
};

未完待续.......


http://www.mrgr.cn/news/68445.html

相关文章:

  • 小张求职记六
  • 现代Web开发:React Hooks深入解析
  • 从0开始学习Linux——文件目录
  • Oh My Posh安装
  • 【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
  • esp32记录一次错误
  • 《XGBoost算法的原理推导》12-22计算信息增益(Gain)的公式 公式解析
  • 【AI技术】PaddleSpeech
  • 【计网不挂科】计算机网络期末考试——【选择题&填空题&判断题&简述题】题库(1)
  • NVR设备ONVIF接入平台EasyCVR私有化部署视频平台如何安装欧拉OpenEuler 20.3 MySQL
  • 超干干货!看完,你就是产品经理天花板
  • aws申请ssl证书的方法【该证书仅供aws】
  • <数据集>草莓叶片病害识别数据集<目标检测>
  • 【EI稳定检索】2025通信技术与数据安全国际研讨会(CTADS 2025)
  • 常见加密算法逆向分析
  • 吐糟-致敬一棍子把我打死的知识
  • 三品PLM产品管理系统如何提升企业研发管理效率?
  • SourceTree突然打不开,删除这个文件就好了
  • linux服务器通过手机USB共享网络
  • 无线婴儿监视器方案(附SI24R1选型)
  • 爬虫-------字体反爬
  • linux 安装anaconda3
  • 366_C++_SystemClock类,每1秒定时轮巡,需要不停在后台执行的任务,可以用这种方式
  • 腾讯云双11最强优惠攻略详解
  • 基于数组实现的Huffman树和Huffman编码
  • windows环境下vscode下载安装