文章目录
- 一、数组基础
- 二、题
- 1. 704 二分查找
- 2. 27 移除元素
- 3. 977 有序数组的平方
- 4. 209 长度最小的子数组
一、数组基础
数组是存放在连续内存空间上的相同类型数据的集合,也就是说数组内存空间的地址是连续的。
因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址,注意:数组的元素是不能删的,只能覆盖。
1、数组初始化分配内存
int record[26] = {0};
2、vector排序函数:sort(A.begin(),A.end());
3、vector res = {1, 2, 3, 4};
4、vector int res(10,0); // 创建一个大小为10的vector
vector<vector> res(10, vector(10, 0)) // 创建一个10*10的二维vector
5、查找vector中的元素
vector<int>::iterator aa = find(visited.begin(), visited.end(), 5); // 如果vector是空的,出现段错误
if (aa == visited.end()) 没找到
else *aa 找到了返回值
PS:vector的底层实现是array,但严格来讲vector是容器,不是数组。之后补充
6、二维数组
int array[2][3] = {
{0, 1, 2},
{3, 4, 5}
};
vector<int> res(10,0); // 创建一个大小为10的vector
vector<vector<int>> res(10, vector<int>(10, 0));
二维int型数组内存地址,相邻数组元素差了4个字节
二、题
1. 704 二分查找
前提条件:有序数组、无重复元素
着重点:
1、while的退出条件非常重要,小于等于:while(left <= right)
2、取中间值索引时非常重要:int mid = (right - left)/2 + left;
奇数个索引刚好在中间,偶数个索引在中间偏左位置
2. 27 移除元素
题目描述:给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
双指针,感觉很难想,需要重点2刷。
核心思想:每次fast都会给slow值,除非fast指向了val
代码如下(示例):
int removeElement(vector<int>& nums, int val) {
int slow = 0;
int fast = 0;
while(fast < nums.size()){ // 每次fast都会给slow值,除非fast指向了val
if(nums[fast] != val){
nums[slow] = nums[fast];
slow++;
}
fast++;
}
return slow;
}
// 2021年第一次做
int fast = 0;
int slow = 0;
int removeElement(vector<int>& nums, int val) {
for(fast = 0;fast<nums.size();fast++)
{
if(nums[fast] != val) //在快和慢没有分开时,当快指针不为val时,带着slow走
{ //在快和慢分开之后,,当快指针不为val,每次赋值结束,slow指针自加
nums[slow] = nums[fast]; //只要不赋值,慢指针就永远不自加
slow++;
}
//当快指针为val时,快指针自己走,第一次快与慢分开的时候就是第一次碰到val的时候
}
return slow;
}
3. 977 有序数组的平方
vector<int> sortedSquares(vector<int>& nums) {
int k = nums.size() - 1;
vector<int> res(nums.size(),0);
int left = 0;
int right = nums.size() - 1;
while(right >= left){
if(nums[right] * nums[right] >= nums[left] * nums[left]){
res[k] = nums[right] * nums[right];
k--;
right--;
}else{
res[k] = nums[left] * nums[left];
k--;
left++;
}
}
return res;
}
4. 209 长度最小的子数组
题目:给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其和 ≥ target 的长度最小的连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
这题做的时候思维僵化了,没有利用好≥这个条件,总觉得应该固定窗口的大小再滑动,没想到可以动态条件窗口的大小,用了三种解法都是暴力解,之后可以看看。
做这题时同时复习了哈希映射和earse函数:
1、earse输入的是数组的迭代器,例:vector.erase(vector.begin());
2、遍历哈希映射的方式
for (auto it = windowfalse.begin(); it != windowfalse.end(); it++)
cout << *it << endl;
// 必须使用单for来完成滑窗
int minSubArrayLen(int target, vector<int>& nums) {
int res = 999999999; //INT32_MAX
int sum = 0;
int k = 0;
int left = 0;
for (int right = 0; right < nums.size(); right++) {
sum += nums[right];
while (sum >= target) {
k = right - left + 1;
res = res > k ? k : res; // 题目要求是最小的长度,这个k不一定最小,暂时保存一下
sum -= nums[left];
left++; // 动态滑窗!!窗口的大小不是固定的
}
}
return res == 999999999 ? 0 : res;
}
int minSubQueueLen(int target, vector<int> nums) {
// 滑窗size为k时
for (int k = 1; k < nums.size() + 1; k++) {
unordered_set<int> windowfalse;
queue<int> window;
for (int i = 0; i < nums.size(); i++) {
window.push(nums[i]);
if (i >= k) {
// windowfalse.erase(nums[i - k]); // 哈希映射会删除滑窗中的该元素。。
window.pop();
}
int ans = 0;
// cout << k << "滑窗";
/*for (auto it = windowfalse.begin(); it != windowfalse.end(); it++)
{
int a = *it;
ans += a;
}*/
// queue是没有遍历操作的,这是很弱智的做法,时间复杂度太高
for (int i = 0; i < window.size(); i++) {
ans += window.front();
window.push(window.front());
window.pop();
}
if (ans >= target)
return k;
}
}
return 0;
}
int minSubvectorLen(int target, vector<int>& nums) {
// 滑窗size为k时
for (int k = 1; k < nums.size() + 1; k++) {
vector<int> window;
for (int i = 0; i < nums.size(); i++) {
window.push_back(nums[i]);
if (i >= k) {
window.erase(window.begin());
}
int ans = 0;
// 时间复杂度太高
for (int i = 0; i < window.size(); i++) {
ans += window[i];
}
if (ans >= target)
return k;
}
}
return 0;
}
// 超出时间限制。。双指针暴力解
int minSubArrayLen(int target, vector<int>& nums) {
// 滑窗size为k时
for (int k = 1; k < nums.size() + 1; k++) {
int left = 0;
for (int right = 0; right < nums.size(); right++) {
if ((right - left) > (k - 1)) {
left++;
}
int ansleft = left;
int ansright = right;
int ans = 0;
while (ansleft <= ansright) {
ans += nums[ansleft];
ansleft++;
}
if (ans >= target) {
return k;
}
}
}
return 0;
}