全网最全面的华为OD机试真题汇总,100%原题题库,不需要开会员即可查看全部内容,更多考题请查看真题库。
真题库:https://www.yuque.com/codernav.com/od
题目:求最大数字
知识点单调栈
时间限制:1s 空间限制:256MB 限定语言:不限
题目描述:
给定一个由纯数字组成以字符串表示的数值,现要求字符串中的每个数字最多只能出现2次,超过的需要进行删除;删除某个重复的数字后,其它数字相对位置保持不变。
如”34533″,数字3重复超过2次,需要删除其中一个3,删除第一个3后获得最大数值”4533″
请返回经过删除操作后的最大的数值,以字符串表示。
输入描述:
第一行为一个纯数字组成的字符串,长度范围:[1,100000]
输出描述:
输出经过删除操作后的最大的数值
示例1
输入:
34533
输出:
4533
示例2
输入:
5445795045
输出:
5479504
解题思路:
根据题意,所有数字不超过2个,对输入的字符串进行去重处理,所有数字最多保留2个
对步骤1处理完的数组进行全排列,同时需要判断排列后的字符串是否为原始字符串的子串,最后求出其中最大值
代码实现一:
package com.codernav.demo.hwod.exam;
import java.util.*;
/**
* @title 求最大数字
* @Description 给定一个由纯数字组成以字符串表示的数值,现要求字符串中的每个数字最多只能出现2次,超过的需要进行删除;删除某个重复的数字后,其它数字相对位置保持不变。
* 如"34533",数字3重复超过2次,需要删除其中一个3,删除第一个3后获得最大数值"4533"
* 请返回经过删除操作后的最大的数值,以字符串表示。
* @Author 开发者导航
* @website https://codernav.com
* @date 2023/5/28
*/
public class Main {
public static List<Integer> resList = new ArrayList<>();
public static String[] inputStrs;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
inputStrs = sc.nextLine().split("");
Map<String, Integer> map = new HashMap<>();
for (int i = 0; i < inputStrs.length; i++) { //求出所有数字的出现次数
map.put(inputStrs[i], map.getOrDefault(inputStrs[i], 0) + 1);
}
List<String> list = new ArrayList<>();
for (Map.Entry<String, Integer> m : map.entrySet()) {
String num = m.getKey();
list.add(num);
if (m.getValue() >= 2) { //次数大于等于2只记两次
list.add(num);
}
}
String[] strsNum = new String[list.size()];
list.toArray(strsNum); //集合转化为数组
combine(strsNum, 0, strsNum.length - 1);
Collections.sort(resList);
System.out.println(resList.get(resList.size() - 1));
}
public static void swap(String[] strings, int indexa, int indexb) {
String temp = strings[indexa];
strings[indexa] = strings[indexb];
strings[indexb] = temp;
}
/**
* 对存在的数字进行全排列,找出其中最大的值
*
* @param strs 存在数字数组
* @param start 进行交换的index
* @param end 数组的最后一个index
*/
public static void combine(String[] strs, int start, int end) {
if (start == end) {
String numStr = "";
for (String s : strs) {
numStr += s; //将数组中的数字进行拼接
}
if (!resList.contains(Integer.valueOf(numStr)) && isChild(strs)) { //剔除满足子串且存在的数字
resList.add(Integer.valueOf(numStr));
}
} else {
for (int i = start; i < strs.length; i++) {
if (i != start && strs[i].equals(strs[start])) { //用来交换的索引不同且数字相等则重复
continue;
}
swap(strs, i, start);
if (strs[0].equals("0")) {
continue; //首位为0不满足
}
combine(strs, start + 1, end);
swap(strs, i, start);
}
}
}
/**
* 判断数组是否为输入数组的子串
*
* @param child
* @return
*/
public static boolean isChild(String[] child) {
int index = 0; //父数组索引
boolean isOver = false; //父数组是否遍历结束
int count = 0;
for (int i = 0; i < child.length; i++) {
String str = child[i];
for (int j = index; j < inputStrs.length; j++) {
String temp = inputStrs[j];
if (j == inputStrs.length - 1) {
isOver = true; //父数组遍历结束了
}
if (temp.equals(str)) {
index = j + 1; //存在该字符,则更新count
count++;
break;
}
}
if (isOver) { //父数组遍历完成且index没有刷新
break;
}
}
return count == child.length;
}
}
代码实现二:
package com.codernav.demo.hwod.exam;
import java.util.*;
/**
* @title 求最大数字
* @Description 给定一个由纯数字组成以字符串表示的数值,现要求字符串中的每个数字最多只能出现2次,超过的需要进行删除;删除某个重复的数字后,其它数字相对位置保持不变。
* 如"34533",数字3重复超过2次,需要删除其中一个3,删除第一个3后获得最大数值"4533"
* 请返回经过删除操作后的最大的数值,以字符串表示。
* @Author 开发者导航
* @website https://codernav.com
* @date 2023/5/28
*/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
/**
* key:数字
* value:数字出现的次数
*/
Map<Integer, List<Integer>> map = new HashMap<>();
int[] nums = new int[str.length()]; //转化为数组形式
for (int i = 0; i < str.length(); i++) {
List<Integer> tempList = new ArrayList<>();
int num = str.charAt(i) - '0';
nums[i] = num;
if (map.containsKey(num)) {
tempList = map.get(num);
tempList.add(i);
} else {
tempList.add(i);
map.put(num, tempList);
}
}
List<Map.Entry<Integer, List<Integer>>> list = new ArrayList<>();
for (Map.Entry<Integer, List<Integer>> m : map.entrySet()) {
if (m.getValue().size() > 2) { //将出现超过2次的数字放在一个集合中
list.add(m);
}
}
list.sort((a, b) -> {
return a.getKey() - b.getKey();
});
for (Map.Entry<Integer, List<Integer>> m : list) {
handle(m.getValue(), nums);
}
String res = "";
for (int i : nums) {
if (i != -1) {
res += i;
}
}
System.out.println(res);
}
public static void handle(List<Integer> list, int[] nums) {
while (list.size() > 2) {
int index1 = list.get(0);
if (searchNum(nums, index1 + 1) > nums[index1]) {
list.remove(0);
nums[index1] = -1;
continue;
}
int index2 = list.get(1);
if (searchNum(nums, index2 + 1) > nums[index2]) {
list.remove(1);
nums[index2] = -1;
continue;
}
int index3 = list.get(2);
list.remove(2);
nums[index3] = -1;
}
}
public static int searchNum(int[] nums, int index) {
int res = 0;
for (int i = index; i < nums.length; i++) {
if (nums[i] != -1) {
res = nums[i];
break;
}
}
return res;
}
}
代码实现三:满分Java代码实现
package com.codernav.demo.hwod.exam;
import java.util.ArrayList;
import java.util.Scanner;
/**
* @title 求最大数字
* @Description 给定一个由纯数字组成以字符串表示的数值,现要求字符串中的每个数字最多只能出现2次,超过的需要进行删除;删除某个重复的数字后,其它数字相对位置保持不变。
* 如"34533",数字3重复超过2次,需要删除其中一个3,删除第一个3后获得最大数值"4533"
* 请返回经过删除操作后的最大的数值,以字符串表示。
* @Author 开发者导航
* @website https://codernav.com
* @date 2023/5/28
*/
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
int n = str.length();
//输入数字的数组
int[] nums = new int[n];
//输入数字的各位数的个数
int[] countNum = new int[10];
//新组成的数字的各位数的个数
int[] usedNum = new int[10];
for (int i = 0; i < n; ++i) {
nums[i] = str.charAt(i) - '0';
countNum[nums[i]]++;
}
//新组成的数字各数
ArrayList<Integer> resList = new ArrayList<>();
for (int num : nums) {
if (usedNum[num] == 2) {
countNum[num]--;
continue;
}
int lastIndex = resList.size() - 1;
//与前面一个数进行比较,如果这个数大于前一个数且前一个数的数量大于2,则将前一个数移除;(让较大的数排在前面)
while (lastIndex >= 0 && num > resList.get(lastIndex) && countNum[resList.get(lastIndex)] > 2) {
usedNum[resList.get(lastIndex)]--;
countNum[resList.get(lastIndex)]--;
resList.remove(lastIndex);
lastIndex = resList.size() - 1;
}
resList.add(num);
usedNum[num]++;
}
for (int x : resList) {
System.out.print(x);
}
}
}
© 版权声明
文章版权归作者所有,未经允许请勿转载。
相关文章
暂无评论...
