如何找到Java中不允许存在某个特定数字的小于N的最大数M

如何找到Java中不允许存在某个特定数字的小于N的最大数M,java,string,algorithm,Java,String,Algorithm,最近我得到了一个采访编程问题,关于如何找到最大数M小于N,并且一些特定的数字不允许存在于M中 例如,N=123,digit=2,那么它将输出:119 我的想法是先把N转换成字符串,然后从左到右找到数字的第一个位置,使这个数字减少1。然后我将N中的所有剩余数字设置为9,使这个数字最大化。是否有人能指出一些我忽略的角落案例?这个问题是否有一些很好的Java实现可供参考 。。。首先将N转换为字符串,然后从左到右找到数字的第一个位置,使该数字减少1 这似乎很难。您如何“找到使数字减少的位置” 为什么不采

最近我得到了一个采访编程问题,关于如何找到最大数M小于N,并且一些特定的数字不允许存在于M中

例如,N=123,digit=2,那么它将输出:119

我的想法是先把N转换成字符串,然后从左到右找到数字的第一个位置,使这个数字减少1。然后我将N中的所有剩余数字设置为9,使这个数字最大化。是否有人能指出一些我忽略的角落案例?这个问题是否有一些很好的Java实现可供参考

。。。首先将N转换为字符串,然后从左到右找到数字的第一个位置,使该数字减少1

这似乎很难。您如何“找到使数字减少的位置”

为什么不采用更为暴力的方法:将数字保留为一个数字,逐个减少,转换为字符串以查找数字是否存在,例如:

public int getMaxN(int N, char digit) {
    for (int i = N; i > 0; --i) {
        if (Integer.toString(i).indexOf(digit) == -1) {
            return i;
        }
    }
    throw new NoSuchElementException();
}

@Test
public void testGetMaxN() {
    assertEquals(119, getMaxN(123, '2'));
    assertEquals(122, getMaxN(123, '3'));
    assertEquals(99, getMaxN(123, '1'));
}

@Test(expected = NoSuchElementException.class)
public void testNoSuchElement() {
    getMaxN(0, '0');
}

可能存在一种更智能、更高效的方法。

我认为它有效,如果您发现任何案件处理不当,请告诉我

public static void main(String[] args) {
    int N     = 100211020;
    int digit = 0;

    int m;
    for (m = 9 ; m > 0 && m == digit; m--);

    String sres;
    String s   = N + "";
    int length = s.length();
    int i      = s.indexOf(digit + "");

    if (i < 0)
        sres = s;
    else {
        StringBuilder sb = new StringBuilder();
        if (digit != 0) {
            for (int j=0 ; j<i ; j++) sb.append(s.charAt(j));
            sb.append(digit - 1);
            for (int j=i + 1 ; j<length ; j++) sb.append(m);
        } else {
            if (s.charAt(0) != '1')
                sb.append(mod10(s.charAt(0) - '0' - 1));
            for (int j=1 ; j<length ; j++) sb.append(9);            
        }
        sres = sb.toString();
    }
    System.out.println(sres);
}

