二分查找指定元素
/*
* 需求:
* 给定一个数组,判断是否包含某个值,如果包含则返回其下标,否则返回-1
* 顺序查找:
* 1 遍历,循环比较
* 2 如果有和目标元素相等,返回下标
* 3 如果循环结束,没有相等的,返回-1
* 缺点:查询效率低,如果有100万个数据,恰好查询值在末尾,时间复杂度则为100万,数据量小时使用
* 二分查找:
* 1 建立在排序的基础上
* 2 数据没有重复元素,如果有,先找到之前一个
* 3 用于查找固定有序的数
* 实现:
* 1 确定起始和结束位置
* 2 确定中间数据,判断是否为目标数据。若是直接返回
* 3 若目标数据小于中间数据,起始值不变,结束值为中间值减一
* 4 若目标数据大于中间数据,结束值不变,起始值为中间值加一
* 5 若起始值大于结束值,结束比较,说明不存在
* 6 循环执行
* */
public class Array_BinarySearch {
public static void main(String[] args) {
int[] nums = {2,3,1,5,6,0};
int value = 5;
int result = m2(nums, value);
System.out.println(result);
}
public static int m1(int[] nums, int value){
// 顺序查找
for (int i = 0; i < nums.length; i++) {
if (nums[i]==value) return i;
}
return -1;
}
public static int m2(int[] nums, int value){
// Arrays.sort(nums);
int count = 0; // 计算查找次数
int startPos = 0; // 起始位置
int endPos = nums.length - 1; // 结束位置
int middle = (startPos+endPos) / 2; // 中间位置
// 若起始值大于结束值,结束比较
while (startPos<=endPos){
count++;
if (nums[middle]==value){ // 判断目标数据是否等于中间值
System.out.println("count:"+count);
return middle;
}else if (nums[middle]>value){ // 判断目标数据是否小于中间值
endPos = middle - 1;
}else if (nums[middle]<value){ // 判断目标数据是否大于中间值
startPos = middle + 1;
}
middle = (startPos+endPos) / 2; // 重新计算中间值
}
System.out.println("count:"+count);
return -1;
}
}
// 方法声明:[修饰符列表] 返回值类型 方法名(参数列表){方法体}
/*
* 基本数据类型 保存值的大小,引用数据类型保存内存地址,Java中string是引用
* 传值:基本类型传递
*
* 值传递(pass by value)是指在调用函数时将实际参数复制一份传递到函数中,
* 这样在函数中如果对参数进行修改,将不会影响到实际参数
* 引用传递(pass by reference)是指在调用函数时将实际参数的地址直接传递到函数中,
* 那么在函数中对参数所进行的修改,将影响到实际参数
* */
查找数组中只出现一次的数字
/*
* 只出现一次的数字
* 给定一个非空整数数组,除了某个元素只出现一次外,其余元素均出现2次,找出只出现一次的元素,不使用额外的数组空间
* 实例:
* 输入:{2,2,1} 输出:1
* 输入:{2,4,1,2,1} 输出:4
* */
public class SearchOnly {
public static void main(String[] args) {
int[] nums = {2,1,4,4,2,1};
int result = searcher(nums);
System.out.println(result);
}
public static int searcher(int[] nums){
for (int i = 0; i < nums.length; i++) {
// 假设所有元素都是单个的,标记为false
boolean flag = false;
for (int j = 0; j < nums.length; j++) {
// 判断是否有元素出现第二次
// i!=j说明不是同一个位置上的元素
// nums[i]==nums[j]说明有元素出现第二次
if (i!=j && nums[i]==nums[j]){
// 下表不等,有成对的情况,标记为true
flag = true;
// 说明有相同元素,终止内层循环,找下一个数
break;
}
}
// 判断该数是否为单个
if (!flag){
return nums[i];
}
}
// 没有任何一个数是的单个,返回-1
return -1;
}
}
搜索有序数组中某元素插入位置
/*
* 搜索插入位置:
* 给定一个排序数组和一个目标值,在数组中查找目标值,返回其索引,若目标值不存在,返回它将要被按顺序插入的位置
* 假设数组无重复元素
* 示例:
* 输入:{1,3,5,6} ,5 输出:2
* 示例:
* 输入:{1,3,5,6} ,4 输出:2
*
* 思路:
* 1.数组有序
* 2.升序:如果目标值等于当前位,返回索引。如果大于上一位,且小于下一位,则为插入位置。都不满足则插入末尾
* 3.降序:如果目标值等于当前位,返回索引。如果小于上一位,且大于下一位,则为插入位置。都不满足则插入末尾
* */
public class InsertLocation {
public static void main(String[] args) {
// int[] nums = {1,3,5,6};
int[] nums = {8,6,5,3,1};
int number = 2;
int result = test(nums, number);
System.out.println(result);
}
public static int test(int[] nums, int number){
for (int i = 0; i < nums.length; i++) {
if (nums[0]<nums[1]){ // 升序
if (number<=nums[i]) return i;
}else if (nums[0]>nums[1]){ // 降序
if (number>=nums[i]) return i;
}
}
/*
* 如果执行到这里,说明上面return没有执行
* 说明number比数组中所有元素都大或都小
* 则应插入到最后
* */
return nums.length;
}
}