java - 我们如何修复这个算法来找到最小的数字
问题描述
我们想找到从给定长的数字创建的最小数字。
我们正在执行以下编程任务:https ://www.codewars.com/kata/573992c724fc289553000e95
您有一个由数字组成的正数 n。您最多可以做一个操作:选择数字中的一个数字的索引,在该索引处删除该数字,然后将其插入到另一个数字或数字的同一位置,以找到您可以获得的最小数字。
#Task:根据语言返回一个数组或一个元组或一个字符串(参见“示例测试”)
1) the smallest number you got
2) the index i of the digit d you took, i as small as possible
3) the index j (as small as possible) where you insert this digit d to have the smallest number.
例子:
smallest(261235) --> [126235, 2, 0] or (126235, 2, 0) or "126235, 2, 0"
126235 是通过在索引 2 处取 1 并将其放在索引 0 处得到的最小数字
smallest(209917) --> [29917, 0, 1] or ...
[29917, 1, 0] could be a solution too but index `i` in [29917, 1, 0] is greater than
index `i` in [29917, 0, 1].
29917 是通过在索引 0 处取 2 并将其放在索引 1 中得到的最小数字,它给出了 029917,即数字 29917。
smallest(1000000) --> [1, 0, 6] or ...
-> 我们写过:
public class ToSmallest {
public static long[] smallest /**/ (long n) {
System.out.println("\n\nn: "+n);
StringBuilder input = new StringBuilder(String.valueOf(n));
long min = Long.MAX_VALUE;
int minIndex = -1;
//We find the minimum and its index
for(int i=input.length()-1; n>0; i--){
long digit = n%10;
if(min!=Math.min(min,digit)){
minIndex='\0'+i;
}
min = Math.min(min, digit);
n /= 10;
}
System.out.println("min: "+min);
System.out.println("minIndex: "+minIndex);
//We put the minimum as first digit
input = input.deleteCharAt(minIndex);
System.out.println("input: "+input);
input = input.insert(0,min);
System.out.println("input: "+input);
return new long[]{Long.parseLong(input.toString()),minIndex,0};
}
}
我们认为这是不完整的,因为我们假设在所有情况下我们都可以通过以下方式创建最小值:
1) Find the min digit
2) Remove it from where it was
3) Insert it at start
但是,作为单元测试:
import static org.junit.Assert.*;
import java.util.Arrays;
import org.junit.Test;
public class ToSmallestTest {
private static void testing(long n, String res) {
assertEquals(res,
Arrays.toString(ToSmallest.smallest(n)));
}
@Test
public void test() {
System.out.println("Basic Tests smallest");
testing(261235, "[126235, 2, 0]");
testing(209917, "[29917, 0, 1]");
testing(285365, "[238565, 3, 1]");
testing(269045, "[26945, 3, 0]");
testing(296837, "[239687, 4, 1]");
}
}
-> 代码在第二次测试中失败。
我们如何改进算法?
编辑:阅读 Norbert Dopjera 的回答后,我们尝试过:
public class ToSmallest {
public static long[] smallest (long n) {
System.out.println("\n\nn: "+n);
StringBuilder input = new StringBuilder(String.valueOf(n));
long min = Long.MAX_VALUE;
int minIndex = -1;
int numberMinsFound = -1; //
//We find the minimum and its index
while(numberMinsFound == minIndex){ //
for(int i=input.length()-1; n>0; i--){
long digit = n%10;
if(min!=Math.min(min,digit)){
minIndex='\0'+i;
}
min = Math.min(min, digit);
n /= 10;
numberMinsFound++; //
}
}
System.out.println("min: "+min);
System.out.println("minIndex: "+minIndex);
//We put the minimum as first digit
input = input.deleteCharAt(minIndex);
System.out.println("input: "+input);
input = input.insert(0,min);
System.out.println("input: "+input);
return new long[]{Long.parseLong(input.toString()),minIndex,0};
}
}
然而,第二次测试仍然是错误的:
n: 209917
min: 0
minIndex: 1
input: 29917
input: 029917
expected:<[29917, [0, 1]]> but was:<[29917, [1, 0]]>
解决方案
第二个测试实际上失败了,因为您正在使用字符串。您的算法会发现最小数字 0 将其放在前面,因此它会创建以下字符串:“029917”,但由于您正在针对值为“29917”的字符串进行测试,因此测试将失败。您获得的数字是您可以从提供的数字中获得的最低数字,并且您可以进行操作。因此,您的方法在这里是有效的。
编辑:您实际上可以通过以下方式改进您的代码。如果最小值仅在最低索引处找到,即最小值已经是第一个数字,那么您应该搜索第二个最小值。如果第二个最小值再次位于第二个位置,则已经找到第三个最小值等。直到找到未放置在其最低可能索引处的第 N 个最小值并将其放置在那里。这是第三次测试实际测试的内容。您会发现数字 2 是最小数字,但由于它已经在第一个位置,您应该继续找到第二个最小值,数字 3,并将其放置在您找到的上一个最小值之后并且不必移动。
推荐阅读
- javascript - 如何在反应中清除传单地图,以便绘制新数据?
- c - 计算和打印n个数的gcd和lcm的ac程序
- python - 检测YOLO检测到的物体的角度
- python - 取下一个组值并将其分配给当前组元素
- c# - 如何在 blazor 页面上使用用户管理器?
- java - Maven clean 导致 spring 应用运行失败
- javascript - 无法在 Wordpress 中折叠响应式菜单
- intellij-idea - 如何在 IntelliJ 中将项目作为选项卡打开
- r - 在 RStudio 服务器中安装 magick 包
- flutter - Flutter Firestore 设置数据并获取文档 ID