力扣刷题(代码随想录顺序)
数组
二分查找
704. 二分查找【简单题】
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1
算法思路:通过两个指针,左边为称为L(left) 右边为R(right),
(L+R)/2=M
分为三种情况:
如果M的值等于target 那么返回M
如果M的值大于target 那么就说明要找的值在M指针的左边,此时将R赋值为M,继续重复
如果M的值小于target 那么就说明要找的值在M指针的右边,此时将L赋值为M,重复
那么程序出口是什么呢?假设在最后还没找到 那么我们可以往回退两个步骤
LMR-> L(M)R(此时LM是同一个位置) -> (LMR)(此时LMR都在同一个位置)
代码实现:
递归法实现
循环实现
下面展示一些 内联代码片
。
#include <vector>
#include<iostream>
using namespace std;
class Solution {
public:
int search(vector<int>& nums, int target) {
return sea(0,nums.size()-1,nums,target);
}
int sea(int l,int r,vector<int>& nums, int target){
int m = (l+r)>>1;
if (l==r) return -l;
else if (nums[m]==target) return m;
else if(nums[m]>target) return sea(l,m, nums,target);
else if(nums[m]<target) return sea(m,r,nums,target);
}
};
class Solution2{
public:
int search(vector<int> &nums,int target){
int r = nums.size()-1;
int l = 0;
int m = (l+r)>>1;
while(true){
if(l==r){
m = -1;
break;
}
else if (nums[m]>target) r = m;
else if (nums[m]<target) l = m;
else if (nums[m]==target) break;
m = (l+r)>>1;
}
return m;
}
};
移除元素
思路,总体来说就是将后面的元素覆盖前面的元素
实现方法有两个
方法一:暴力循环这没什么好说的学过C语言就应该回了
方法二:双指针法
注:这里使用了代码随想录的一个图,侵权删!
代码思路:
情况一:fast =low -> fast++ low++
情况二:fast != low ->
情况一:
nums[fast]!=val
nums[low] = nums[fast]
fast ++ low ++
情况二:
nums[fast] ==val
fast++
len–
class Solution {
public:
int search(vector<int>& nums, int target) {
return sea(0,nums.size()-1,nums,target);
}
int sea(int l,int r,vector<int>& nums, int target){
int m = (l+r)>>1;
if (l==r) return -l;
else if (nums[m]==target) return m;
else if(nums[m]>target) return sea(l,m, nums,target);
else if(nums[m]<target) return sea(m,r,nums,target);
}
};
class Solution2{
public:
int search(vector<int> &nums,int target){
int r = nums.size()-1;
int l = 0;
int m = (l+r)>>1;
while(true){
if(l==r){
m = -1;
break;
}
else if (nums[m]>target) r = m;
else if (nums[m]<target) l = m;
else if (nums[m]==target) break;
m = (l+r)>>1;
}
return m;
}
977.有序数组的平方
题目说明
// 977. 有序数组的平方
// 给你一个按 非递减顺序 排序的整数数组 nums,返回 每
// 个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
// 示例 1:
// 输入:nums = [-4,-1,0,3,10]
// 输出:[0,1,9,16,100]
// 解释:平方后,数组变为 [16,1,0,9,100]
// 排序后,数组变为 [0,1,9,16,100]
解题思路
先排序,然后一个指针指向尾指针,一个头指针,谁的平方大谁动
class Solution{
public:
vector<int> sortedSquares(vector<int>& nums){
vector<int> result = vector<int>(nums.size(),0);
int k = nums.size()-1;
for(int i=0,j=nums.size()-1;i<=j;){
if (nums[i]*nums[i]<=nums[j]*nums[j]){
result[k--] = nums[j]*nums[j];
j--;
}
else{
result[k--] = nums[i]*nums[i];
i++;
}
}
return result;
}
};
209.长度最小的子数组
题目说明
/*
209.长度最小的子数组
题目链接:https://leetcode-cn.com/problems/minimum-size-subarray-sum/
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。
示例:
输入:s = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
*/
同样用双指针法,一个头指针一个尾指针,在头尾指针之和大于s时,尾向前移动,小于s时,头向前移动,当相加起来等于s时,不断向前即可。
螺旋矩阵Ⅱ
题目说明:
我直接举例把
01 02 03 04
12 13 14 05
11 16 15 06
10 09 08 07
这道题我并不认为难并且思路和代码随想录的不一样,我是用了四个挡板,也就是上下左右具体看代码就很容易懂
class Solution {
public:
vector<vector<int>> generateMatrix(int n) {
int left = 0;
int right = n-1;
int up = 0;
int down = n-1;
vector<vector<int>> res(n, vector<int>(n, 1));//知识点一个
int i =0;
int j = 0;
int count = 1;
while(true){
//向左跑
while( j<right )
res[i][++j]=++count;
up+=1;//上挡板下降一个
//向下跑
while(i<down)
res[++i][j] = ++count;
right-=1;
while(j>left)
res[i][--j] = ++count;
down--;//下挡板上升一个
while(i>up)
res[--i][j]=++count;
left++;
if(count>=n*n)
break;
}
return res;
}
};
1二数之和
没什么好说的 跳过一下
2三数之和
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:[ [-1, 0, 1], [-1, -1, 2] ]
首先要用排序,为什么呢,我现在可以给出理由,第一就是避免重复值的出现,避免了去重这一步,(看呆会的操作就知道了) 第二是算法用三指针法 二指针和三指针在移动的时候就是根据大小来移动的。
这道题稍微难一些,可以理解为 二数之和 是双指针法,三数之和 是三指针法
首先第一个指针从i=0到size()-1没什么好说的,然后第二个指针从i+1开始 到尾指针结束,第三个自然是尾指针,二指针三指针之和加起来为target-nums[i] 然后两个指针不断移动, 如果 三个加起来大于target 那么说明尾指针太大了,如果小于0,说明头指针太小了,那么自然是要相应的往中间靠,那么往中间靠的过程。如果是碰上了加起来等于target的值,自然是要指针相应移动,但是下一个值和当前值相同,怎么办? 解决办法就是,判断当前值和下一个值相同否,相同继续移动
(来源:代码随想录)
侵删!
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> result;
sort(nums.begin(),nums.end());
int len = nums.size()-1;
for(int i =0;i<=len-3;i++){
//如果都连在一起了肯定就不用了下一次了
for(int j = i+1;j<=len-2;j++){
int left = j+1;
int right = len;
while(left<right){
int a = nums[i]+nums[j]+nums[left]+nums[right];
if(a==target){
vector<int> temp = {nums[i],nums[j],nums[left],nums[right]};
result.push_back(temp);
while (right>i &&nums[right-1]==nums[right]) {
//如果需要下一个和当前的相同,那我肯定要让他继续移动啊
right--;
// cout<<right<<"right="<<endl;
}
while( left<len && nums[left+1]==nums[left]){
left++;
// cout<<left<<"left="<<endl;
}
right--;
left++;
continue;//移动完成后就交给下一轮去做把
}
if(a>0){
right--;
}
if(a<0){
left++;
}
}
}
while(i<len&&nums[i]==nums[i+1]){
i++;
}
}
return result;
}
};
四数之和
没什么好说的 再套一层循环,同时避免越界就好
总结
数组篇总结:
第一自然是双指针法
然后就是一些vector的构造
vector构造的例子
vector():创建一个空vector
vector(int nSize):创建一个vector,元素个数为nSize
vector(int nSize,const t& t):创建一个vector,元素个数为nSize,且值均为t
vector(const vector&):复制构造函数
vector(begin,end):复制[begin,end)区间内另一个数组的元素到vector中
vector的常用函数
void push_back(const T& x):向量尾部增加一个元素X
void pop_back():删除向量中最后一个元素
iterator begin():返回向量头指针迭代器,指向第一个元素
iterator end():返回向量尾指针迭代器,指向向量最后一个元素的下一个位置