编写函数:
class Solution{
public int solution(int[] A);
}
,给定一个由N个整数组成的数组A,返回最小的正整数(大于0) 在A中不会发生。
例如,给定A = [1,3,6,4,1,2],该函数应返回5。
给定A = [1,2,3],该函数应返回4。
给出A = [-1,-3],该函数应返回1。
为以下假设写出高效的算法。
N是[1..100,000]范围内的整数;
数组A的每个元素都是[-1,000,000..1,000,000]范围内的整数。
我用Java编写了以下算法:
public class TestCodility {
public static void main(String args[]){
int a[] = {1,3,6,4,1,2};
//int a[] = {1,2,3};
//int b[] = {-1,-3};
int element = 0;
//checks if the array "a" was traversed until the last position
int countArrayLenght = 0;
loopExtern:
for(int i = 0; i < 1_000_000; i++){
element = i + 1;
countArrayLenght = 0;
loopIntern:
for(int j = 0; j < a.length; j++){
if(element == a[j]){
break loopIntern;
}
countArrayLenght++;
}
if(countArrayLenght == a.length && element > 0){
System.out.println("Smallest possible " + element);
break loopExtern;
}
}
}
}
它可以完成工作,但是我很确定它效率不高。所以我的问题是,如何改进该算法以使其变得高效?
答案 0 :(得分:0)
您应该了解Big O和运行时的复杂性。 它是一种通用结构,可以更好地理解代码效率。
访问此网站,它以Big O的形式显示了运行时复杂性的图形,可帮助您搜索更有效的编程。
但是,长话短说... 任意程序消耗的操作和内存最少,是实现您打算与代码一起完成工作的最有效方法。
您可以通过减少算法中的冗余并摆脱实现您要执行的操作不需要执行的任何操作来提高效率
答案 1 :(得分:0)
重点是对数组进行排序,然后对其进行迭代。使用排序数组,您可以简单地跳过所有负数,然后找到所需的最小可能元素。
以下是您任务的更通用的解决方案:
import java.util.Arrays;
public class Main {
public static int solution(int[] A) {
int result = 1;
Arrays.sort(A);
for(int a: A) {
if(a > 0) {
if(result == a) {
result++;
} else if (result < a){
return result;
}
}
}
return result;
}
public static void main(String args[]){
int a[] = {1,3,6,4,1,2};
int b[] = {1,2,3};
int c[] = {-1,-3};
System.out.println("a) Smallest possible " + solution(a)); //prints 5
System.out.println("b) Smallest possible " + solution(b)); //prints 4
System.out.println("c) Smallest possible " + solution(c)); //prints 1
}
}
该算法的复杂度应为O(n * log(n))
答案 2 :(得分:0)
主要思想与丹尼斯相同。
首先进行排序,然后使用java8功能进行处理。
很少有可能增加计时的方法。(不是很确定java 8处理它们的效率如何:filter,distinct甚至是take-while ...在最坏的情况下,这里有3个完整循环的类似内容。另外一个循环用于将数组转换为流)。总体而言,您应该获得相同的运行时复杂度。
优点之一可能是冗长,但与Denis解决方案相比,还需要一些其他知识。
import java.util.function.Supplier;
import java.util.stream.IntStream;
public class AMin
{
public static void main(String args[])
{
int a[] = {-2,-3,1,2,3,-7,5,6};
int[] i = {1} ;
// get next integer starting from 1
Supplier<Integer> supplier = () -> i[0]++;
//1. transform array into specialized int-stream
//2. keep only positive numbers : filter
//3. keep no duplicates : distinct
//4. sort by natural order (ascending)
//5. get the maximum stream based on criteria(predicate) : longest consecutive numbers starting from 1
//6. get the number of elements from the longest "sub-stream" : count
long count = IntStream.of(a).filter(t->t>0).distinct().sorted().takeWhile(t->t== supplier.get()).count();
count = (count==0) ? 1 : ++count;
//print 4
System.out.println(count);
}
}
答案 3 :(得分:0)
有许多具有O(n)空间复杂度和O(n)类型复杂度的解决方案。您可以将数组转换为;
就目前而言,看起来像@Ricola所述的更有效的算法。具有O(n)时间复杂度和O(1)空间复杂度的Java解决方案:
static void swap(final int arr[], final int i,final int j){
final int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
static boolean isIndexInSafeArea(final int arr[], final int i){
return arr[i] > 0 && arr[i] - 1 < arr.length && arr[i] != i + 1 ;
}
static int solution(final int arr[]){
for (int i = 0; i < arr.length; i++) {
while (isIndexInSafeArea(arr,i) && arr[i] != arr[arr[i] - 1]) {
swap(arr, i, arr[i] - 1);
}
}
for (int i = 0; i < arr.length; i++) {
if (arr[i] != i + 1) {
return i+1;
}
}
return arr.length + 1;
}