Java 在另一个较大的数组中查找数组
我最近被要求为一份工作编写3个测试程序。它们将使用核心JavaAPI和我选择的任何测试框架编写。在适当的情况下,应实施单元测试 虽然我没有收到任何反馈,但我想他们不喜欢我的解决方案(否则我会从他们那里听到),所以我决定在这里展示我的程序,并询问这个实现是否被认为是好的,如果不是,为什么 为了避免混淆,我现在只问第一个问题 实现一个查找 在另一个较大的数组中。信息技术 应接受两个数组作为参数 它将返回 第一个数组,其中第二个数组 第一次完全发生。如, findArray([2,3,7,1,20],[7,1])应该 返回2 我没有试图找到任何现有的解决方案,而是想自己去做 可能的原因: 1.应该是静态的。 2.应该使用行注释而不是块注释。 3.没有先检查空值(我知道,只是发现太迟了)。 4. ? 更新:Java 在另一个较大的数组中查找数组,java,arrays,Java,Arrays,我最近被要求为一份工作编写3个测试程序。它们将使用核心JavaAPI和我选择的任何测试框架编写。在适当的情况下,应实施单元测试 虽然我没有收到任何反馈,但我想他们不喜欢我的解决方案(否则我会从他们那里听到),所以我决定在这里展示我的程序,并询问这个实现是否被认为是好的,如果不是,为什么 为了避免混淆,我现在只问第一个问题 实现一个查找 在另一个较大的数组中。信息技术 应接受两个数组作为参数 它将返回 第一个数组,其中第二个数组 第一次完全发生。如, findArray([2,3,7,1,20],
提出了很多理由,我很难选择一个答案,因为很多答案都有很好的解决方案。正如@aditerich所提到的,我倾向于相信他们希望我展示核心API的知识(他们甚至要求我写一个函数,而不是写一个算法) 我认为获得这份工作的最佳方式是提供尽可能多的解决方案,包括: 1.使用Collections.indexofpublist()方法实现,以显示我了解核心集合API。 2.使用蛮力方法实现,但提供更优雅的解决方案。 3.使用搜索算法实现,例如Boyer Moore。 4.使用System.arraycopy()和Arrays.equal()的组合实现。然而,这并不是性能方面的最佳解决方案,它将显示我对标准数组例程的了解 谢谢大家的回答
更新结束。 以下是我写的: 实际计划:
package com.example.common.utils;
/**
* This class contains functions for array manipulations.
*
* @author Roman
*
*/
public class ArrayUtils {
/**
* Finds a sub array in a large array
*
* @param largeArray
* @param subArray
* @return index of sub array
*/
public int findArray(int[] largeArray, int[] subArray) {
/* If any of the arrays is empty then not found */
if (largeArray.length == 0 || subArray.length == 0) {
return -1;
}
/* If subarray is larger than large array then not found */
if (subArray.length > largeArray.length) {
return -1;
}
for (int i = 0; i < largeArray.length; i++) {
/* Check if the next element of large array is the same as the first element of subarray */
if (largeArray[i] == subArray[0]) {
boolean subArrayFound = true;
for (int j = 0; j < subArray.length; j++) {
/* If outside of large array or elements not equal then leave the loop */
if (largeArray.length <= i+j || subArray[j] != largeArray[i+j]) {
subArrayFound = false;
break;
}
}
/* Sub array found - return its index */
if (subArrayFound) {
return i;
}
}
}
/* Return default value */
return -1;
}
}
我建议作出以下改善:
- 将函数设为静态,这样可以避免创建实例
- 外环条件可能是
i好的,从我的头顶开始:
public int findArray(int[] largeArray, int[] subArray) { int subArrayLength = subArray.length; if (subArrayLength == 0) { return -1; } int limit = largeArray.length - subArrayLength; int i=0; for (int i = 0; i <= limit; i++) { boolean subArrayFound = true; for (int j = 0; j < subArrayLength; j++) { if (subArray[j] != largeArray[i+j]) { subArrayFound = false; break; } /* Sub array found - return its index */ if (subArrayFound) { return i; } } /* Return default value */ return -1; }
- 是的,应该是静态的
- 一家抱怨这一点的公司不值得为之工作
- 是的,但是你会怎么做?返回?或者抛出异常?它将以现有的方式抛出异常
- 我认为主要的问题是你的代码不是很优雅。内部循环中的检查太多。过多的冗余检查
只是生的,从我的头顶上:public int findArray(int[] largeArray, int[] subArray) { int subArrayLength = subArray.length; if (subArrayLength == 0) { return -1; } int limit = largeArray.length - subArrayLength; int i=0; for (int i = 0; i <= limit; i++) { boolean subArrayFound = true; for (int j = 0; j < subArrayLength; j++) { if (subArray[j] != largeArray[i+j]) { subArrayFound = false; break; } /* Sub array found - return its index */ if (subArrayFound) { return i; } } /* Return default value */ return -1; }
public int findArray(int[]大数组,int[]子数组){ int subArray length=subArray.length; 如果(子阵列长度==0){ 返回-1; } int limit=largeArray.length-子阵列长度; int i=0; 对于(int i=0;i
int findSubArr(int[]arr,int[]subar) { int lim=阵列长度-子阵列长度;
对于(int i=0;i在较大的整数数组中查找整数数组,可以使用与在较大的字符串中查找子字符串相同的算法。对于这一点,有许多已知的算法(请参阅)。尤其是Boyer-Moore字符串搜索对于大型数组非常有效。您尝试实现的算法效率不高(Wikipedia称之为“naive”实现) 关于您的问题:- 是的,这样的方法应该是静态的
- 别在意,这是品味的问题
- 可以包括null检查,或者您应该在JavaDoc中声明不允许使用null值,或者JavaDoc应该声明,当任一参数为null时,将抛出NullPointerException
“仅使用核心Java API”的要求也可能意味着他们想看看您是否会重新发明轮子。因此,除了您自己的实现之外,您可以提供单线解决方案,只是为了安全:public static int findArray(Integer[] array, Integer[] subArray) { return Collections.indexOfSubList(Arrays.asList(array), Arrays.asList(subArray)); }
指出给出的示例包含无效的数组文本可能是一个好主意,也可能不是一个好主意。之前发布的一些经过优化的代码:public int findArray(byte[] largeArray, byte[] subArray) { if (subArray.length == 0) { return -1; } int limit = largeArray.length - subArray.length; next: for (int i = 0; i <= limit; i++) { for (int j = 0; j < subArray.length; j++) { if (subArray[j] != largeArray[i+j]) { continue next; } } /* Sub array found - return its index */ return i; } /* Return default value */ return -1; }
public int findArray(字节[]大数组,字节[]子数组){ if(subArray.length==0){ 返回-1; } int limit=largeArray.length-subArray.length; 下一步: 对于(int i=0;i,这里是字符串的#indexOf:
/** * Code shared by String and StringBuffer to do searches. The * source is the character array being searched, and the target * is the string being searched for. * * @param source the characters being searched. * @param sourceOffset offset of the source string. * @param sourceCount count of the source string. * @param target the characters being searched for. * @param targetOffset offset of the target string. * @param targetCount count of the target string. * @param fromIndex the index to begin searching from. */ static int indexOf(char[] source, int sourceOffset, int sourceCount, char[] target, int targetOffset, int targetCount, int fromIndex) { if (fromIndex >= sourceCount) { return (targetCount == 0 ? sourceCount : -1); } if (fromIndex < 0) { fromIndex = 0; } if (targetCount == 0) { return fromIndex; } char first = target[targetOffset]; int max = sourceOffset + (sourceCount - targetCount); for (int i = sourceOffset + fromIndex; i <= max; i++) { /* Look for first character. */ if (source[i] != first) { while (++i <= max && source[i] != first); } /* Found first character, now look at the rest of v2 */ if (i <= max) { int j = i + 1; int end = j + targetCount - 1; for (int k = targetOffset + 1; j < end && source[j] == target[k]; j++, k++); if (j == end) { /* Found whole string. */ return i - sourceOffset; } } } return -1; }
/** *由String和StringBuffer共享以执行搜索的代码 *源是正在搜索的字符数组,目标是 *正在搜索的字符串。 * *@param source正在搜索的字符。 *@param sourceOffset源字符串的偏移量。 *@param sourceCount源字符串的计数。 *@param目标是要搜索的字符。 *@param targetOffset目标字符串的偏移量。 *@param targetCount目标字符串的计数。 *@param fromIndex开始搜索的索引。 */ 静态int indexOf(char[]source,int sourceOffset,int sourceCount, char[]目标,int targetOffset,int targetCount, int fromIndex){ if(fromIndex>=sourceCount){ 返回(targetCount==0?sourceCount:-1); } 如果(从索引<0){ fromIndex=0; } 如果(targetCount==0){ 从索引返回; } char first=目标[targetOffset]; int max=sourceOffset+(sourceCount-targetCount);
对于(int i=sourceOffset+fromIndex;i以下是一种使用KMP模式匹配算法的方法。此解决方案采用
。其中O(n+m)
和n=大数组长度
。有关详细信息,请检查: 蛮力取m=子数组长度
。我刚刚检查了O(n*m)
方法也是集合。indexofpublist
O(n*m)
公共静态int子字符串索引(int[]大数组,int[]子数组){ 如果(largeArray.length==0 | | s
public static int findArray(Integer[] array, Integer[] subArray) { return Collections.indexOfSubList(Arrays.asList(array), Arrays.asList(subArray)); }
public int findArray(byte[] largeArray, byte[] subArray) { if (subArray.length == 0) { return -1; } int limit = largeArray.length - subArray.length; next: for (int i = 0; i <= limit; i++) { for (int j = 0; j < subArray.length; j++) { if (subArray[j] != largeArray[i+j]) { continue next; } } /* Sub array found - return its index */ return i; } /* Return default value */ return -1; }
/** * Code shared by String and StringBuffer to do searches. The * source is the character array being searched, and the target * is the string being searched for. * * @param source the characters being searched. * @param sourceOffset offset of the source string. * @param sourceCount count of the source string. * @param target the characters being searched for. * @param targetOffset offset of the target string. * @param targetCount count of the target string. * @param fromIndex the index to begin searching from. */ static int indexOf(char[] source, int sourceOffset, int sourceCount, char[] target, int targetOffset, int targetCount, int fromIndex) { if (fromIndex >= sourceCount) { return (targetCount == 0 ? sourceCount : -1); } if (fromIndex < 0) { fromIndex = 0; } if (targetCount == 0) { return fromIndex; } char first = target[targetOffset]; int max = sourceOffset + (sourceCount - targetCount); for (int i = sourceOffset + fromIndex; i <= max; i++) { /* Look for first character. */ if (source[i] != first) { while (++i <= max && source[i] != first); } /* Found first character, now look at the rest of v2 */ if (i <= max) { int j = i + 1; int end = j + targetCount - 1; for (int k = targetOffset + 1; j < end && source[j] == target[k]; j++, k++); if (j == end) { /* Found whole string. */ return i - sourceOffset; } } } return -1; }
public static int subStringIndex(int[] largeArray, int[] subArray) { if (largeArray.length == 0 || subArray.length == 0){ throw new IllegalArgumentException(); } if (subArray.length > largeArray.length){ throw new IllegalArgumentException(); } int[] prefixArr = getPrefixArr(subArray); int indexToReturn = -1; for (int m = 0, s = 0; m < largeArray.length; m++) { if (subArray[s] == largeArray[m]) { s++; } else { if (s != 0) { s = prefixArr[s - 1]; m--; } } if (s == subArray.length) { indexToReturn = m - subArray.length + 1; break; } } return indexToReturn; } private static int[] getPrefixArr(int[] subArray) { int[] prefixArr = new int[subArray.length]; prefixArr[0] = 0; for (int i = 1, j = 0; i < prefixArr.length; i++) { while (subArray[i] != subArray[j]) { if (j == 0) { break; } j = prefixArr[j - 1]; } if (subArray[i] == subArray[j]) { prefixArr[i] = j + 1; j++; } else { prefixArr[i] = j; } } return prefixArr; }
Clean and improved code public static int findArrayIndex(int[] subArray, int[] parentArray) { if(subArray.length==0){ return -1; } int sL = subArray.length; int l = parentArray.length - subArray.length; int k = 0; for (int i = 0; i < l; i++) { if (parentArray[i] == subArray[k]) { for (int j = 0; j < subArray.length; j++) { if (parentArray[i + j] == subArray[j]) { sL--; if (sL == 0) { return i; } } } } } return -1; }
public final class ArrayUtils { // main method public static int indexOf(int[] haystack, int[] needle) { return indexOf(haystack, needle, 0); } // helper methods private static int indexOf(int[] haystack, int[] needle, int fromIndex) { for (int i = fromIndex; i < haystack.length - needle.length; i++) { if (containsAt(haystack, needle, i)) { return i; } } return -1; } private static boolean containsAt(int[] haystack, int[] needle, int offset) { for (int i = 0; i < needle.length; i++) { if (haystack[i + offset] != needle[i]) { return false; } } return true; } // prevent initialization private ArrayUtils() {} }
byte[] arr1 = {1, 2, 3, 4, 5, 6, 7, 7, 8, 9, 1, 3, 4, 56, 6, 7}; byte[] arr2 = {9, 1, 3}; boolean i = IsContainsSubArray(arr1, arr2);
public static boolean IsContainsSubArray(byte[] Large_Array, byte[] Sub_Array){ try { int Large_Array_size, Sub_Array_size, k = 0; Large_Array_size = Large_Array.length; Sub_Array_size = Sub_Array.length; if (Sub_Array_size > Large_Array_size) { return false; } for (int i = 0; i < Large_Array_size; i++) { if (Large_Array[i] == Sub_Array[k]) { k++; } else { k = 0; } if (k == Sub_Array_size) { return true; } } } catch (Exception e) { } return false; }
import javax.annotation.Nullable; /** * Ensures that an object reference passed as a parameter to the calling method is not null. * * @param reference an object reference * @param errorMessage the exception message to use if the check fails; will be converted to a * string using {@link String#valueOf(Object)} * @return the non-null reference that was validated * @throws NullPointerException if {@code reference} is null */ public static <T> T checkNotNull(T reference, @Nullable Object errorMessage) { if (reference == null) { throw new NullPointerException(String.valueOf(errorMessage)); } return reference; } /** * Returns the start position of the first occurrence of the specified {@code * target} within {@code array}, or {@code -1} if there is no such occurrence. * * <p>More formally, returns the lowest index {@code i} such that {@code * java.util.Arrays.copyOfRange(array, i, i + target.length)} contains exactly * the same elements as {@code target}. * * @param array the array to search for the sequence {@code target} * @param target the array to search for as a sub-sequence of {@code array} */ public static int indexOf(int[] array, int[] target) { checkNotNull(array, "array"); checkNotNull(target, "target"); if (target.length == 0) { return 0; } outer: for (int i = 0; i < array.length - target.length + 1; i++) { for (int j = 0; j < target.length; j++) { if (array[i + j] != target[j]) { continue outer; } } return i; } return -1; }
public static void findArray(int[] array, int[] subArray) { if (subArray.length > array.length) { return; } if (array == null || subArray == null) { return; } if (array.length == 0 || subArray.length == 0) { return; } //Solution 1 List<Integer> master = Arrays.stream(array).boxed().collect(Collectors.toList()); List<Integer> pattern = IntStream.of(subArray).boxed().collect(Collectors.toList()); System.out.println(Collections.indexOfSubList(master, pattern)); //Solution2 for (int i = 0; i <= array.length - subArray.length; i++) { String s = Arrays.toString(Arrays.copyOfRange(array, i, i + subArray.length)); if (s.equals(Arrays.toString(subArray))) { System.out.println("Found at:" + i); return; } } System.out.println("Not found."); }
String[] smallArray = {"1","2","3"}; final String[] bigArray = {"0","1","2","3","4"}; boolean result = Arrays.stream(smallArray).allMatch(s -> Arrays.stream(bigArray).anyMatch(b -> b.equals(s)));