学习内容:
704. 二分查找
- 使用前提:数组为有序数组,同时题目还强调数组中无重复元二分法素
- 二分法第一种写法:左闭右闭
// 版本一 class Solution { public: int search(vector<int>& nums, int target) { int left = 0; int right = nums.size() - 1; // 定义target在左闭右闭的区间里,[left, right] while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <= int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2 if (nums[middle] > target) { right = middle - 1; // target 在左区间,所以[left, middle - 1] } else if (nums[middle] < target) { left = middle + 1; // target 在右区间,所以[middle + 1, right] } else { // nums[middle] == target return middle; // 数组中找到目标值,直接返回下标 } } // 未找到目标值 return -1; } };
- 二分法第二种写法:左闭右开
// 版本二 class Solution { public: int search(vector<int>& nums, int target) { int left = 0; int right = nums.size(); // 定义target在左闭右开的区间里,即:[left, right) while (left < right) { // 因为left == right的时候,在[left, right)是无效的空间,所以使用 < int middle = left + ((right - left) >> 1); if (nums[middle] > target) { right = middle; // target 在左区间,在[left, middle)中 } else if (nums[middle] < target) { left = middle + 1; // target 在右区间,在[middle + 1, right)中 } else { // nums[middle] == target return middle; // 数组中找到目标值,直接返回下标 } } // 未找到目标值 return -1; } };
27. 移除元素(重新刷,感觉又有了新的理解)
- 双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
- 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
- 慢指针:指向更新 新数组下标的位置。
class Solution { public: int removeElement(vector<int>& nums, int val) { int slow =0; for(int fast =0;fast<nums.size();fast++) { if(val!=nums[fast]) { nums[slow++]=nums[fast]; } } return slow; } };
977.有序数组的平方 (也是快慢指针比较,有序情况)
- 给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
class Solution { public: vector<int> sortedSquares(vector<int>& nums) { int right = 0; int left = nums.size()-1; int n = nums.size(); vector<int> result(nums.size(),0); while(n--) { if(nums[left]*nums[left] > nums[right]*nums[right]) { result[n] = nums[left]*nums[left]; left--; } else{ result[n] = nums[right]*nums[right]; right++; } } return result; } };
209.长度最小的子数组
-
本题关键在于理解滑动窗口。这个while循环很重要,老是想成if,if只能执行一次,不能保证这个一次循环后sum<target.
class Solution { public: int minSubArrayLen(int target, vector<int>& nums) { int res = INT_MAX; int i =0; int j =0; int sum =0; int sub = 0; for(i<=j;j<nums.size();j++) { sum += nums[j]; while(sum>=target) { sub = j-i+1; res = res < sub ? res :sub; sum -= nums[i]; i++; } } return res == INT_MAX ? 0 : res; } };
59.螺旋矩阵II
- 左闭右开:重点是把区间分割明白,loop次数搞明白。
- 填充上行从左到右
- 填充右列从上到下
- 填充下行从右到左
- 填充左列从下到上
class Solution { public: vector<vector<int>> generateMatrix(int n) { vector<vector<int>> grid(n,vector<int>(n,0)); int loop = n/2; int startx=0; int starty=0; int count =1; int offset = 1; while(loop--) { for(int i = startx;i<n-offset;i++) { grid[startx][i] = count++; } for(int i= starty;i<n-offset;i++) { grid[i][n-offset] = count++; } for(int i =n-offset;i>startx;i--) { grid[n-offset][i] = count++; } for(int i=n-offset; i>starty;i--) { grid[i][starty] =count++; } startx++; starty++; offset++; } if(n%2) { grid[n/2][n/2]=count; } return grid; } };
58. 区间和
- 前缀和思想,根据前缀和,可以求区间和
#include <bits/stdc++.h> using namespace std; int main() { int n; cin>>n; std::vector<int> total; int a; int sum =0; while(n--) { cin>>a; sum +=a; total.push_back(sum); } int m1,m2; while(cin>>m1>>m2) { if(m1==0) { cout<<total[m2]<<endl; } else { cout<<total[m2]-total[m1-1]<<endl; } } return 0; }
44. 开发商购买土地
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int main()
{
int n, m;
cin >> n >> m;
int sum = 0;
vector<vector<int>> grid(n, vector<int>(m, 0));
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin >> grid[i][j];
sum += grid[i][j];
}
}
int result = INT_MAX;
int sum1=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
sum1 += grid[i][j];
if(j == m-1)
{
result = min(result,abs(sum-sum1-sum1));
}
}
}
sum1 =0;
for(int j=0;j<m;j++)
{
for(int i=0;i<n;i++)
{
sum1 += grid[i][j];
if(i==n-1){
result = min(result,abs(sum-sum1-sum1));
}
}
}
cout<< result<<endl;
return 0;
}
数组完结。。。。。