![](/img/trans.png)
[英]Find the number of times a number is repeated in an array in less than O(n^2)
[英]how to find maximum number M less than N in which some specific digit is not allowed to exist in Java
最近,我遇到了一個采訪編程問題,關於如何找到小於N的最大數M,並且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');
}
可能存在更智能和有效的方法。
嘗試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;
}
我使用的技巧是找到正確的數字以從原始數字中減去,並最大化剩余的數字。 通常,這只是一個數字,第一個不良數字位置為1,但是如果將被禁止的數字設為0,則比較棘手,因為當減法進行下去時,它可以產生更多的0。 當一串數字(如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));
}
}
它打印:
19
199
123
119
999
999
999999
999999
80000008
80888888
編輯:修復了JoJo指出的拐角案例。
我認為可以,請告訴我是否有任何處理不當的案件。
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;
}
編輯:
我最終決定使用字符串來處理digit = 0
的情況,這與我的第一種方法相當復雜。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.