重拾C++之菜鸟刷算法第一篇---数组
数组
一、二分查找
知识点:
-
int middle = itBegin + (itEnd - itBegin)/ 2; // 防止溢出
在 C++ 中,如果两个整数相加的结果超过了整数类型的表示范围,就会发生溢出,导致结果不再是预期的值。
考虑到二分查找中常用到的 (itBegin + itEnd) / 2,如果 itBegin 和 itEnd 都是很大的正整数时,它们的和可能超过整数类型的最大表示范围,导致溢出。
而使用 (itBegin + (itEnd - itBegin) / 2) 这样的写法,可以避免这个问题。首先,通过 itEnd - itBegin 计算出两个迭代器之间的距离,然后再除以2。这样,即使 itBegin 和 itEnd 很大,它们之间的差值仍然是正数,不会导致溢出。
-
middle - 1, middle + 1;
假如有一堆数字牌,从最左边到最右边,这些数字是按照从小到大的顺序排列的。我们要找的数字就叫做 "target"。
现在,我们先看最中间的一张牌的数字,这张牌的位置就是 middle。如果这张牌上的数字比我们要找的数字 "target" 大,那么我们就知道 "target" 只可能在这张牌的左边,因为数字是按照从小到大的顺序排列的。
所以,我们把牌堆缩小到左边一半,把最右边的牌移到 middle - 1 的位置。这样,我们就把寻找的范围缩小了一半,继续找。
这样做的好处有两点:
1. 防止出现无限循环
如果有两张相邻的牌上的数字相等且都等于目标数字,我们每次猜中间的数字都不变,就陷入了无限循环,就像玩一个不停的游戏一样。
2. 提高搜索效率
如果目标数字比中间的数字小,那就说明目标数字在这张牌的左边。
题目
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
题解
class Solution { public: int search(vector& nums, int target) { // 求vector长度 .size() int itBegin = 0; int itEnd = nums.size() - 1; while (itBegin nums[middle]) { itBegin = middle + 1; } else{ return middle; } } return -1; } };
二、移除元素
知识点
这是一个快慢指针的问题,我想到了这个题解,但是没有想到快慢指针也可以用数字表示。
反正fast往前冲,slow只有符合条件的时候才赋值往前移动。
题目
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。 元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
题解
class Solution { public: int removeElement(vector& nums, int val) { int slow = 0; int fast = 0; while(fast
三、有序数组的平方
知识点
-
双指针 (使用条件,需要构造一个新数组)
题目
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
题解
class Solution { public: vector sortedSquares(vector& nums) { vector result(nums.size(), 0); // vector的构造函数 int begin = 0; int end = nums.size() - 1; int Final = nums.size() - 1; while(begin nums[begin] * nums[begin]){ result[Final] = nums[end] * nums[end]; end --; Final --; } else{ result[Final] = nums[begin] * nums[begin]; begin ++; Final --; } } return result; } };
四、长度最小的子数组
知识点
-
滑动窗口
-
滑动窗口内容
-
滑动窗口的起始位置
-
滑动窗口的结束位置
题目
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
题解
class Solution { public: int minSubArrayLen(int target, vector& nums) { int subLength = 0; int result = INT32_MAX;// 记录最大数 int sum = 0; // 用来记录子序列总和 int i = 0; // 用来记录起始指针位置 for (int j = 0; j = target) { subLength = j - i + 1; // 滑动窗口的内容 result = result > subLength ? subLength:result; sum -= nums[i++]; // 滑动窗口的起始位置移动规则 } } return result == INT32_MAX ? 0 : result; } };
五、螺旋矩阵 II
知识点
-
不变性原则,规则是具有确定性的(比如开区间和闭区间,如果你决定了遍历都是【闭区间,开区间),那么请仔细确定接下来的步骤也应该遵守这个原则)
题目
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
题解
class Solution { public: vector generateMatrix(int n) { vector Matrix(n, vector(n, 0)); int startX = 0; int startY = 0; int offset = 1; int count = 1; int k = 0; int i, j; while(k startY; j--){ Matrix[i][j] = count++; } for (; i > startX; i--){ Matrix[i][j] = count++; } k++; startX++; startY++; offset++; } if(n % 2 == 1){ Matrix[n/2][n/2] = count; } return Matrix; } };
题目整理来自{代码随想录},今天就到这啦~
-
-
-
-