算法学习(Day1) |LeetCode(C++)| 704.二分查找、27.移除元素

文章详细解析了LeetCode上的两道题目,分别是704.二分查找和27.移除元素。在二分查找中,探讨了左闭右闭和左闭右开两种区间定义以及防止溢出的计算方法。在移除元素问题中,介绍了单遍历和快慢指针两种解决方案,强调了指针移动的策略和效率。
摘要由CSDN通过智能技术生成

LeetCode 704.二分查找

相关学习

文章讲解视频讲解

分析

初步理解与思路:

1.设置两个变量用来实现二分查找的查找范围收缩,low=0、hight=nums.size(); mid=(low+hight)/2
2.再通过mid与target比较来收缩范围。

随想录读后理解

初步理解的遗漏,收缩范围就是对区间进行操作,其中是选择左开还是右开等未能深度理解其中作用
疑问:什么叫做循环不变量?

代码实现

//左闭右闭
int low=0,hight=nums.size()-1;
        int mid;
        while(low<=hight){
            mid=(low+hight)/2;
            //防止溢出且等同于mid=(low+hight)/2;
            //mid=low+((hight-low)/2);
            //mid=low+((hight-low)>>1);??
            if(nums[mid]==target){return mid;}
            else if(nums[mid]<target){ low=mid+1;}
            else if(nums[mid]>target){hight=mid-1;}
        }
        return -1;
    }
//左闭右开
int low=0,hight=nums.size();
        int mid;
        while(low<hight){
            mid=(low+hight)/2;
            mid=low+((hight-low)/2);
            //mid=low+((hight-low)>>1);??
            if(nums[mid]==target){return mid;}
            else if(nums[mid]<target){ low=mid+1;}
            else if(nums[mid]>target){hight=mid;}
        }
        return -1;
    }

代码分析:

  1. 关键点Ⅰ:区间定义 左闭右闭、左闭右开
    左闭右闭区间 如数组a[8] 其区间为 low=0、hight=7;
    条件为low<=hight,low=mid+1,hight=mid-1; 因为mid已经判断过,收缩区间中无mid。
    左闭右开区间 区间为low=0、hight=8;
    条件为 low<hight,low=mid+1,hight=mid.因为为右开 low==hight不存在故无等号,hight=mid 是需要保持右开的状态,最后一个比较元素为low位置。
    查找的情况不同:
    左闭右闭查找情况如下在这里插入图片描述
    左闭右开查找情况如下在这里插入图片描述
  2. 关键点Ⅱ 防止溢出且等同于mid=(low+hight)/2;
    //mid=low+((hight-low)/2);
    //mid=low+((hight-low)>>1);

笔记整理与收获

LeetCode 27-移除元素

相关学习

文章讲解视频讲解

分析

初步理解与思路:

1.设置一个遍历变量依次往后遍历整个给数组,长度为原数组长度。设置一个累计变量记录不相等的元素数量,最后将该值返回即为数组长度,遍历变量++。每找到一个元素,将后续元素前移一位,重新判断。
2.设置快慢变量,慢变量为最后剩下元素数量,快变量为遍历变量。

随想录读后理解

初步理解的遗漏,后继元素前移遍历数还是会继续往后遍历,但是前移的元素就会被跳过判断。使用快慢变量能更加准确的继续替换,而不出现前移的元素被跳过。遍历变量作为快变量,low变量作为慢变量。
另一种方式,可以采用两头并进的方式,将需要删除的元素移到后面,故从前找需要删除的,从后找不需要删除的,交换两个位置的值,直到前后“指针”会于一点。

代码实现

int size=nums.size();
        int low=0;
        for(int i=0;i<size;i++){
            if(nums[i]!=val){nums[low++]=nums[i];}
           }
        return low;
        }
//代码随想录
 int rear=nums.size()-1;
        int front=0;
        while(front<=rear){
            while(front<=rear&&nums[front]!=val){front++;}
            while(front<=rear&&nums[rear]==val){rear--;}
            if(front<rear){nums[front++]=nums[rear--];}   
        }
        return front;
        }

代码分析:

  1. 关键点Ⅰ:快慢指针
    常用于将两个循环简化成一个循环。对于数组的覆盖较为方便。
  2. 关键点Ⅱ :两个指针,一个从前遍历,一个从后遍历。 需要注意的是,再设置两个方向遍历时,== 其中的变量如 front 或rear都是在变化的,故也需要加上判断条件如 front<=rear ==。因为在front与rear相遇之前就实现了题目的要求,也就不需要进行交换了。

笔记整理与收获

VsdeDebug代码

#include<iostream>
using namespace std;
//二分查找
/*
void search(int a[], int size, int target){
	int low = 0,hight;
	int mid;
	//左闭右闭
	hight = size - 1;
	while (low <= hight){
		mid = low + ((hight - low) >> 1);
		if (a[mid] > target){ 
			cout << "当前找到位置为:" << mid << " 其值:" << a[mid] << endl;
			hight = mid - 1;
		}
		else if (a[mid] < target){
			cout << "当前找到位置为:" << mid << " 其值:" << a[mid] << endl;
			low = mid + 1;
		}
		else if (a[mid] == target){
			cout << "找到target位置为:" << mid <<" 值为:"<< a[mid] << endl;
			return;
		}
	}
	cout << "未找到target位置"<< endl;
	
	//左闭右开
	hight=size;
	while (low < hight){
		mid = low + ((hight - low) >> 1);
		if (a[mid] > target){
			cout << "当前找到位置为:" << mid << " 其值:" << a[mid] << endl;
			hight = mid ;
		}
		else if (a[mid] < target){
			cout << "当前找到位置为:" << mid << " 其值:" << a[mid] << endl;
			low = mid + 1;
		}
		else if (a[mid] == target){
			cout << "找到target位置为:" << mid << " 值为:" << a[mid] << endl;
			return;
		}
	}
	cout << "未找到target位置" << endl;
}*/   
//移除元素
int remove(int a[],int size,int val){
	int low = 0;
	for (int i = 0; i < size; i++){
		if (a[i] != val){
			a[low] = a[i]; low++; 
		}
	}
	return low;
}
int remove_2(int a[], int size, int val){
	int front = 0;
	int rear = size - 1;
	while (front <= rear){
		while (front <= rear&&a[front] != val){ front++; }
		while (front <= rear&&a[rear] == val){ rear--; }
		if (front < rear){ a[front++] = a[rear--]; }
	}
	return front;
}
void test_array(){//创建一个一维数组,并输出。
	int array[4] = { 2, 3, 2, 3 };
	for (int i = 0; i < 4; i++){
		cout << array[i]<<" "<<endl;
	}
	int len=remove_2(array, 4, 3);
	cout << len << endl;
	//search(array,6,9);
}
int main(){
	test_array();

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值