704 二分查找
704. 二分查找https://leetcode.cn/problems/binary-search/
题目描述:
给定一个 n
个元素有序的(升序)整型数组 nums
和一个目标值 target
,写一个函数搜索 nums
中的 target
,如果目标值存在返回下标,否则返回 -1
。
解题思路:
有两个关键问题。
1. 如何定义区间?区间的定义决定whlie循环的条件。
一般会定义为左闭右闭区间或者左闭右开区间。
如果是左闭右闭区间,那么left<=right合法,如果是左闭右开区间,那么left<right合法。
2. target不等于nums[mid]时,区间端点如何变化?
以target<nums[mid]为例,此时target偏小。
如果是左闭右闭区间,区间右端点要到mid的左边,需要right=mid-1。因为如果right=mid的话,下一次搜索的区间又包括了mid,但是条件中已经说了target<nums[mid],所以下一次的区间不能含有mid。
如果是左闭右开区间,区间右端点要到mid的左边,right=mid即可,因为右边是开的。
两种情况的区间左端点一样,都是left=mid+1。因为左边都是闭的。
代码:
左闭右闭区间:
class Solution {
public int search(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while(left <= right){//左闭右闭区间,括号中是区间合法的条件
int mid = (left + right) / 2;
if(target < nums[mid])
//target较小,要在左侧区间搜索。且nums[mid]不符合条件,左侧区间不能包含mid
right = mid - 1;
else if(target > nums[mid]) left = mid + 1;
else return mid;
}
return -1;
}
}
左闭右开区间:
class Solution {
public int search(int[] nums, int target) {
int left = 0, right = nums.length;
while(left < right){//左闭右开区间,括号中是区间合法的条件
int mid = (left + right) / 2;
if(target < nums[mid])
//target较小,要在左侧区间搜索。且nums[mid]不符合条件,左侧区间不能包含mid
right = mid;
else if(target > nums[mid]) left = mid + 1;
else return mid;
}
return -1;
}
}
27 移除元素27. 移除元素
https://leetcode.cn/problems/remove-element/题目描述:
给你一个数组 nums
和一个值 val
,你需要原地移除所有数值等于 val
的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1)
额外空间并原地修改输入数组。
解题思路:
如果不要求原地的话好办,新开一个数组,然后一个指针去遍历旧数组,不等于val的值就放到新数组中。但是本题要求空间复杂度O(1),那么就需要双指针。
fast用于遍历数组,slow作为新数组下标。(这个新数组不是新开空间的新数组,位置没有变,和nums是一个空间,只是含义变了)
fast是萝卜,slow是坑,把右边的萝卜填到左边的坑里。
fast什么情况都+1,slow符合条件才+1。(条件是fast指的值不是val)
代码:
class Solution {
public int removeElement(int[] nums, int val) {
int fast = 0, slow = 0;
while(fast < nums.length){
if(nums[fast] != val) nums[slow++] = nums[fast];
fast++;
}
return slow;
}
}
977 有序数组的平方
977. 有序数组的平方https://leetcode.cn/problems/squares-of-a-sorted-array/
题目描述:
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
解题思路:
这个难在nums中可能有负数。要是都是正数,那不就直接平方了,原数组的顺序和平方后的顺序一样。有负数的话,可以想象,平方后大的数在左右两头。
那么就用双指针来处理,一个从最左边开始(i),一个从最右边开始(j),比较i和j所指数的大小,更大的那个放到新数组中。所以新数组从大到小来更新(下标k)。
由于语法忘了,此处加点java创建数组的小知识:
1. 声明并赋值
int[] arr = {1,2,4};
2. 声明数组名开辟空间并且赋值
int[] arr;
arr = new int[]{1,2,3};3. 声明数组时指定元素个数然后赋值
int[] arr1= new int[3];
注意:最大元素下标为2,并且所有的元素值均为0
赋值一般用for循环在Java中,当你声明并初始化一个基本类型数组,比如
int
类型的数组,它的每个元素都会被自动初始化为该类型的默认值。对于int
类型的数组,每个元素的初始值是0
。创建数组,如果在创建的同时不初始化数组则必须指定其大小: int Array0=new int[3];
--------------------------------------------------------------------------
参考链接:
代码:
class Solution {
public int[] sortedSquares(int[] nums) {
int len = nums.length;
int i = 0, j = len - 1, k = len - 1;
int[] res = new int[len];
while(i <= j){
if(nums[i] * nums[i] > nums[j] * nums[j]){
res[k--] = nums[i] * nums[i];
i++;
}
else{
res[k--] = nums[j] * nums[j];
j--;
}
}
return res;
}
}