给定一个string数组str,其是由一个排过序的字符串数组插入了一些空字符串得到的,同时给定数组大小n和需要查找的string x,请用时间复杂度在log级别的算法返回该串的位置(位置从零开始)。
测试样例:
["a","b","","c","","d"],6,"c"
返回:3
import java.util.*;
/*
思路:这题目是二分法的变种,空格就左移一步,为防止越界,要先判断左右两边是不是为空格,先找到左右两边都不是空格再开始
但是不得不说,在空串>>子串的时候,复杂度还是O(n),不过如果不过滤掉空串直接动手做的话我只想得到这种方法
*/
public class Finder {
public int findString(String[] str, int n, String x) {
if(str==null||str.length==0) return -1;
int start =0;
int end=n-1;
while(str[start]==""){
start++;
if(start==n) return -1;
}//先找到左右两边都不是空格的端点
while(str[end]==""){
end--;
}
while(start<=end){
int mid =(start+end)/2;
while(str[mid]=="") mid--;
if(str[mid].compareTo(x)==0) return mid;
else if(str[mid].compareTo(x)>0){
end =mid-1;
while(str[end]=="") end--;
}
else {
start=mid+1;
while(str[start]=="") start++;
}
}
return -1;
}
}
运行时间:42ms
占用内存:9564k
每一次都过掉查找子串开头和结尾的空格,那么就可以保证头和尾部都没有空格。
那么剩下就是处理中间字符串的空格了。
处理完以后就是正常的二分查找。
看了一下跟大家的思路相比,自己想的这个算是比较简洁了,与诸位分享一波。
class Finder {
public:
int findString(vector<string> str, int n, string x) {
// write code here
int low = 0;
int high = str.size() - 1;
int mid = 0;
while(low <= high) {
while (str[low] == "" && low < high) low ++;
while (str[high] == "" && low < high) high --;
mid = (low + high) >> 1;
if (str[mid] == x) return mid;
while (str[mid] == "" && mid > low) mid--;
if (str[mid].compare(x) > 0) high = mid - 1;
else low = mid + 1;
}
return -1;
}
}; 我承认这是欺骗自己!!
ArrayList<String> arrayList = new ArrayList<>();
for(int i=0;i<str.length;i++){
arrayList.add(str[i]);
}
return arrayList.indexOf(x);
二分查找修改版,若遇到空串,先向左找第一个非空,找不到再向右。
平均O(longn),最差O(n)。运行时间1ms。
class Finder {
public:
int findString(vector<string> str, int n, string x)
{
int left = 0, right = n - 1;
while (str[left] == "") ++left;
while (str[right] == "") --right;
while (left < right)
{
if(str[left] == x) return left;
if(str[right] == x) return right;
int mid = (left + right) >> 1;
if (str[mid] == "")
{
int _left = mid - 1;
while (_left > left && str[_left] == "") --_left;
if (_left != left) mid = _left;
else
{
int _right = mid + 1;
while (_right < right && str[_right] == "") ++_right;
mid = _right;
}
}
if (x == str[mid]) return mid;
else if (x < str[mid]) right = mid - 1;
else left = mid + 1;
}
return left;
}
};
class Finder {
public:
int findString(vector<string> str, int n, string x) {
// write code here
/*方法1,顺序查找
if(n<=0) return -1;
for(int i=0;i<n;i++)
if(str[i]==x)
return i;
return -1;*/
//思路2,二分查找,空格单独处理
int start=0,end=n-1;
int mid;
while(start<=end)
{
mid=(start+end)/2;
//假如是空格,向左(或向右)找到第一个不为空的字符
if(str[mid]=="")
{
int index=mid;
while(index>=start && str[index]=="") --index;
if(index<start) start=mid+1;//一直到最左边都是空格,那么只能在右半边查找
else if(str[index]==x) return index;//左边第一个非空字符等于x,直接返回下标
else if(str[index]>x) end=mid-1;//左边第一个非空字符串大于x,那只能继续向左查找
else start=mid+1;//否则,向右查找
}
else
{
if(str[mid]==x) return mid;
else if(str[mid]>x) end=mid-1;
else start=mid+1;
}
}
return -1;
}
};
class Finder {
public:
int findString(vector<string> str, int n, string x) {
int l=0, r=str.size()-1, m=0;
while(l<=r){
while(str[l]=="" && l<r)
l++;
while(str[r]=="" && l<r)
r--;
m = (l+r)>>1;
if(str[m]==x)
return m;
while(str[m]=="" && l<r)
m--;
if(str[m]>x)
r = m-1;
else
l = m+1; }
return -1;
}
};
log复杂度,锁定 快排,堆排,归并,二分, 这里考虑快速排序:
# -*- coding:utf-8 -*-
class Finder:
def findString(self, s, n, x):
# write code here
left = []
right = []
for i in range(n):
if s[i] > x:
right.append(s[i])
elif s[i] < x:
left.append(s[i])
else:
return s.index(x)
if findString(left, len(left), x):
return findString(left, len(left), x)
return findString(right, len(right), x)
//java version. the most important thing is to deal with the void(mid="") import java.util.*; public class Finder { public int findString(String[] str, int n, String x) { if(str == null || n == 0 || x == null || x == ""){ return -1; } int start = 0, end = n-1; while(start <= end){ int mid = start + (end - start) / 2; int left = mid - 1; int right = mid + 1; if(str[mid].isEmpty()){ while(true){ if(left < start && end < right){ return -1; }else if(start < left && !str[left].isEmpty()){ mid = left; break; }else if(right < end && !str[right].isEmpty()){ mid = right; break; } left--; right++; } } if(str[mid].equals(x)){ return mid; }else if(str[mid].compareTo(x) < 0){ start = mid + 1; }else{ end = mid - 1; } } return -1; } }
public int findString(String[] str, int n, String x) {
for (int l = 0, r = n - 1; l <= r; ) {
int m = (l + r) / 2;
for (int i = m, j = m; ; ) { //过掉空字符串
if (i >= l) {
if (str[i].isEmpty())
i--;
else {
m = i;
break;
}
} else if (j <= r) {
if (str[j].isEmpty())
j++;
else {
m = j;
break;
}
} else
return -1;
}
if (str[m].compareTo(x) > 0)
r = m - 1;
else if (str[m].compareTo(x) < 0)
l = m + 1;
else
return m;
}
return -1;
}
class Finder { public: int half_find(vector<string> str,int start,int end,string x){ if(start > end) return -1; int mid = (start + end)/2; if(str[mid] == ""){ int res1 = half_find(str,start,mid-1,x); if(res1 != -1) return res1; int res2 = half_find(str,mid+1,end,x); if(res2!= -1) return res2; } else{ if(str[mid] == x) return mid; else if(str[mid] < x) return half_find(str,mid+1,end,x); else return half_find(str,start,mid-1,x); } return -1; } int findString(vector<string> str, int n, string x) { // write code here if(n == 0) return 0; return half_find(str,0,n-1,x); } };
# -*- coding:utf-8 -*-
class Finder:
def findString(self, s, n, x):
if n < 1:
return -1
i = 0
j = n - 1
while i <= j:
mid = (i + j)/2
# 移动mid位置
if s[mid] == '':
left = mid - 1
right = mid + 1
while True:
if left < i and right > j:
return -1
elif left >= i and s[left] != '':
mid = left
break
elif right <= j and s[right] != '':
mid = right
break
right += 1
left -= 1
if s[mid] == x:
return mid
elif s[mid] < x:
i = mid + 1
else:
j = mid - 1
return -1
public static int findString(String[] str, int n, String x) {
// write code here
if (str == null || 0 == n || x == null || x == "") {
return -1;
}
int start = 0;
int end = n - 1;
while (start < end) {
int mid = start + (end - start) >> 1;
int left = mid - 1;
int right = mid + 1;
if (str[mid].isEmpty()) {
while (true) {
if (start > left && end < right) {
return -1;
} else if (start < left && !str[left].isEmpty()) {
mid = left;
break;
} else if (end > right && !str[right].isEmpty()) {
mid = right;
break;
}
left--;
right++;
}
}
if (str[mid].equals(x)) {
return mid;
} else if (str[mid].compareTo(x) < 0) {
start = mid + 1;
} else {
end = mid - 1;
}
}
return -1;
}
大家可以看下这个题的代码,根据程序员面试金典上的递归代码改进而来的,我根据该题的测试用例进行测试一下,没出什么问题,但一直提交不成功。求大神解答
class Finder {
public:
int findString(vector<string> str, int n, string x) {
int size = str.size();
if(size == 0 || n <= 0){
return -1;
}//if
// 采用二分查找
int start = 0,end = size - 1;
int mid;
while(start <= end){
mid = (end - start) / 2 + start;
// 遇到空格特殊处理
if(str[mid] == ""){
int index = mid;
while(index >= start && str[index] == ""){
--index;
}//while
if(index < start){
start = mid + 1;
}//if
else if(str[index] == x){
return index;
}//else
else if(str[index] > x){
end = index - 1;
}//else
else{
start = mid + 1;
}//else
}//if
// 非空格
else{
// 找到目标
if(str[mid] == x){
return mid;
}//if
// 中间值比目标大只能在中间值的左边
else if(str[mid] > x){
end = mid - 1;
}//else
// 中间值比目标小只能在中间值的右边
else{
start = mid + 1;
}//else
}//else
}//while
return -1;
}
};
# -*- coding:utf-8 -*- class Finder: def findString(self, s, n, x): # write code here if n <= 0: return -1 low = 0 high = n - 1 while low <= high: while s[low] == '' and low < high: # 过滤左边空格 low += 1 while s[high] == '' and low < high: # 过滤右边空格 high -= 1 mid = (low + high) // 2 if s[mid] == x: return mid while s[mid] == '' and low < high: # 过滤中间空格 mid -= 1 if s[mid] > x: # 大于要查找的x,high往左移动,使得mid也往左移动 high -= 1 else: low += 1 # 小于要查找的x,high往右移动,使得mid也往右移动 return -1 # 没有找到x,返回-1
import java.util.*;
public class Finder {
public int findString(String[] str, int n, String x) {
if (n <=0) return -1;
// write code here
int l =0, r = str.length -1;
while (l<=r) {
int mid = l+ (r-l)/2;
if (str[mid].length() ==0) {
int index = mid;
while ( index>=l && str[index].length()==0){
--index;
}
if (index < l) {
//[l,mid ]一直都是空格,不用找了
l = mid +1;
}
else if(str[index] ==x) {
return index;
}else if(str[index].compareTo(x) >0) {
r = mid -1;
}else{
l = mid +1;
}
}else {
if(str[mid].equals(x)) {
return mid;
}else if (str[mid].compareTo(x) >0) {
//amid > x
r = mid -1;
}else{
l = mid +1;
}
}
}
return -9999;
}
} class Finder {
public:
int findString(vector<string> str, int n, string x) {
//使用折半查找法
int location;
if(n<=0)
{
return location;
}
int mid = n/2;
int front = 0;
int back = n;
while(front < back)
{
mid = (front + back) / 2;
if(str[mid] != " ")
{
if(x > str[mid] )
{
front = mid + 1;
}
else if( x < str[mid])
{
back = mid - 1;
}
else
{
return mid;
}
}
else if(str[mid] == " ")
{
if(x > str[mid+1])
{
front = mid + 2;
}
else if(x < str[mid-1])
{
back = mid - 2;
}
else{
return mid;
}
}
}
}
}; class Finder {
public:
int findString(vector<string> str, int n, string x) {
// write code here
int left = 0;
int right = n-1;
while(left <= right){
int mid = left+(right-left)/2;
if(str[mid] == x){
return mid;
}
// 这种情况是新增加的
else if(str[mid] == ""){
if(mid >0 && str[mid-1] < x){
left = mid+1;
}else if(mid >0 && str[mid-1] > x){
right = mid-1;
}
}
else if(str[mid] > x){
right = mid-1;
}
else if(str[mid] < x){
left = mid+1;
}
}
return left;
}
};