【问题标题】:Roman to Integer in JS why it only convert the first characterJS中的Roman to Integer为什么只转换第一个字符
【发布时间】:2018-09-14 12:42:14
【问题描述】:

我尝试解决 Leedcode 问题 13,问题是给定一个罗马数字,将其转换为整数。(输入保证在 1 到 3999 的范围内。) 这是我下面的代码,我想知道为什么它只将罗马数字中的第一个字符转换为整数?

var romanToInt = function(s) {
  var result = 0;
  if (s == null) {
    result = 0;
  }
  var myMap = new Map();
  myMap.set('I', 1);
  myMap.set('V', 5);
  myMap.set('X', 10);
  myMap.set('L', 50);
  myMap.set('C', 100);
  myMap.set('D', 500);
  myMap.set('M', 1000);

  var len = s.length;
  for (var i = 0; i < len; i++) {
    if (myMap.get(s.charAt(i)) < myMap.get(s.charAt(i + 1))) {
      result -= myMap.get(s.charAt(i))
    } else {
      result += myMap.get(s.charAt(i))
    }
    return result;
  };
}

console.log(romanToInt('VI'));
console.log(romanToInt('V'));
console.log(romanToInt('VII'));

【问题讨论】:

  • 顺便说一句,每个函数调用都会重新创建整个 Map。你应该把它移到你的函数之外。
  • @cece 你的逻辑没问题,在循环后面加上“return”语句,因为你计算和返回的时间是同时的。

标签: javascript integer roman-numerals


【解决方案1】:

因为

return result;

在一次迭代后结束循环。将其向下移动一行。如果你会做正确的格式化,你根本不会犯这样的错误;)

const values = new Map([
  ['I', 1],
  ['V', 5],
  ['X', 10]
  /*....*/
]);

function romanToInt(string) {
  let result = 0,
    current, previous = 0;
  for (const char of string.split("").reverse()) {
    current = values.get(char);
    if (current >= previous) {
      result += current;
    } else {
      result -= current;
    }
    previous = current;
  }
  return result;
}

console.log(romanToInt('I'));
console.log(romanToInt('II'));
console.log(romanToInt('III'));
console.log(romanToInt('IV'));
console.log(romanToInt('V'));
console.log(romanToInt('VI'));
console.log(romanToInt('VII'));
console.log(romanToInt('VIII'));
console.log(romanToInt('IX'));
console.log(romanToInt('X'));
console.log(romanToInt('XI'));
console.log(romanToInt('XII'));
console.log(romanToInt('XIII'));
console.log(romanToInt('XIV'));
console.log(romanToInt('XV'));
console.log(romanToInt('XVI'));
console.log(romanToInt('XVII'));
console.log(romanToInt('XVIII'));
console.log(romanToInt('XIX'));
console.log(romanToInt('XX'));

