Skip to content

Commit 964e0a2

Browse files
Create 小于 N 的最大数.md
1 parent d0bd71d commit 964e0a2

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed

Dichotomy/小于 N 的最大数.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
### 题目描述
2+
3+
数组 nums 中给定可以使用的 1 ~ 9 的数,返回由数组 nums 中的元素组成的小于 n 的最大数。元素可以重复使用。
4+
5+
示例 1:nums = {1, 2, 9, 4},n = 2533,返回 2499。
6+
7+
示例 2:nums = {1, 2, 5, 4},n = 2543,返回 2542。
8+
9+
示例 3:nums = {1, 2, 5, 4},n = 2541,返回 2525。
10+
11+
示例 4:nums = {1, 2, 9, 4},n = 2111,返回 1999。
12+
13+
示例 5:nums = {5, 9},n = 5555,返回 999。
14+
15+
---
16+
17+
贪心 + 二分查找:详见注释。
18+
19+
```java
20+
package com.example.demo.test;
21+
22+
23+
// nums = [5, 4, 8, 2], n = 5416, res = 5288
24+
25+
import java.util.Arrays;
26+
27+
28+
public class Solution {
29+
30+
public static void main(String[] args) {
31+
int[] nums = {1,2,5,4};
32+
int n = 2541;
33+
Arrays.sort(nums);
34+
String s = findMin(n, nums[0]);
35+
StringBuilder sb = new StringBuilder();
36+
boolean flag = false;
37+
for(int i = 0; i < s.length(); i++){
38+
/*
39+
每位都找小于等于该位最大的数,如果s这个位置的数大于等于nums的最大值,就用最大值,否则去数组找最接近的
40+
如果当前从数组中找的数字小于s对应这位的数字,此后选择的数字都可以是数组中的最大值
41+
例如2513和{2,4,6,8},选到第二位4之后,4比5小,此后就可以都选择8,组成2488
42+
*/
43+
char c = s.charAt(i);
44+
if(flag){
45+
sb.append(nums[nums.length - 1]);
46+
} else {
47+
int index = getIndex(nums, i, s);
48+
sb.append(nums[index]);
49+
if(nums[index] < c - '0') flag = true;
50+
}
51+
}
52+
System.out.println(sb);
53+
}
54+
55+
public static int getIndex(int[] nums, int index, String s){
56+
int target = s.charAt(index) - '0';
57+
/*
58+
此外,选择数字还要受到下一位数字的影响
59+
假设s为2411,nums为{2,4,6,8}
60+
第二位数字应该选4,但如果选了4,后面再拼接就一定会大于s了。
61+
*/
62+
if(index < s.length() - 1){
63+
int next = s.charAt(index + 1) - '0';
64+
if(next <= nums[0]){
65+
target -= 1;
66+
}
67+
}
68+
return dichotomy(nums, target);
69+
}
70+
71+
72+
/**
73+
* 二分查找,查找小于等于target的最大下标。
74+
* @param nums
75+
* @param target
76+
* @return
77+
*/
78+
public static int dichotomy(int[] nums, int target){
79+
int left = 0, right = nums.length;
80+
while(left < right){
81+
int mid = (left + right) / 2;
82+
if(nums[mid] < target){
83+
left = mid + 1;
84+
} else if(nums[mid] > target){
85+
right = mid;
86+
} else return mid;
87+
}
88+
return left - 1;
89+
}
90+
91+
/**
92+
* 判断是否能拼出和 n 长度一样的字符串,通过判断str的第一位与nums[0](minValue)的大小关系,无法判断则迭代判断下一位
93+
* @param n
94+
* @param minValue
95+
* @return
96+
*/
97+
public static String findMin(int n, int minValue){
98+
boolean flag = false;
99+
String numStr = String.valueOf(n);
100+
for(int i = 0; i < numStr.length(); i++){
101+
if(minValue < (numStr.charAt(i) - '0')){
102+
flag = true;
103+
break;
104+
}
105+
}
106+
int maxValue = flag ? (n - 1) : (int)(Math.pow(10, numStr.length() - 1) - 1);
107+
return String.valueOf(maxValue);
108+
}
109+
}
110+
111+
```

0 commit comments

Comments
 (0)