每日一题 为了工作 2020 0412 第四十一题

/**
 *
 *  问题:在有序但含有空的数组中查找字符串
 *
 *  题目:给定一个字符串数组 strs[], 在 strs中有些位置为 null, 但在不为 null的位置上,
 *  其字符串是按照字典顺序由小到大依次出现的。再给定一个字符串str, 请返回 str在strs中
 *  出现的最左的位置。
 *
 *  举例:
 *      strs= [null,"a" ,null,"a" ,null,"b",null,"c"], str="a", 返回1。
 *      strs= [null,"a",null,"a",nu ll,"b" ,nul I, "c"], str=null,只要str为null, 就返回-1。
 *      strs= [null,"a",null,"a",null,"b" ,null,"c"], str="d", 返回-1。
 *
 *  解答:二分查找
 *  1. 假设在 strs[left .. right]上进行查找的过程, 全局整型变量res表示字符串str在strs中最左
 *  的位置。初始时,left=0, right =strs.length-1 , res=-1。
 *
 *  2. 令mid=(left+right)/2, 则 strs[mid]为 strs[left .. right]中间位置的字符串。
 *  3. 如果字符串strs[mid]与 str一样,说明找到了str, 令 res=mid 。但要找的是最左的位置,所以
 *  还要在左半区寻找,看有没有更左的 str出现,所以令 right=mid-1, 然后重复步骤2。
 *  4. 如果字符串strs[mid]与 str不一样, 并且 strs[mid]!=null,此时可以比较 strs[mid]和str,
 *  如果strs[mid]的子典顺序比str小,说明整个左半区不会出现str, 需要在右半区寻找,所以令left=mid+1, 然后重复步骤2。
 *  5. 如果字符串strs[mid]与str不一样, 并且 strs[mid]=null,此时从mid开始,从右到左遍历左半区
 *  (即strs[left .. mid])。如果整个左半区都为null, 那么继续用二分的方式在右半区上查找(即令left=mid+1),
 *  然后重复步骤2。如果整个左半区不都为null, 假设从右到左遍历strs[left .. mid]时, 发现第一个不为null
 *  的位置是 i,那么把 str和strs[i]进行比较。如果strs[i]字典顺序小于str, 同样说明整个左半区没有str, 令left=mid+1,
 *  然后重复步骤2。如果strs[i]字典顺序等于str, 说明找到str,令res=mid, 但要找的是最左的位置, 所以还要在strs[left .. i-1]
 *  上寻找, 看有没有更左的str出现, 所以令right=i-1, 然后重复步骤2。如果strs[i]字典顺序大于str,说明strs[i .. right]上
 *  都没有str, 需要在strs[left ..i-1]上,所以令right=i-1,然后重复步骤2。
 *
 * @author 雪瞳
 *
 */

  

public class GetIndex {
	public static int  getIndex(String strs[],String find){
		if(strs==null||strs.length==0||find==null){
			return -1;
		}
		int res =-1;
		int left = 0;
		int right = strs.length-1;

		int mid = 0;
		int i=0;

		while(left<=right){
			mid = (left+right)/2;
			if(strs[mid]!=null&&strs[mid]==find){
				res = mid;
				right = mid -1;
			}else if(strs[mid]!=null){
				if(strs[mid].compareTo(find)<0){
					left=mid+1;
				}else{
					right=mid-1;
				}
			}else{
				i = mid;
				//从左开始遍历
				while(strs[i]==null&&--i>=left){
				}
				if(i<left || strs[i].compareTo(find)<0){
					left=mid+1;
				}else{
					res=strs[i].equals(find)?i:res;
					right=i-1;
				}
			}

		}

		return res;	

	}
	public static void main(String[] args) {
		String str[] = {null,"a" ,null,"a" ,null,"b",null,"c"};

		int index = getIndex(str, "b");
		showCharArray(str);
		System.out.println(index);
	}

	public static void showCharArray(String array[]){
		for (String arr : array) {
			System.err.print(arr+"\t");
		}
		System.out.println();
	}
}

  

原文地址:https://www.cnblogs.com/walxt/p/12684786.html

时间: 2024-10-05 23:08:56

每日一题 为了工作 2020 0412 第四十一题的相关文章

每日一题 为了工作 2020 0303 第一题

Java 栈的相关操作 题目 : * 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的操作 * 要求 : * 1.pop.push.getMin操作的时间复杂度都是O(1). * 2.设计栈类型可以使用现成的栈结构. * 首先明确Java栈的相关操作函数 Stack stack = new Stack();//实例化栈对象 * 进栈操作 stack.push(“Object”);//返回的是入栈的内容 stack.add("Object");//返回的是true或

