个人简介:
大一新生(主攻C、C++) 专业:计算机科学与技术
引言:
刚接触算法,每一个算法的设计总是让我深思,从时间和空间的角度考虑算法的可行性。即使最开始会很枯燥,甚至烦躁,但是当静下心来,理清思路,从变量的定义,数据类型的转化,循环······
···
反正,坚持下去就对了!这一次,是为了“热爱”
一.(704. 二分查找 - 力扣(LeetCode))
1.题目:
给定一个
n
个元素有序的(升序)整型数组nums
和一个目标值target
,写一个函数搜索nums
中的target
,如果目标值存在返回下标,否则返回-1
。
示例 1:
输入:nums=[-1,0,3,5,9,12],
target=9
输出: 4 解释:9 出现在nums中并且下标为 4
示例 2:
输入:nums= [-1,0,3,5,9,12],
target = 2
输出: -1 解释:2 不存在nums中因此返回 -1
提示:
- 你可以假设
nums
中的所有元素是不重复的。 n
将在[1, 10000]
之间
2.思路:
1.定义变量
类型:整形int
意义:left:数组最左边数字的下标 ;
right :数组最右边数字的下标;
middle:数组中间数的下标;
2.逻辑流程
利用二分法,不断更新区间
3.代码实现
1.左闭右闭:
C++
//左闭右闭 [left,right]
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0,right =nums.size()-1,middle; //定义出左右区间及中间值
while(left<=right){
middle=left+(right-left)/2; //防止溢出(也可以用>>1)
if(nums[middle]>target){
right =middle-1; //更新右区间
}
else if(nums[middle]<target){
left=middle+1; //更新左区间
}
else {
return middle;
}
}
return -1;
}
};
C
int search(int* nums, int numsSize, int target) {
int left=0,right=numsSize-1,middle;//数组的大小需要获取
while(left<=right){
middle=left+(right-left)/2;
if(nums[middle]>target){
right=middle-1;
}
else if(nums[middle]<target){
left=middle+1;
}
else {return middle;}
}
return -1;
}
2.左闭右开(注意三个不一样的地方):
C++
//左闭右开 [left,right)
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0,right =nums.size(),middle; //定义出左右区间及中间值
while(left<right){
middle=left+(right-left)/2; //防止溢出(也可以用>>1)
if(nums[middle]>target){
right =middle; //更新右区间
}
else if(nums[middle]<target){
left=middle+1; //更新左区间
}
else {
return middle;
}
}
return -1;
}
};
C
int search(int* nums, int numsSize, int target) {
int left=0,right=numsSize,middle;
while(left<right){
middle = left + (right-left)/2;
if(nums[middle]>target){
right=middle;
}
else if(nums[middle]<target){
left=middle+1;
}
else {return middle;}
}
return -1;
}
二、(27. 移除元素 - 力扣(LeetCode))
1.题目:
给你一个数组
nums
和一个值val
,你需要 原地 移除所有数值等于val
的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用
O(1)
额外空间并 原地 修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝 int len = removeElement(nums, val); // 在函数里修改输入数组对于调用者是可见的。 // 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 for (int i = 0; i < len; i++) { print(nums[i]); }
示例 1:
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释: 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。
示例 2:
输入:nums = [0,1,2,2,3,0,4,2], val = 2 输出:5, nums = [0,1,3,0,4] 解释:函数应该返回新的长度函数应该返回新的长度为5, 并且 nums 中的前五个元素为
0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。
提示:
0 <= nums.length <= 100
0 <= nums[i] <= 50
0 <= val <= 100
2.思路
数组中的元素无法删除,只能覆盖,遍历数组,然后将用目标值下一个不等于目标值的元素进行覆盖
3.代码实现
1.暴力解法
C++
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int size = nums.size();//获取数组的长度
for(int i = 0; i<size;i++){
if(nums[i] == val){ //寻找下标为i的与val相等的值
for(int j = i+1;j<size;j++){//内循环进行覆盖
nums[j-1]=nums[j];
}
i--; //下标前移
size--; //数组长度缩短
}
}
return size; //返回循环后数组的长度
}
};
C
int removeElement(int* nums, int numsSize, int val) {
for(int i = 0;i<numsSize;i++){
if(nums[i] == val){
for(int j = i+1;j<numsSize;j++){
nums[j-1]=nums[j];
}
i--;
numsSize--;
}
}
return numsSize;
}
2双指针法
C++
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowpoint = 0; //定义慢指针和快指针
for(int fastpoint = 0;fastpoint <nums.size();fastpoint++){
if(nums[fastpoint] != val){ //将快指针遍历的值存到满指针的数组中
nums[slowpoint++]=nums[fastpoint]; //每次更新后下标后移
}
}
return slowpoint; //慢指针的数值等于最后的数组长度
}
};
C
int removeElement(int* nums, int numsSize, int val) {
int slowpoint = 0;
for(int fastpoint = 0;fastpoint < numsSize;fastpoint++){
if(nums[fastpoint] != val){
nums[slowpoint++]=nums[fastpoint];
}
}
return slowpoint;;
}
3.相向指针法(还在学习中)
C++
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int leftIndex = 0;
int rightIndex = nums.size() - 1;
while(leftIndex<=rightIndex){
//找左边等于val的元素
while(leftIndex <= rightIndex && nums[leftIndex] != val){
++leftIndex;
}
//找右边不等于val的元素
while(leftIndex <= rightIndex && nums[rightIndex] == val){
--rightIndex;
}
//将右边不等于val的元素覆盖左边等于val的元素
if(leftIndex < rightIndex){
nums[leftIndex++] = nums[rightIndex--];
}
}
return leftIndex; //leftIndex一定指向了最终数组末尾的下一个元素
}
};
C
int removeElement(int* nums, int numsSize, int val) {
int leftIndex = 0;
int rightIndex = numsSize - 1;
while(leftIndex <= rightIndex) {
// 找左边等于val的元素
while(leftIndex <= rightIndex && nums[leftIndex] != val) {
++leftIndex;
}
// 找右边不等于val的元素
while(leftIndex <= rightIndex && nums[rightIndex] == val) {
--rightIndex;
}
// 将右边不等于val的元素覆盖左边等于val的元素
if(leftIndex < rightIndex) {
nums[leftIndex++] = nums[rightIndex--];
}
}
return leftIndex; // leftIndex一定指向了最终数组末尾的下一个元素
}