public static int mod10(int n) {
    int res = n % 10;
    return res < 0 ? res + 10 : res;
}
publicstaticvoidmain(字符串[]args){
int N=100211020;
整数位数=0;
int m;
对于(m=9;m>0&&m==digit;m--);
字符串sres;
字符串s=N+“”;
int length=s.length();
int i=s.indexOf(数字+“”);
if(i<0)
sres=s;
否则{
StringBuilder sb=新的StringBuilder();
如果(数字!=0){
对于(int j=0;j尝试3。仍然为O(n),但由于特殊的0情况需要级联备份:

static int banDigit(int number, int digit) {
    int length = (Integer.toString(number)).length();
    int result = 0;
    boolean foundDigit = false;
    for (int i = length - 1; i >= 0; i--) {
        if (!foundDigit) {
            int currentDigit = (int) number / ((int) Math.pow(10, i));
            number = number % (int) Math.pow(10, i);
            if (currentDigit == digit) {
                //if nonzero digit banned, we can just decrement and purge 9 or 8 to right
                if (digit > 0) {
                    currentDigit--;
                } else {
                    // we have to subtract one from the previous 
                    result = result - (int) Math.pow(10, i);
                    //then we have to check if doing that caused a bunch of ones prior
                    for (int j = i + 1; j < length; j++) {
                        if ((int) (result % (int) Math.pow(10, j + 1)) / (int) Math.pow(10, j) == 0) {
                            result = result - (int) Math.pow(10, j);
                        }
                    }
                }
                foundDigit = true;
            }
            result += currentDigit * Math.pow(10, i);
        } else if (digit == 9) {
            result += 8 * Math.pow(10, i);
        } else {
            result += 9 * Math.pow(10, i);
        }
    }
    return result;
}
static int banDigit(整数、整数位数){
int length=(Integer.toString(number)).length();
int结果=0;
布尔数字=假;
对于(int i=length-1;i>=0;i--){
如果(!foundDigit){
int currentDigit=(int)number/((int)Math.pow(10,i));
数字=数字%(整数)数学功率(10,i);
如果(当前位数==位数){
//如果非零位被禁止,我们可以将9或8减到右边
如果(数字>0){
当前数字--;
}否则{
//我们必须从先前的数据中减去一个
结果=结果-(int)数学功率(10,i);
//然后,我们必须检查这样做是否导致了之前的一系列错误
对于(int j=i+1;j
我使用的技巧是从原始数字中找出正确的数字进行减法,并将剩余的数字最大化。这通常只是一个在第一个坏数字位置有1的数字,但如果禁止的数字为0,则会有点棘手,因为减法进行时会产生更多的0。当有str时会发生这种情况像1110这样的数字,在0之前加1。我的程序在这个O(n)时间解决方案中跟踪这些数字,其中n是位数

import java.math.BigInteger;
import java.util.Arrays;

public class RemoveDigits {

  public static BigInteger removeDigits(BigInteger number, int banned) {
    char[] digits = number.toString().toCharArray(); // digits of the number
    char[] subtractChars = null; // array used to initialize BigInteger to subtract from the bad digit
    char maxDigit = banned == 9 ? '8' : '9'; // digit to fill rest of the number with
    int badCarryIndex = -1; // if banned == 0 keep track of the carry possibility
    int badDigitIndex = -1;
    for (int i = 0; i < digits.length; i++) {
      if (banned == 0 && digits[i] == '1') { // keep track of first character affected by carry
        if (badCarryIndex < 0) {
          badCarryIndex = i;
        }
      } else if (Character.digit(digits[i], 10) == banned) {
        badDigitIndex = i;
        if (badCarryIndex != 0) { // calculate the real first character affected by carry
          badCarryIndex--;
        }
        subtractChars = badCarryIndex < 0 ? new char[digits.length - badDigitIndex] : new char[digits.length - badCarryIndex - 1];
        subtractChars[0] = '1';
        break;
      } else { // reset if found a good character
        badCarryIndex = -1;
      }
    }
    if (badDigitIndex >= 0) {
      // fill the rest of the digits with maxDigit
      Arrays.fill(digits, badDigitIndex + 1, digits.length, maxDigit);
      // build subtractChars
      if (badCarryIndex >= 0) {
        // banned == 0, have to worry about carry producing 0's
        Arrays.fill(subtractChars, 1, badDigitIndex - badCarryIndex, '1');
        Arrays.fill(subtractChars, badDigitIndex - badCarryIndex, subtractChars.length, '0');
      } else {
        Arrays.fill(subtractChars, 1, subtractChars.length, '0');
      }
      BigInteger maxedNumber = new BigInteger(new String(digits));
      BigInteger subtractNumber = new BigInteger(new String(subtractChars));
      return maxedNumber.subtract(subtractNumber);
    }
    return number; // no bad digits in original number
  }

  public static void main(String[] args) {
    System.out.println(removeDigits(new BigInteger("20"), 0));
    System.out.println(removeDigits(new BigInteger("210"), 0));
    System.out.println(removeDigits(new BigInteger("123"), 0));
    System.out.println(removeDigits(new BigInteger("123"), 2));
    System.out.println(removeDigits(new BigInteger("1000"), 0));
    System.out.println(removeDigits(new BigInteger("1000"), 1));
    System.out.println(removeDigits(new BigInteger("1111020"), 0));
    System.out.println(removeDigits(new BigInteger("2011020"), 0));
    System.out.println(removeDigits(new BigInteger("80000009"), 9));
    System.out.println(removeDigits(new BigInteger("80937921"), 9));
  }
}
import java.math.biginger;
导入java.util.array;
公共类迁移者{
公共静态BigInteger removeDigits(BigInteger数字,禁止整数){
char[]digits=number.toString().toCharray();//数字的位数
char[]subtractChars=null;//用于初始化要从错误数字中减去的BigInteger的数组
char maxDigit=banked==9?'8':'9';//用于填充数字其余部分的数字
int badCarryIndex=-1;//如果禁用==0,跟踪进位可能性
int-badDigitIndex=-1;
对于(int i=0;i=0){
//用maxDigit填充其余数字
数组.fill(数字,badDigitIndex+1,数字.length,maxDigit);
//建立一个新的角色
如果(badCarryIndex>=0){
//禁止==0,必须担心产生0的进位
填充(减法字符,1,badDigitIndex-badCarryIndex,'1');
数组.fill(subtractChars,badDigitIndex-badCarryIndex,subtractChars.length,'0');
}否则{
数组.fill(subtractChars,1,subtractChars.length,'0');
}
BigInteger maxedNumber=新的BigInteger(新字符串(数字));
BigInteger subtractNumber=新的BigInteger(新字符串(subtractChars));
返回maxedNumber.subtract(subtractNumber);
}
返回编号;//原始编号中没有错误数字
}
公共静态void main(字符串[]args){
System.out.println(removeDigits(新的大整数(“20”),0));
System.out.println(removeDigits(新的大整数(“210”),0));
System.out.println(removeDigits(新的大整数(“123”),0));
System.out.println(removeDigits(新的大整数(“123”),2));
System.out.println(removeDigits(新的大整数(“1000”),0));
System.out.println(删除数字