LCR 164. 破解闯关密码
破解闯关密码
闯关游戏需要破解一组密码,闯关组给出的有关密码的线索是:
- 一个拥有密码所有元素的非负整数数组 password
- 密码是 password 中所有元素拼接后得到的最小的一个数
请编写一个程序返回这个密码。
示例 1:
输入: password = [15, 8, 7]
输出: "1578"
示例 2:
输入: password = [0, 3, 30, 34, 5, 9]
输出: "03033459"
思路:
本题传达出的一个信号是:碰见这种感觉到有点没搞清楚怎么操作的题目,试着先手推一下示例
这个问题本质就是一个排序问题,怎么看出来的呢?
比如原数组是3、30、34、1、9
3和30的位置应该互换,因为 330 大于 303 ----> 30、3、34、1、9
3和34的位置不需要换,因为 334 小于 343 ----> 30、3、34、1、9
34和1的位置需要互换,因为 341 大于 134 ----> 30、3、1、34、9
34和9的位置不需要换,因为 349 小于 934 ----> 30、3、1、34、9
这样其实就是一次循环走完,但是发现,这个1,是不是应该放到第一位呢,所以,这样的循环还得再来几次吧,也就是说,我需要两层for循环。
这个过程是不是很眼熟???
冒泡排序!!!
对,就是冒泡,只是两个字符串互换位置的判断逻辑变了,不是简单的比大小,而是要根据两数拼接后的大小,再来调整位置。
所以归根结底就是一个排序问题。
所以怎么去优化算法,也就变成了采用哪种排序算法的问题了?先给出冒泡排序:
class Solution {
public String crackPassword(int[] password) {
String[] strs = new String[password.length];
for(int i = 0; i < password.length; i++){
strs[i] = String.valueOf(password[i]);
}
for(int i = 0; i < strs.length; i++){
for(int j = 0; j < strs.length - 1; j++){
if((strs[j] + strs[j+1]).compareTo(strs[j+1] + strs[j]) > 0){
String temp = strs[j];
strs[j] = strs[j+1];
strs[j+1] = temp;
}
}
}
StringBuilder builder = new StringBuilder();
for(int i = 0; i < strs.length; i++){
builder.append(strs[i]);
}
return builder.toString();
}
}
使用Arrays,sort()并自定义排序规则:
class Solution {
public String crackPassword(int[] password) {
String[] strs = new String[password.length];
for(int i = 0; i < password.length; i++){
strs[i] = String.valueOf(password[i]);
}
//使用Arrays.sort() 并指定排序的规则
Arrays.sort(strs,(a,b) -> (a + b).compareTo(b + a));
StringBuilder builder = new StringBuilder();
for(int i = 0; i < strs.length; i++){
builder.append(strs[i]);
}
return builder.toString();
}
}
使用快速排序
class Solution {
public String crackPassword(int[] password) {
String[] strs = new String[password.length];
// 将数字数组转换成字符串数组
for (int i = 0; i < password.length; i++) {
strs[i] = String.valueOf(password[i]);
}
// 对字符串数组进行快速排序
quickSort(strs, 0, strs.length - 1);
// 构建最终的字符串
StringBuilder builder = new StringBuilder();
for (String s : strs) {
builder.append(s);
}
return builder.toString();
}
// 快速排序函数
private void quickSort(String[] strs, int low, int high) {
if (low < high) {
int pivotIndex = partition(strs, low, high); // 获取基准元素的索引
quickSort(strs, low, pivotIndex - 1); // 对左半部分进行递归排序
quickSort(strs, pivotIndex + 1, high); // 对右半部分进行递归排序
}
}
// 分区函数:选择一个基准元素,将数组分为两部分
private int partition(String[] strs, int low, int high) {
String pivot = strs[high]; // 选择最后一个元素为基准
int i = low - 1; // i 是较小元素的索引
for (int j = low; j < high; j++) {
// 如果当前元素按我们的比较规则小于基准元素,则交换
if ((strs[j] + pivot).compareTo(pivot + strs[j]) < 0) {
i++;
swap(strs, i, j);
}
}
swap(strs, i + 1, high); // 将基准元素放到正确的位置
return i + 1; // 返回基准元素的索引
}
// 交换数组中两个元素
private void swap(String[] strs, int i, int j) {
String temp = strs[i];
strs[i] = strs[j];
strs[j] = temp;
}
}