给定一个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; } };