给定一个由两个正整数L和R表示的范围。找到该范围内具有数字最大乘积的数字。
例子:
Input : L = 1, R = 10
Output : 9
Input : L = 51, R = 62
Output : 59
方法:此处的关键思想是从最高有效数字开始对数字R的数字进行迭代。从左到右,即从最高有效数字到最低有效数字,用比当前数字少一位代替当前数字,并将数字中当前数字之后的所有数字替换为9,因为数字已经小于R在当前位置,因此我们可以安全地在以下数字中放置任何数字,以最大程度地增加数字乘积。另外,检查结果数是否大于L以保持在该范围内并更新最大乘积。
下面是上述方法的实现:
C++
// CPP Program to find the number in a
// range having maximum product of the
// digits
#include
using namespace std;
// Returns the product of digits of number x
int product(int x)
{
int prod = 1;
while (x) {
prod *= (x % 10);
x /= 10;
}
return prod;
}
// This function returns the number having
// maximum product of the digits
int findNumber(int l, int r)
{
// Converting both integers to strings
string a = to_string(l);
string b = to_string(r);
// Let the current answer be r
int ans = r;
for (int i = 0; i < b.size(); i++) {
if (b[i] == '0')
continue;
// Stores the current number having
// current digit one less than current
// digit in b
string curr = b;
curr[i] = ((curr[i] - '0') - 1) + '0';
// Replace all following digits with 9
// to maximise the product
for (int j = i + 1; j < curr.size(); j++)
curr[j] = '9';
// Convert string to number
int num = 0;
for (auto c : curr)
num = num * 10 + (c - '0');
// Check if it lies in range and its product
// is greater than max product
if (num >= l && product(ans) < product(num))
ans = num;
}
return ans;
}
// Driver Code
int main()
{
int l = 1, r = 10;
cout << findNumber(l, r) << endl;
l = 51, r = 62;
cout << findNumber(l, r) << endl;
return 0;
}
Java
// Java Program to find the number in a
// range having maximum product of the
// digits
class GFG
{
// Returns the product of digits of number x
static int product(int x)
{
int prod = 1;
while (x > 0)
{
prod *= (x % 10);
x /= 10;
}
return prod;
}
// This function returns the number having
// maximum product of the digits
static int findNumber(int l, int r)
{
// Converting both integers to strings
//string a = l.ToString();
String b = Integer.toString(r);
// Let the current answer be r
int ans = r;
for (int i = 0; i < b.length(); i++)
{
if (b.charAt(i) == '0')
continue;
// Stores the current number having
// current digit one less than current
// digit in b
char[] curr = b.toCharArray();
curr[i] = (char)(((int)(curr[i] -
(int)'0') - 1) + (int)('0'));
// Replace all following digits with 9
// to maximise the product
for (int j = i + 1; j < curr.length; j++)
curr[j] = '9';
// Convert string to number
int num = 0;
for (int j = 0; j < curr.length; j++)
num = num * 10 + (curr[j] - '0');
// Check if it lies in range and its product
// is greater than max product
if (num >= l && product(ans) < product(num))
ans = num;
}
return ans;
}
// Driver Code
public static void main (String[] args)
{
int l = 1, r = 10;
System.out.println(findNumber(l, r));
l = 51;
r = 62;
System.out.println(findNumber(l, r));
}
}
// This code is contributed by chandan_jnu
Python3
# Python3 Program to find the number
# in a range having maximum product
# of the digits
# Returns the product of digits
# of number x
def product(x) :
prod = 1
while (x) :
prod *= (x % 10)
x //= 10;
return prod
# This function returns the number having
# maximum product of the digits
def findNumber(l, r) :
# Converting both integers to strings
a = str(l);
b = str(r);
# Let the current answer be r
ans = r
for i in range(len(b)) :
if (b[i] == '0') :
continue
# Stores the current number having
# current digit one less than current
# digit in b
curr = list(b)
curr[i] = str(((ord(curr[i]) -
ord('0')) - 1) + ord('0'))
# Replace all following digits with 9
# to maximise the product
for j in range(i + 1, len(curr)) :
curr[j] = str(ord('9'))
# Convert string to number
num = 0
for c in curr :
num = num * 10 + (int(c) - ord('0'))
# Check if it lies in range and its
# product is greater than max product
if (num >= l and product(ans) < product(num)) :
ans = num
return ans
# Driver Code
if __name__ == "__main__" :
l, r = 1, 10
print(findNumber(l, r))
l, r = 51, 62
print(findNumber(l, r))
# This code is contributed by Ryuga
C#
// C# Program to find the number in a
// range having maximum product of the
// digits
using System;
class GFG
{
// Returns the product of digits of number x
static int product(int x)
{
int prod = 1;
while (x > 0)
{
prod *= (x % 10);
x /= 10;
}
return prod;
}
// This function returns the number having
// maximum product of the digits
static int findNumber(int l, int r)
{
// Converting both integers to strings
//string a = l.ToString();
string b = r.ToString();
// Let the current answer be r
int ans = r;
for (int i = 0; i < b.Length; i++)
{
if (b[i] == '0')
continue;
// Stores the current number having
// current digit one less than current
// digit in b
char[] curr = b.ToCharArray();
curr[i] = (char)(((int)(curr[i] -
(int)'0') - 1) + (int)('0'));
// Replace all following digits with 9
// to maximise the product
for (int j = i + 1; j < curr.Length; j++)
curr[j] = '9';
// Convert string to number
int num = 0;
for (int j = 0; j < curr.Length; j++)
num = num * 10 + (curr[j] - '0');
// Check if it lies in range and its product
// is greater than max product
if (num >= l && product(ans) < product(num))
ans = num;
}
return ans;
}
// Driver Code
static void Main()
{
int l = 1, r = 10;
Console.WriteLine(findNumber(l, r));
l = 51;
r = 62;
Console.WriteLine(findNumber(l, r));
}
}
// This code is contributed by chandan_jnu
PHP
= $l and
product($ans) < product($num))
$ans = $num;
}
return $ans;
}
// Driver Code
$l = 1;
$r = 10;
print(findNumber($l, $r) . "\n");
$l = 51;
$r = 62;
print(findNumber($l, $r));
// This code is contributed
// by chandan_jnu
?>
C++
// CPP program for the above approach
#include
using namespace std;
#define int long long int
// pair of array to store product and number
// dp[pos][tight1][tight2][start]
pair dp[20][2][2][2];
pair recur(string l, string r, int pos, int ta,
int tb, int st)
{
// Base case if pos is equal
// to l or r size return
// pair{1,""}
if (pos == l.size()) {
return { 1, "" };
}
// look up condition
if (dp[pos][ta][tb][st].first != -1)
return dp[pos][ta][tb][st];
// Lower bound condition
int start = ta ? l[pos] - '0' : 0;
// Upper bound condition
int end = tb ? r[pos] - '0' : 9;
// To store the maximum product
// initially its is set to -1
int ans = -1;
// To store the corresponding
// number as number is large
// so store it as a string
string s = "";
for (int i = start; i <= end; i++) {
// Multiply with this val
int val = i;
// check for leading zeroes as 00005
if (st == 0 and i == 0) {
val = 1;
}
// Recursive call for next
// position and store it in
// a pair pair first gives
// maximum product pair
// second gives number which
// gave maximum product
pair temp
= recur(l, r, pos + 1, ta & (i == start),
tb & (i == end), st | i > 0);
// check if calculated product is greater than
// previous calculated ans
if (temp.first * val > ans) {
ans = temp.first * val;
// update string only if no leading zeroes
// becoz no use to append the leading zeroes
if (i == 0 and st == 0) {
s = temp.second;
}
else {
s = temp.second;
s.push_back('0' + i);
}
}
}
// while returning memoize the ans
return dp[pos][ta][tb][st] = { ans, s };
}
pair solve(int a, int b)
{
// convert int l to sting L and int r to string R ,
// as integer value should be large
string L = to_string(a);
string R = to_string(b);
// to make the size of strings
// equal append zeroes in
// front of string L
if (L.size() < R.size()) {
reverse(L.begin(), L.end());
while (L.size() < R.size()) {
L.push_back('0');
}
reverse(L.begin(), L.end());
}
// initialize dp
// as it is pair of array so memset will not work
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
for (int l = 0; l < 2; l++) {
dp[i][j][k][l].first = -1;
}
}
}
}
// as we have to return pair second value
// it's that number which gaves mximum product
// initally pos=0,ta=1,tb=1,start=0(becoz number is not
// started yet)
pair ans = recur(L, R, 0, 1, 1, 0);
// reverse it becoz we were appending from right to left
// in recursive call
reverse(ans.second.begin(), ans.second.end());
return { ans.first, ans.second };
}
signed main()
{
// take l and r as input
int l = 52, r = 62;
cout << "l= " << l << "\n";
cout << "r= " << r << "\n";
pair ans = solve(l, r);
cout << "Maximum Product: " << ans.first << "\n";
cout << "Number which gave maximum product: "
<< ans.second;
return 0;
}
输出:
9
59
时间复杂度:O(18 * 18),如果我们要处理的数字最大为10 18 。
另一种方法:可以使用Digit Dp解决
观察要点:
1.据我们所知,我们使用紧缩数字dp来检查该数字的范围是否受到限制,同样,在这里,我们将使用紧缩ta和紧缩tb (基本上是两个紧缩条件),其中ta会告诉我们
数字和tb的lower_bound会告诉我们数字的upper_bound ,使用两个紧密值的原因是我们必须计算最大乘积,可能是这样的:
max(l,r)≠max(r)– max(l-1) ,我们的整数应在从l到r的范围内。
2.假设范围值分别为l = 5和r = 15,因此要使大小相等,我们应在转换为字符串后在数字前附加零,并在计算答案时注意前导零,
Dp状态包括:-
1)位置
- 它会从整数的左方告诉索引的位置
2)
- 它代表数字的下界,我们必须确保数字应大于或等于{l}
- 假设我们正在构建一个大于0055的数字,并且创建了一个类似于005的序列,那么在第4位,我们不能放置小于5的数字,而该数字只能介于5到9之间。因此,进行检查这个界限,我们需要ta。
Example : Consider the value of l = 005
Index : 0 1 2
digits : 0 0 5
valid numbers like: 005,006,007,008...
invalid numbers like: ...001,002,003,004
3)待定
- 数字的上限,我们必须确保数字应小于或等于{r}
- 再次假设我们正在构建一个小于526的数字,并且创建了一个类似52的序列,因此在第3位,我们不能放置大于6的数字,而只能在0到6之间放置。检查这个界限,我们需要TB
Example : Consider the value of r = 150
Index : 0 1 2
digits : 1 5 0
valid numbers like: ...148,149,150
invalid numbers like: 151,152,153...
4)圣
- 用于检查前导零(从005〜5)
3.约束:l和r(1≤l≤r≤10 ^ 18)
算法:
- 我们将根据紧缩ta和紧缩tb从头到尾遍历i,如下所示:
start = ta == 1 ? l[ pos ] - '0' : 0;
end = tb ==1 ? r[ pos ] -'0' : 9;
- 首先,我们将检查前导零为:
if ( st == 0 and i = 0) then multiply with 1,else multiply with i
- 对于每个位置,我们将计算序列的乘积并检查是否为最大乘积,并存储相应的数字
int ans = 0;
for(int i = start; i <= end; i++){
int val = i;
if (st==0 and i==0) val = 1;
ans = max (ans, val * solve (pos+1, ta&(i==start),tb&(i==end) ,st|i>0);
}
C++实现:
C++
// CPP program for the above approach
#include
using namespace std;
#define int long long int
// pair of array to store product and number
// dp[pos][tight1][tight2][start]
pair dp[20][2][2][2];
pair recur(string l, string r, int pos, int ta,
int tb, int st)
{
// Base case if pos is equal
// to l or r size return
// pair{1,""}
if (pos == l.size()) {
return { 1, "" };
}
// look up condition
if (dp[pos][ta][tb][st].first != -1)
return dp[pos][ta][tb][st];
// Lower bound condition
int start = ta ? l[pos] - '0' : 0;
// Upper bound condition
int end = tb ? r[pos] - '0' : 9;
// To store the maximum product
// initially its is set to -1
int ans = -1;
// To store the corresponding
// number as number is large
// so store it as a string
string s = "";
for (int i = start; i <= end; i++) {
// Multiply with this val
int val = i;
// check for leading zeroes as 00005
if (st == 0 and i == 0) {
val = 1;
}
// Recursive call for next
// position and store it in
// a pair pair first gives
// maximum product pair
// second gives number which
// gave maximum product
pair temp
= recur(l, r, pos + 1, ta & (i == start),
tb & (i == end), st | i > 0);
// check if calculated product is greater than
// previous calculated ans
if (temp.first * val > ans) {
ans = temp.first * val;
// update string only if no leading zeroes
// becoz no use to append the leading zeroes
if (i == 0 and st == 0) {
s = temp.second;
}
else {
s = temp.second;
s.push_back('0' + i);
}
}
}
// while returning memoize the ans
return dp[pos][ta][tb][st] = { ans, s };
}
pair solve(int a, int b)
{
// convert int l to sting L and int r to string R ,
// as integer value should be large
string L = to_string(a);
string R = to_string(b);
// to make the size of strings
// equal append zeroes in
// front of string L
if (L.size() < R.size()) {
reverse(L.begin(), L.end());
while (L.size() < R.size()) {
L.push_back('0');
}
reverse(L.begin(), L.end());
}
// initialize dp
// as it is pair of array so memset will not work
for (int i = 0; i < 20; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 2; k++) {
for (int l = 0; l < 2; l++) {
dp[i][j][k][l].first = -1;
}
}
}
}
// as we have to return pair second value
// it's that number which gaves mximum product
// initally pos=0,ta=1,tb=1,start=0(becoz number is not
// started yet)
pair ans = recur(L, R, 0, 1, 1, 0);
// reverse it becoz we were appending from right to left
// in recursive call
reverse(ans.second.begin(), ans.second.end());
return { ans.first, ans.second };
}
signed main()
{
// take l and r as input
int l = 52, r = 62;
cout << "l= " << l << "\n";
cout << "r= " << r << "\n";
pair ans = solve(l, r);
cout << "Maximum Product: " << ans.first << "\n";
cout << "Number which gave maximum product: "
<< ans.second;
return 0;
}
输出
l= 52
r= 62
Maximum Product: 45
Number which gave maximum product: 59