【讨论】:

  • 哈哈,这是一个不错的收获:)
  • @cece 如果您的问题得到解决,请不要忘记标记答案?
  • string.reverse()???即使我们解决了这个问题,结果也不会正确。发帖前你试过了吗?
  • 感谢您提醒我!@NielsNet
  • 你修复了string.reverse(),但逻辑仍然不正确,会给出错误的结果:(。
【解决方案2】:

因为您的return result; 在循环内,所以只需将return result; 移动到循环外即可。

以下是您的代码的简化(可读性)版本。

const myMap=new Map();
myMap.set('I', 1);
myMap.set('V', 5);
myMap.set('X', 10);
myMap.set('L', 50);
myMap.set('C', 100);
myMap.set('D', 500);
myMap.set('M', 1000);

var romanToInt = function(s) {
   var result=0;
   if(s){
     var s1=s.split('');
     s1.forEach(function(e,i){
          result += myMap.get(e) < myMap.get(s1[i+1]) ? -myMap.get(e) : myMap.get(e);  // used ternary oprator with '-' where required
     });
   }
   return result; //move it outside loop
}
console.log(romanToInt('IV'));
console.log(romanToInt('V'));
console.log(romanToInt('VII'));

【讨论】:

    【解决方案3】:

    Roman to Integer的较短版本:

    var romanToInt = (str) => {
      const roman = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000 };
      let num = 0;
      for (let i = 0; i < str.length; i++) {
        const curr = roman[str[i]];
        const next = roman[str[i + 1]];
        (curr < next) ? (num -= curr) : (num += curr);
      }
      return num;
    };
    
    console.log(romanToInt('IV'));
    console.log(romanToInt('VIII'));
    console.log(romanToInt('LXXIX'));
    console.log(romanToInt('MCMXLIV'));

    @Jin150Job 的另一个独特解决方案

    var romanToInt = (str) => {
      const roman = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000 };
      let num = 0;
      if (str.includes('CM')) num -= 200;
      if (str.includes('CD')) num -= 200;
      if (str.includes('XC')) num -= 20;
      if (str.includes('XL')) num -= 20;
      if (str.includes('IX')) num -= 2;
      if (str.includes('IV')) num -= 2;
      for (var i = 0; i < str.length; i++) {
        num += roman[str[i]];
      }
      return num;
    };
    
    console.log(romanToInt('IV'));
    console.log(romanToInt('VIII'));
    console.log(romanToInt('LXXIX'));
    console.log(romanToInt('MCMXLIV'));

    【讨论】:

      【解决方案4】:

      对此解决方案的一个不错且更可取的答案是:

        let roman = "XXI";
        const numeral = {I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000};
        let total = 0;
        let current, last = 0;
        roman.split("").reverse().forEach(e => {
          current = numeral[e];
          if (current >= last) {total += current;} else {total -= current;}
          last = current;
        });
        
        return total;
      

      【讨论】:

        【解决方案5】:

        这是查找罗马数字的整数的另一种解决方案

        function romanToInt(romanNumber) {
           let currentValue = 0;
            let result = 0;
            const string = romanNumber.split('');
            const romanNumbers = {
              I: 1,
              V: 5,
              X: 10,
              L: 50,
              C: 100,
              D: 500,
              M: 1000,
            };
            let firstNum = romanNumbers[string[0].toUpperCase()];
            for (let char of string) {
              currentValue = romanNumbers[char.toUpperCase()];
              if (currentValue <= firstNum) {
                result += currentValue;
              } else {
                result = currentValue - result;
              }
            }
            console.log(`Roman: ${romanNumber}\nInteger: ${result} \n \n`);
            return result;
        }
        
        romanToInt('I');
        romanToInt('IV');
        romanToInt('VI');
        romanToInt('IX');
        romanToInt('X');
        romanToInt('XI');
        romanToInt('XII');
        romanToInt('XL');
        romanToInt('LV');
        romanToInt('MMM');
        romanToInt('MMC');
        romanToInt('MMc');

        【讨论】:

          【解决方案6】:

          也许你可以试试:

          function romanToInt(romanString) {
             if(typeof romanString !== 'string') return NaN;
             const romanRegExp = /^(?=[MDCLXVI])(M*)(?:(C)(?:(D)|(M))|(D?)(C{0,3}))(?:(X)(?:(L)|(C))|(L?)(X{0,3}))(?:(I)(?:(V)|(X))|(V?)(I{0,3}))$/i;
             let parts = romanString.match(romanRegExp);
             if(!parts) return NaN;
             let result = 0;
             [0, 1000, -100,500,1000,500,100, -10,50,100,50,10, -1,5,10,5,1].forEach(
                (weight, i) => result += weight * (parts[i] || '').length
             );
             return result;
          }
          
          console.log(romanToInt('IV'));
          console.log(romanToInt('MMXIX'));

          【讨论】:

            【解决方案7】:

            试试这个。它应该工作:

            
            
            function conversion(r) {
              const arr = r.split('');
              const val = {
                I: 1,
                V: 5,
                X: 10,
                L: 50,
                C: 100,
                D: 500,
                M: 1000,
              };
            
              let sum = 0;
              for (let i = 0; i < arr.length; i += 1) {
                if (val[arr[i]] < val[arr[i + 1]]) {
                  sum += val[arr[i + 1]] - val[arr[i]];
                  i += 1;
                } else {
                  sum += val[arr[i]];
                }
              } return sum;
            }
                  
            console.log(conversion("VIII"));
            console.log(conversion("LXXIX"));
            console.log(conversion("MCMXLIV"));

            【讨论】:

              【解决方案8】:

              ** 此解决方案适用于每个罗马数字

              function romanToInt(romeNumStr) {
                  const romeMap = {I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000};
                  let total = 0;
                  for (let i=0; i<romeNumStr.length; i++) {
                      const chVal = romeMap[romeNumStr[i]];
                      let chNextVal
                      if (i+1 < romeNumStr.length) {
                          // There is more chars
                          chNextVal = romeMap[romeNumStr[i+1]];
                          if (chVal >= chNextVal) {
                              total += chVal;
                          } else {
                              // Do reverse
                              total += chNextVal-chVal
                              i+=1
                          }
                      } else {
                          // Last char
                          total += chVal;
                      }
                  }
                  return total
              }
              

              我的测试:

              // TEST
              romanToInt('MMMDXCIX')
              =3599
              

              【讨论】:

                【解决方案9】:

                这是使用reduce的一个

                const romanNumerals = {
                  I: 1,
                  V: 5,
                  X: 10,
                  L: 50,
                  C: 100,
                  D: 500,
                  M: 1000,
                }
                
                const convertToNumber = romanNumeral => {
                  const romanDigits = romanNumeral.split('')
                
                  return romanDigits.reduce(
                    (acc, curr, index) =>
                      romanNumerals[curr] < romanNumerals[romanDigits[index + 1]]
                        ? acc - romanNumerals[curr]
                        : acc + romanNumerals[curr],
                    0
                  )
                }
                
                console.log(convertToNumber('XXXIX'))
                console.log(convertToNumber('XL'))
                console.log(convertToNumber('MMXXI'))
                console.log(convertToNumber('CLX'))
                console.log(convertToNumber('DCCLXXXIX'))
                console.log(convertToNumber('MCMXVIII'))
                console.log(convertToNumber('MMMCMXCIX'))

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2022-12-20
                  • 2023-03-30
                  • 2021-05-26
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-01-28
                  • 2015-04-25
                  相关资源
                  最近更新 更多