一.二分查找
题目描述:
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
自己的思路:
分为两种情况:
1.数组中不存在要找的数
1.1.target小于最小值或target大于最大值
1.2.taget大于最小值并小于最大值
1.2.1.那么这种情况只能是夹在两个数中间了
2.数组中存在要找的数
然后是定义两个指针,移来移去,这里面我还存在比如说什么时候取小于,什么时候取小于等于这些操作符有些混淆的问题。
然后脑子里想了想,比如说要找的是2.5,数组中相邻的两个是2,3,那么i一定等于j,不会出现j==k的情况。
package 二分查找;
public class _704 {
public int search(int []nums,int target){
int n = nums.length;//数组的长度
int j = 0;//左边指针
int k = n-1;//右边指针
/*target小于数组中的最小值或大于最大值,直接返回-1*/
if (target<nums[0]||target>nums[n-1]){
return -1;
}
/*要去里面找*/
while(j<=k){
if (j+1==k&&nums[j]<target&&target<nums[k]){
return -1;
}
if(target==nums[j]){
return j;
}else if(target==nums[k]){
return k;
}
int i = (j+k)/2;
if (target<nums[i]){
k=i;
}else if (target>nums[i]){
j=i;
}else if (target==nums[i]){
return i;
}
}
return -1;
}
}
根据我自己脑子里想想写的方法,这是写的结果,等下我去看下博客和视频看下有没有提升。
看了下视频,有两个可以提升的地方,一个是没有考虑好左闭右闭区间的问题,一个是取中间值的时候重复判断了,现在去重新ti
class Solution {
public int search(int[] nums, int target) {
int n = nums.length;//数组的长度
int j = 0;//左边指针
int k = n-1;//右边指针
/*第一种情况,target小于数组中的最小值或大于最大值,直接返回-1*/
if (target<nums[0]||target>nums[n-1]){
return -1;
}
/*第二种情况,要去里面找*/
while(j<=k){
int i = (j+k)/2;
if (target==nums[i]){
return i;
}else if (target<nums[i]){
k=i-1;
}else if (target>nums[i]){
j=i+1;
}
}
//如果上面while循环结束还没有找到,那么就是夹在中间的情况,直接返回-1
return -1;
}
}
没什么提升,但是思路清晰了很多。
二.移除元素
题目描述:
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
思路:
因为要求是O(1),而且不需要考虑超出新长度后面的元素,所以脑子里想到是交换,先写一下,看看对不对。
package 移除元素;
public class _27 {
public int removeElement(int[] nums, int val) {
int j = 0;
for (int i=0;i<nums.length;i++){
if (nums[i]==val){
j++;
}
}
/*
* 1.现在知道数量了,如果有5个,把这5个移到数组后面去;
* 2.如果后面5个中已经包含了val,保留,只需移动前面几个
* */
if (j==0){
return nums.length;
}else{
for(int i =0;i<nums.length;i++){
if (nums[i]==val&&i<nums.length-j){
for (int k=nums.length-j;k<nums.length;k++){
if (nums[k]!=val){
int temp=nums[i];
nums[i]=nums[k];
nums[k]=temp;
}
}
}
}
}
return nums.length-j;
}
}
去看下视频。
讲了一个快慢指针的操作,直接把时间复杂度度变成O(n)了,是真的牛逼。
class Solution {
public int removeElement(int[] nums, int val) {
int i = 0;//慢指针,指向新数组的下标
int j = 0;//快指针,指向符合新数组条件的数的下标
for (;j<nums.length;j++){
if (nums[j]!=val){
nums[i]=nums[j];
i++;
}
}
return i;
}
}