学习目标:
- 704. 二分查找
- 27. 移除元素
- Java基础常见面试题总结(上)
学习内容:
704. 二分查找
题目链接 &&文章讲解
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
左闭右闭区间 [left, right]
class Solution {
public int search(int[] nums, int target) {
//判断target是否在数组查找区间
if (target < nums[0] || target > nums[nums.length - 1]) {
return -1;
}
int left=0;
int right=nums.length-1;//[0,nums.length-1]
while(left<=right){//left == right [left, right]为有效区间
int mid = left + ((right - left) >> 1);//mid=(left+right)/2;
if(nums[mid]<target) {
left=mid+1;//[mid+1,right]
}else if(nums[mid]>target){
right=mid-1;//[left,mid-1]
}else{
return mid;
}
}
return -1;
}
}
左闭右开区间[left, right)
class Solution {
public int search(int[] nums, int target) {
//判断target是否在数组查找区间
if (target < nums[0] || target > nums[nums.length - 1]) {
return -1;
}
int left=0;
int right=nums.length;//[0,nums.length)
while(left<right){//left == right [left, right)为无效区间
int mid = left + ((right - left) >> 1);//mid=(left+right)/2;
if(nums[mid]<target) {
left=mid+1;//[mid+1,right)
}else if(nums[mid]>target){
right=mid;//[left,mid)
}else{
return mid;
}
}
return -1;
}
}
- 二分法前提:数组为有序数组 数组中无重复元素
- 区间选择:指针的初始化、循环结束的条件、指针的更新方式
- mid溢出问题: mid = (l + r) / 2时,如果l + r 大于 INT_MAX那么就会产生溢出问题
mid = l + (r - l) / 2或者 mid = l + ((r - l) >> 1) 可以避免溢出问题- target判断:避免当 target 小于nums[0]或target大于nums[nums.length - 1]时多次循环运算
- 时间复杂度:O(log n) 空间复杂度:O(1)
27. 移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
- 不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组
- 元素的顺序可以改变,你不需要考虑数组中超出新长度后面的元素
暴力法
class Solution {
public int removeElement(int[] nums, int val) {
int len=nums.length;
for(int i=0;i<len;i++){
if(nums[i]==val){//查找要移动的元素
for(int j=i+1;j<len;j++){
nums[j-1]=nums[j];//数组集体向前移动
}
i--;//i也向前移动一位
len--;//更新数组长度
}
}
return len;
}
}
快慢指针法
class Solution {
public int removeElement(int[] nums, int val) {
int slow=0;
for(int fast=0;fast<nums.length;fast++){//fast寻找新数组元素
if(nums[fast]!=val){
nums[slow]=nums[fast];//slow更新新数组
slow++;
}
}
return slow;
}
}
相向指针法
class Solution {
public int removeElement(int[] nums, int val) {
int left=0;
int right=nums.length-1;
while(right>=0&&nums[right]==val) right--;//right指向值不为val的元素
while(left<=right){
if(nums[left]==val){//left指向要删除的元素
nums[left]=nums[right]; //right元素移到left
right--;//right位置移除
}
left++;
while(right>=0&&nums[right]==val) right--;
}
return left;
}
}
- 暴力法:一个for循环遍历数组元素 ,第二个for循环更新数组,在更新数组之后,由于数组整体前移,需要把第一层循环下标-1,向前移动一位
时间复杂度:O(n^2) 空间复杂度:O(1)- 快慢指针法:快指针寻找新的数组元素(即跳过数组中值为val的元素),慢指针根据快指针寻找到的元素更新数组,慢指针的下标即为新数组长度
时间复杂度:O(n) 空间复杂度:O(1)- 相向指针法:改变数组的顺序,将右边不等于val的元素覆盖左边等于val的元素
时间复杂度:O(n) 空间复杂度:O(1)
Java基础常见面试题总结(上)
基础概念与常识
- Java语言特点
- Java SE vs Java EE
- JVM vs JDK vs JRE
- 字节码及其好处
- “编译与解释并存”
- AOT编译模式优点
- Java和C++区别
基本语法
- 三种注释形式
- 标识符和关键字
- 自增自减和移位运算符
- continue、break、return
基本数据类型
- 8种基本数据类型默认值和空间
- 基本类型和包装类型
- 自动装箱与拆箱
- 浮点数运算精度丢失
- BigInteger类型
变量
- 成员变量与局部变量
- 静态变量作用
- 字符型常量与字符串常量
方法
- 方法的返回值和返回值和参数类型
- 静态方法为什么不能调用非静态成员
- 静态方法和实例方法
- 重载和重写
- 可变长参数