剑指offer第二版——面试题53(java)

面试题:在排序数组中查找数字

题目一:求数字在排序数组中出现的次数

题目二:求0~n-1中缺失的数字

题目三:求数组中数值=下标的元素

具体题目:

题目一中,统计一个数字在排序数组中出现的次数

题目二中,长度n-1的递增排序数组中,所有数字都是唯一的,且每个数字都在0~n-1之内,在0~n-1内的n个数字有且只有一个数字不在数组中,找出该数

题目三中,单调递增数组,数组中每个元素都是整数并且是唯一的,找出数组中任意一个数值等于其下标的元素

思路:

题目一:查找数字x的次数

如果从头开始查找,从查找到x开始计数,则时间复杂度为O(n)

如果使用二分查找算法,找到数组中的一个x,但是查找到的位置可能两边都还有x,所以需要从查找到的位置分别往前遍历和往后遍历,这个算法的时间复杂度也是O(n)

因此,可以使用二分查找算法,分别查找数组中x的开头位置和结束位置:

1. 用二分查找法查找开头位置 start

    如果所查找的子数组(数组)的中间位置为a>x,则将查找的子数组设置为该位置左边的部分;如果所查找的子数组(数组)的中间位置的a

    如果所查找啊的子数组(数组)的中间位置a=x,则检查当前位置的前面一个数,看其是否为x,如果a前面的数不为x,则a的位置为x的开头位置;如果a的前一个数也为x,则将子数组设置为【上一轮子数组开头到a前面位置】

2. 用二分查找法查找末尾位置 end

    【当a!=x时 与1.相同】如果所查找的子数组(数组)的中间位置为a>x,则将查找的子数组设置为该位置左边的部分;如果所查找的子数组(数组)的中间位置的a

如果位置上的a>下标如果所查找啊的子数组(数组)的中间位置a=x,则检查当前位置的后面一个数,看其是否为x,如果a后面的数不为x,则a的位置为x的结尾位置;如果a的后一个数也为x,则将子数组设置为【a后面一位到上一轮子数组结尾】

3. 出现次数为end - start +1

 

题目二:

因为数组长度为n-1,且从0~n-1递增,所以缺失的数之前的其他数的下标=数,缺失数之后的数是下标<数

方法与题目一相似,用二分法进行查找

    如果当前位置的数a=下标,则说明要查找的缺失数x在a的右边;

    如果当前位置的数a>下标,则需要判断当前位置是否为缺失数的位置——如果当前位置的前一位满足下标=数,则当前位置为缺失的位置;否则,缺失的位置在a左边,继续查找。

 

题目三:

使用二分查找法进行查找时:

    如果位置上的a=下标,为查找的位置

    如果位置上的a>下标——如果a左边的数不满足a=下标,则需要查找的数在a的左边(因为右边的数都大于a,所以肯定都是数>下标);

    如果位置上的a<下标——如果a右边的数不满足a=下标,则需要查找的数在a的右边(因为a左边的数都小于a,所以肯定都是数<下标),循环直到找到符合条件的数(位置)

 

代码:

题目一:

public class Q53_1 {
	public static void main(String[] args) {
		int[] list = new int[] {1,1,2,3,3,3,3,3,4,5};
		System.out.println(numOfnum(list,1));
	}
	
	public static int numOfnum(int[] list,int x) {
		int start = startOflist(list,x);
		int end = 0;
		if(start!=-1) {
			 end = endOflist(list,x);
			 return  end-start+1;	
		}	
		System.out.printf("there is no %d\n",x);
		return -1;
	}

	public static int startOflist(int[] list,int x) {
		int end = list.length-1;
		int start = 0;
		while(end>=start) {
			int i = (end + start)/2;
			if(list[i]>x) {
				end = i-1;
			}
			
			if(list[i]=start) {
			int i = (end + start)/2;
			if(list[i]>x) {
				end = i-1;
			}
			
			if(list[i]

题目二:

public class Q53_2 {
	public static void main(String[] args) {
		int[] list = new int[] {0,1,2,3,5,6,7,8,9};
		int loc = lostNum(list);
		if(loc!=-1)
			System.out.printf("lost:%d\n",loc);
	}
	
	public static int lostNum(int[] list) {
		int end = list.length-1;
		int start = 0;
		while(end>=start) {
			int i = (start + end) /2;
			if(list[i]==i) {
				start = i+1;
			}
			
			if(list[i]>i) {
				if(i==0) {
					return i;
				}else {
					if(list[i-1]==i-1) {
						return i;
					}else {
						end = i-1;
					}
				}
			}
		}
		System.out.println("no number lost!");
		return -1;
	}
}

 

题目三:

public class Q53_3 {
	public static void main(String[] args) {
		int[] list = new int[] {-3,-1,1,2,5};
		int loc = equalLoc(list);
		if(loc!=-1) {
			System.out.printf("equal loc:%d", loc);
		}
	}
	
	
	public static int equalLoc(int[] list) {
		int end = list.length-1;
		int start = 0;
		while(end>=start) {
			int i = (start + end) /2;
			if(list[i]==i) {
				return i;
			}

			if(list[i]i) {
				if(i==0) {
					return -1;
				}else {
					if(list[i-1]==i-1) {
						return i-1;
					}else {
						end = i-1;
					}
				}
			}
		}
		System.out.println("no equal loc!");
		return -1;
	}
}

 

你可能感兴趣的:(剑指offer第二版)