有一个n个整数的序列a1,a2,...,an。我们需要使用最小元素更改序列中的每个元素,这些元素放在它之前。如果没有这样的元素,我们需要用-1替换它。所有的变化都是同步和独立的。
的示例:
4 3 1 2 1 - > -1 4 3 3 2
5 4 3 2 1 - > -1 5 4 3 2
我的代码太慢,并且在序列太大时没有通过超时错误的测试。如何改善其表现?
这是我的代码:
public static void main(String[] args) throws InterruptedException {
ArrayList<Integer> list = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
int nElements = scanner.nextInt();
for (int i = 0; i < nElements; i++) {
list.add(scanner.nextInt());
}
ArrayList<Integer> newList = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
int tmp = -1;
for (int j = i - 1; j >= 0; j--) {
if (list.get(i) < list.get(j)) {
if (list.get(j) < tmp || tmp == -1) {
tmp = list.get(j);
}
}
}
newList.add(tmp);
}
list = newList;
}
更新:我忘了提到新值应该大于我们改变的元素。
答案 0 :(得分:1)
你的方法目前是O(n ^ 2),其中n是列表的大小,因为嵌套循环的构造方式。
您不需要内部循环:您已经在要添加到列表中的下一个值上有一个上限,即新列表中的上一个值。如果输入列表中相应的前一个元素较小,则下一个元素将仅较小。所以只需取两个数字中较小的一个。
List<Integer> newList = new ArrayList<>();
if (list.size() > 0) { newList.add(-1); }
if (list.size() > 1) { newList.add(list.get(0)); }
for (int i = 2; i < list.size(); i++) {
newList.add(Math.min(list.get(i-1), newList.get(i-1)));
}
答案 1 :(得分:0)
public static void main(String[] args) {
int[] values = {10,3,5,7,9,2,2,14,-5,7,9,3};
if ( values.length == 0 ) { return; }
int minValue = values[0];
int temp;
values[0] = -1;
for(int i=1; i<values.length; i++) {
temp = values[i];
values[i] = minValue;
if ( temp < minValue ) {
minValue = temp;
}
}
}
您可以记住当前项目之前的最小值,并在找到新项目时替换它。这个在O(N)中运行,不需要额外的内存。
答案 2 :(得分:0)
感谢cpp初学者的建议!树集和天花板方法使它工作:
public static void main(String[] args) throws InterruptedException {
ArrayList<Integer> list = new ArrayList<>();
Scanner scanner = new Scanner(System.in);
int nElements = scanner.nextInt();
for (int i = 0; i < nElements; i++) {
list.add(scanner.nextInt());
}
ArrayList<Integer> newList = new ArrayList<>();
TreeSet<Integer> set = new TreeSet<>();
for (Integer aList : list) {
Integer tmp = set.ceiling(aList + 1);
if (tmp == null) {
newList.add(-1);
} else {
newList.add(tmp);
}
set.add(aList);
}
list = newList;
}
谢谢大家!