每日一题 为了工作 2020 0304 第二题

/** * 题目: * 编写一个类,用两个栈实现队列,支持队列的基本操作(add.poll.peek) * 分析: * 栈的特点是先进后出,而队列的特点是先进先出,我们可以用两个栈正好能把顺序 * 反过来实现类似队列的操作. * 具体实现是一个栈作为压入栈,在压入数据时只往这个栈中压入,记为stackPush, * 另一个栈只作为弹出栈,在弹出数据时只从这个栈弹出,记为stackPop. * 因为数据压入栈的时候,顺序是先进后出的,那么只要把stackPush的数据在压入 * stackPop中

每日一题 为了工作 2020 0305 第三题

/** * 问题: * 如何仅适用递归函数和栈操作逆序一个栈 * 一个栈依次压入1.2.3.4.5,那么从栈顶到栈底分别为5.4.3.2.1.将这个栈转置后, * 从栈顶到栈底为5.4.3.2.1,也就是实现了栈中元素的逆序,但是只可以通过递归函数来实现. * 分析: * 本题目考验查找操作和递归函数的设计,我们需要设计出两个递归函数. * 函数一:将栈stack中的栈底元素返回并移除 * getAndRemoveLastElement() * 函数二:逆序一个栈 * @author 雪瞳 *

每日一题 为了工作 2020 03019 第十七题

/** * 问题:反转双向链表 * * 要求: * 如果链表长度为 N,时间复杂度为O(N),额外的空间复杂度为O(1). * * @author 雪瞳 * */ public class Node<T>{ public T value; public Node next; public Node last; public Node(T data){ this.value =data; } } public class reverseList { private Node current =

每日一题 为了工作 2020 0317 第十五题

/** * 题目:删除链表的a/b处节点 * 给定链表的头节点 head.整数 a和 b, 实现删除位于 a/b处节点的函数. * * 例如: * 链表: 1->2->3->4->5, 假设a/b的值为r. * 如果r等于0, 不删除任何节点: * 如果r在区间(0, 1/5]上, 删除节点1; * 如果r在区间(1/5, 2/5]上, 删除节点2; * 如果r在区间(2/5, 3/5]上, 删除节点3; * 如果r在区间(3/5, 4/5]上, 删除节点4; * 如果r在区间(4

每日一题 为了工作 2020 0322 第二十题

/** * 问题: 判断一个链表是否为回文结构 * 给定一个链表的头节点head, 请判断该链表是否为回文结构. * * 例如: * 1->2->1, 返回 true. * 1->2->2-> 1, 返回 true . * 15->6-> 15, 返回 true. * 1->2->3, 返回 false. * * 解答: * 利用栈结构即可.从左到右遍历链表, 遍历的过程中把每个节点依次压入栈中. * 因为栈是先进后出的, 所以在遍历完成后, 从栈顶到

每日一题 为了工作 2020 0323 第二十一题

/** * 题目:将单向链表按某值划分成左边小.中间相等.右边大的形式 * * 要求: * 给定一个单向链表的头节点 head, 节点的值类型是整型, 再给定一个整数 privot.实现 *一个调整链表的函数, 将链表调整为左部分都是值小于privot的节点, 中间部分都是值等于privot *的节点, 右部分都是值大于privot的节点.除这个要求外, 对调整后的节点顺序没有更多的要求. *例如: 链表 9->0->4->5->1, privot=3.调整后链表可以是1->

每日一题 为了工作 2020 0325 第二十三题

/** * * 问题: 复制含有随机指针节点的链表 * * 分析: * 给定一个由Node节点类型组成的无环单链表的头节点head, 请实现一个函数完成这 * 个链表中所有结构的复制, 并返回复制的新链表的头节点.例如: 链表1->2->3->null, * 假设1的 rand指针指向3, 2的 rand指针指向 null, 3的 rand指针指向1.复制后的链 * 表应该也是这种结构, 比如, 1'->2'->3'->null, 1'的 rand指针指向3',2'的

每日一题 为了工作 2020 0405 第三十四题

/** * 问题: 向有序的环形单链表中插入新节点 * 一个环形单链表从头节点 head开始不降序, 同时由最后的节点指回头节点.给定这样 * 一个环形单链表的头节点 head和一个整数 num, 请生成节点值为 num的新节点,并插入到 * 这个环形链表中, 保证调整后的链表依然有序. * * 解题: * 1. 生成节点值为 num的新节点, 记为 node. * 2. 如果链表为空, 让 node自己组成环形链表, 然后直接返回node. * 3. 如果链表不为空, 令变量 pre=head