算法day01 数组| 704二分查找/ 27移除元素/ 977有序数组的平方
相关知识
数组
- 下表从0开始
- 内存空间的地址是连续的
- 所以数组元素不能删除只能覆盖, 不能单独删除数组中的某个元素
1. 二分查找 LeetCode 704
题目要求
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果 target 存在返回下标,否则返回 -1
你必须编写一个具有 O(log n) 时间复杂度的算法。
示例 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]之间。
nums 的每个元素都将在 [-9999, 9999]之间。
基本思路
设定target的索引在某一区间内
首先判定targe是否在该数组内
如果在则进行以下步骤:
将区间中点middle 对应的nums制和target进行判定
如果nums[middle] < target, 更新区间的左边界
如果nums[middle] > target, 更新区间的右边界
第一种写法 区间左闭右闭[]
- 设定target的索引在[left, right] 内
- [left, right] 左边界可能等于右边界 所以while(left<=right)
-
- 该区间范围包含右边界 , 所以right = nums.length-1, 就能够包含target可能的索引值
- 当在 if(nums[middle] > target)时 right = middle -1 因为middle肯定大于target对应的索引
// 左闭右闭的写法[]
public int search(int[] nums, int target) {
if(target < nums[0] || target > nums[nums.length-1]){
return -1;
}
int left =0 ;
int right = nums.length-1;
while(left <= right){
int middle = left + (right - left)/2;//需要在每次循环中进行更新
if(nums[middle] < target){
//更新左边界
left = middle + 1;
}else if(nums[middle] > target){
right = middle -1;
//更新右边界
}else{
return middle;
}
}
return -1;
第二种写法 左闭右开[)
- 设定target的索引在[left, right) 内
- [left, right) 左右肯定不等, 所以while(left < right)
- 该区间范围不包含右边界 , 所以right = nums.length, 而不是nums.length -1 , 为了区间包含target可能的索引值
- 当在 if(nums[middle] > target)设置右边界的时候 right = middle ** 因为middle肯定大于target对应的索引, 且right不被区间范围包含**
- ">>"意思是右移一位, 也就是/2
/**
**左闭右开的写法[) 不存在[num1, num2)时num1=num2
*/
public int search(int [] nums, int target){
// 判断是否在该数组中 防止目标值大于最大或小于最小是还进入循环
if( target < nums[0] || target > nums[nums.length-1]){
return -1;
}
int left = 0;
int right = nums.length; //索引越界但是它只是一个边界的标记, 也就是不包含该制
while(left < right){
int middle = left + ((right - left)>>1); //右移一位
if(nums[middle] < target){
//更新左边界
left = middle + 1;
}else if(nums[middle] > target){
//更新右边界
right = middle;
}else{
return middle;
}
}
return -1;
}
2.移除元素 LeetCode 27

双指针法
- 设定两个指针, fast和slow
- fast指针用来遍历数组, 寻找新数组的元素
- slow指针指向新的数组下标的位置
- 将fast指向的元素进行比对, 如果不一致则slow++, 如果一致则slow指向不变, 避开为val的元素
- 时间复杂度为O(n)
- 空间复杂度为O(1)
class Solution {
public int removeElement(int[] nums, int val) {
int slow = 0;
for(int fast = 0 ; fast < nums.length ; fast++ ){
if(nums[fast] != val){ //慢指针指向不为val的元素
nums[slow] = nums[fast];
slow ++;
}
}
return slow;
}
}
暴力解法 两层for循环

- 外层i 寻找享用值的元素
- 内层j 讲后续的所有元素依次向前移动一位\
- 注意找到后进行i– , 进行再次判断当前i索引的元素, 因为当前i索引的元素已经被覆盖过了, 仍然可能=val
//暴力解法
public int removeElement(int[] nums, int val){
int size = nums.length;
//第一层寻找等于val的制
for(int i=0; i<size ; i++ ){
if(nums[i] == val){
//第二层 在找到后将之后的索引全部前移动
for(int j = i ; j<size-1; j++){
nums[j] = nums[j+1];
}
size--;
i--; //注意注意
}
}
return size;
}
3. 有序数组的平方
题目描述
给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
示例 1:
- 输入:nums = [-4,-1,0,3,10]
- 输出:[0,1,9,16,100]
- 解释:平方后,数组变为 [16,1,0,9,100],排序后,数组变为 [0,1,9,16,100]
示例 2:
- 输入:nums = [-7,-3,2,3,11]
- 输出:[4,9,9,49,121]
暴力解法
思路
- 首先遍历一遍数组, 将每个元素平方后重新赋值
- 利用Arrays.sort(nums)进行升序排序
- O(n + nlogn)时间复杂度
public int[] sortedSquares(int[] nums) {
//将全部元素进行平方
int i = 0;
while( i < nums.length){
nums[i] *= nums[i];
i++;
}
Arrays.sort(nums);
return nums;
}
注意
- nums[i] *= nums[i];即可赋值
双指针法
思路
-
给出的数组是有序的, 但是平方后的最大值可能会出现在数组两端
-
设置两个指针i, j.
i指向起始位置, 从左到右
j指向终止位置,从右到左 -
设置新数组result 和新的索引index, 让index指向终止位置
-
判断:
如果nums[i]平方>nums[j]平方,则 result[index–] =nums[i]平方,i++, i右移,j不变
如果nums[i]平方<nums[j]平方,则 result[index–] =nums[j]平方,j–, j左移,i不变
/**
1. 双指针法 */
public int[] sortedSquares(int[] nums) {
//设定一个新数组, 存储新的排序元素
//两个指针一个向后, 一个向前
int index = nums.length-1;
int[] result = new int [nums.length];
for(int i = 0, j = nums.length-1; i<=j;){
int squarei = nums[i] * nums[i];
int squarej = nums[j] * nums[j];
if(squarei>squarej){
//如果i对应的元素大于j对应的元素, 则将i对应的元素存入新数组的j索引处, 然后两个索引都向中间移一位
result[index--] = squarei;
i++;
} else{ //如果i对应的元素小于等于j对应的元素, 则将j对应的元素存入新数组的最后,
result[index --] = squarej;
j--;
}
}
return result;
}
注意
- int i,j连续初始化赋值
- for(int i = 0, j = nums.length-1; i<=j;)循环中i,j的加减操作写到循环体中,而不在声明中, 更易于控制
8782

被折叠的 条评论
为什么被折叠?



